diff options
author | brianp <brianp> | 2000-06-07 16:06:39 +0000 |
---|---|---|
committer | brianp <brianp> | 2000-06-07 16:06:39 +0000 |
commit | d374f65d7bc9591d7a431b682ef20f4001120eee (patch) | |
tree | 9f59163fb0eb27d2d68a8c454e2acaaf4c4e3b64 | |
parent | 24bd6ba6296ab8c6e812875e9fcd0ed24eecf9d3 (diff) |
merge from trunkglxmisc-3-0-0-20000607
208 files changed, 35610 insertions, 3745 deletions
diff --git a/xc/config/cf/FreeBSD.cf b/xc/config/cf/FreeBSD.cf index 1043ed8bf..c92902d37 100644 --- a/xc/config/cf/FreeBSD.cf +++ b/xc/config/cf/FreeBSD.cf @@ -82,7 +82,7 @@ XCOMM operating system: OSName (OSMajorVersion./**/OSMinorVersion./**/OSTeenyVe #if defined(UseInstalled) #define DefaultCCOptions /**/ #else -#define DefaultCCOptions -ansi -pedantic -Dasm=__asm GccWarningOptions +/*#define DefaultCCOptions -ansi -pedantic -Dasm=__asm GccWarningOptions*/ #endif #ifndef ExtraLibraries /* support for multi-byte locales is in libxpg4 rather than libc */ @@ -464,7 +464,7 @@ install.man:: @@\ * A hack to work around an optimisation problem with the compiler on * FreeBSD 4.0-current in late 1999/early 2000. */ -#if OSMajorVersion == 4 && OSMinorVersion == 0 && OSTeenyVersion == 0 +#if (OSMajorVersion == 4 || OSMajorVersion == 5) && OSMinorVersion == 0 && OSTeenyVersion == 0 #define FreeBSDGccOptBug #endif diff --git a/xc/config/cf/host.def b/xc/config/cf/host.def index 8b3406a77..8b164f632 100644 --- a/xc/config/cf/host.def +++ b/xc/config/cf/host.def @@ -1,8 +1,8 @@ -#define ProjectRoot /usr/XF86-glxmisc + #define DefaultGcc2i386Opt -O2 #define LibraryCDebugFlags -O2 #define BuildServersOnly YES -#define XF86CardDrivers vga tdfx i810 mga glint r128 +#define XF86CardDrivers vga tdfx i810 mga r128 #define LinuxDistribution LinuxRedHat #define GccWarningOptions -Wall -Wpointer-arith -Wstrict-prototypes \ -Wmissing-prototypes -Wmissing-declarations \ @@ -17,9 +17,16 @@ /* #define GlxBuiltInTdfx YES */ /* #define GlxBuiltInI810 YES */ /* #define GlxBuiltInMga YES */ +/* #define GlxBuiltInR128 YES */ /* #define DoLoadableServer NO */ -#define SharedLibFont NO +/* Optionally turn this on to change the place where you install the build */ +/* #define ProjectRoot /usr/XF86-main */ + +/* Optionally turn this on to force the kernel modules to build */ +/* #define BuildXF86DRM YES */ + +#define SharedLibFont NO #define XnestServer NO #define XVirtualFramebufferServer NO #define XprtServer NO diff --git a/xc/config/cf/xfree86.cf b/xc/config/cf/xfree86.cf index 77e5e454d..5f5991c77 100644 --- a/xc/config/cf/xfree86.cf +++ b/xc/config/cf/xfree86.cf @@ -512,12 +512,21 @@ IPLAN2P8_DEFS = -DUSE_IPLAN2P8 # ifndef GlxBuiltInTdfx # define GlxBuiltInTdfx NO # endif +# ifndef GlxBuiltInMga +# define GlxBuiltInMga NO +# endif +# ifndef GlxBuiltInI810 +# define GlxBuiltInI810 NO +# endif +# ifndef GlxBuiltInR128 +# define GlxBuiltInR128 NO +# endif -# if GlxBuiltInTdfx +# if GlxBuiltInTdfx || GlxBuiltInMga || GlxBuiltInI810 || GlxBuiltInR128 # define GlxDriverUsesMesa YES # endif -# if GlxBuiltInGamma || GlxBuiltInMesa || GlxBuiltInTdfx +# if GlxBuiltInGamma || GlxBuiltInTdfx || GlxBuiltInMga || GlxBuiltInI810 || GlxBuiltInR128 || GlxBuiltInMesa # define GlxUseBuiltInDRIDriver YES # define DRIDynLoadDefines /**/ # else diff --git a/xc/include/GL/glx.h b/xc/include/GL/glx.h index 367ce0a51..e4712b95f 100644 --- a/xc/include/GL/glx.h +++ b/xc/include/GL/glx.h @@ -1,26 +1,38 @@ #ifndef __GLX_glx_h__ #define __GLX_glx_h__ -/* $XFree86: xc/include/GL/glx.h,v 1.5 2000/03/02 16:07:29 martin Exp $ */ /* -** The contents of this file are subject to the GLX Public License Version 1.0 -** (the "License"). You may not use this file except in compliance with the -** License. You may obtain a copy of the License at Silicon Graphics, Inc., -** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 -** or at http://www.sgi.com/software/opensource/glx/license.html. -** -** Software distributed under the License is distributed on an "AS IS" -** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY -** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR -** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific -** language governing rights and limitations under the License. -** -** The Original Software is GLX version 1.2 source code, released February, -** 1999. The developer of the Original Software is Silicon Graphics, Inc. -** Those portions of the Subject Software created by Silicon Graphics, Inc. -** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. -** -** $SGI$ +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. */ #include <X11/Xlib.h> @@ -39,19 +51,19 @@ extern "C" { typedef XID GLXContextID; typedef XID GLXPixmap; typedef XID GLXDrawable; -/* GLX 1.3 */ -typedef XID GLXFBConfigID; -typedef XID GLXPfuffer; -typedef XID GLXWindow; typedef XID GLXPbuffer; -typedef XID GLXFBConfig; - +typedef XID GLXWindow; +typedef XID GLXFBConfigID; /* ** GLXContext is a pointer to opaque data. -**/ +*/ typedef struct __GLXcontextRec *GLXContext; +/* +** GLXFBConfig is a pointer to opaque data. +*/ +typedef struct __GLXFBConfigRec *GLXFBConfig; /************************************************************************/ @@ -76,34 +88,57 @@ extern const char * glXGetClientString (Display *dpy, int name ); extern const char * glXQueryServerString (Display *dpy, int screen, int name ); extern const char * glXQueryExtensionsString (Display *dpy, int screen ); -/* GLX 1.3 */ -extern GLXFBConfig glXChooseFBConfig (Display *dpy, int screen, const int *attribList, int *nitems); +/* New for GLX 1.3 */ +extern GLXFBConfig * glXGetFBConfigs (Display *dpy, int screen, int *nelements); +extern GLXFBConfig * glXChooseFBConfig (Display *dpy, int screen, const int *attrib_list, int *nelements); extern int glXGetFBConfigAttrib (Display *dpy, GLXFBConfig config, int attribute, int *value); extern XVisualInfo * glXGetVisualFromFBConfig (Display *dpy, GLXFBConfig config); -extern GLXWindow glXCreateWindow (Display *dpy, GLXFBConfig config, Window win, const int *attribList); -extern void glXDestroyWindow (Display *dpy, GLXWindow window); -extern GLXPixmap glXCreatePixmap (Display *dpy, GLXFBConfig config,Pixmap pixmap, const int *attribList); +extern GLXWindow glXCreateWindow (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +extern void glXDestroyWindow (Display *dpy, GLXWindow win); +extern GLXPixmap glXCreatePixmap (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); extern void glXDestroyPixmap (Display *dpy, GLXPixmap pixmap); -extern GLXPbuffer glXCreatePbuffer (Display *dpy, GLXFBConfig config, const int *attribList); +extern GLXPbuffer glXCreatePbuffer (Display *dpy, GLXFBConfig config, const int *attrib_list); extern void glXDestroyPbuffer (Display *dpy, GLXPbuffer pbuf); extern void glXQueryDrawable (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); -extern GLXContext glXCreateNewContext (Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct); -extern Bool glXMakeContextCurrent (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +extern GLXContext glXCreateNewContext (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +extern Bool glXMakeContextCurrent (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); extern GLXDrawable glXGetCurrentReadDrawable (void); +extern Display * glXGetCurrentDisplay (void); extern int glXQueryContext (Display *dpy, GLXContext ctx, int attribute, int *value); -extern void glXSelectEvent (Display *dpy, GLXDrawable drawable, unsigned long mask); -extern void glXGetSelectedEvent (Display *dpy, GLXDrawable drawable, unsigned long *mask); +extern void glXSelectEvent (Display *dpy, GLXDrawable draw, unsigned long event_mask); +extern void glXGetSelectedEvent (Display *dpy, GLXDrawable draw, unsigned long *event_mask); -/* Extensions */ -extern Display * glXGetCurrentDisplay (void); +/*** SGI GLX extensions */ extern GLXContextID glXGetContextIDEXT (const GLXContext ctx); extern GLXDrawable glXGetCurrentDrawableEXT (void); extern GLXContext glXImportContextEXT (Display *dpy, GLXContextID contextID); extern void glXFreeContextEXT (Display *dpy, GLXContext ctx); extern int glXQueryContextInfoEXT (Display *dpy, GLXContext ctx, int attribute, int *value); -extern void (*glXGetProcAddressARB(const GLubyte *procName))(); +extern void (*glXGetProcAddressARB(const GLubyte *procName))( void ); + +/*** Should these go here, or in another header? */ +/* +** GLX Events +*/ +typedef struct { + int event_type; /* GLX_DAMAGED or GLX_SAVED */ + int draw_type; /* GLX_WINDOW or GLX_PBUFFER */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came for SendEvent request */ + Display *display; /* display the event was read from */ + GLXDrawable drawable; /* XID of Drawable */ + unsigned int buffer_mask; /* mask indicating which buffers are affected */ + unsigned int aux_buffer; /* which aux buffer was affected */ + int x, y; + int width, height; + int count; /* if nonzero, at least this many more */ +} GLXPbufferClobberEvent; +typedef union __GLXEvent { + GLXPbufferClobberEvent glxpbufferclobber; + long pad[24]; +} GLXEvent; #ifdef __cplusplus } diff --git a/xc/include/GL/glxtokens.h b/xc/include/GL/glxtokens.h index 5a3e219c3..4efa20a71 100644 --- a/xc/include/GL/glxtokens.h +++ b/xc/include/GL/glxtokens.h @@ -1,26 +1,38 @@ #ifndef __GLX_glxtokens_h__ #define __GLX_glxtokens_h__ -/* $XFree86: xc/include/GL/glxtokens.h,v 1.3 2000/02/15 07:13:24 martin Exp $ */ /* -** The contents of this file are subject to the GLX Public License Version 1.0 -** (the "License"). You may not use this file except in compliance with the -** License. You may obtain a copy of the License at Silicon Graphics, Inc., -** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 -** or at http://www.sgi.com/software/opensource/glx/license.html. -** -** Software distributed under the License is distributed on an "AS IS" -** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY -** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR -** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific -** language governing rights and limitations under the License. -** -** The Original Software is GLX version 1.2 source code, released February, -** 1999. The developer of the Original Software is Silicon Graphics, Inc. -** Those portions of the Subject Software created by Silicon Graphics, Inc. -** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. -** -** $SGI$ +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. */ #ifdef __cplusplus @@ -29,9 +41,10 @@ extern "C" { #define GLX_VERSION_1_1 1 #define GLX_VERSION_1_2 1 +#define GLX_VERSION_1_3 1 /* -** Names for attributes to glXGetConfig. +** Visual Config Attributes (glXGetConfig, glXGetFBConfigAttrib) */ #define GLX_USE_GL 1 /* support GLX rendering */ #define GLX_BUFFER_SIZE 2 /* depth of the color buffer */ @@ -39,7 +52,7 @@ extern "C" { #define GLX_RGBA 4 /* true if RGBA mode */ #define GLX_DOUBLEBUFFER 5 /* double buffering supported */ #define GLX_STEREO 6 /* stereo buffering supported */ -#define GLX_AUX_BUFFERS 7 /* number of aux buffers */ +#define GLX_AUX_BUFFERS 7 /* number of aux buffers */ #define GLX_RED_SIZE 8 /* number of red component bits */ #define GLX_GREEN_SIZE 9 /* number of green component bits */ #define GLX_BLUE_SIZE 10 /* number of blue component bits */ @@ -50,6 +63,25 @@ extern "C" { #define GLX_ACCUM_GREEN_SIZE 15 /* number of green accum bits */ #define GLX_ACCUM_BLUE_SIZE 16 /* number of blue accum bits */ #define GLX_ACCUM_ALPHA_SIZE 17 /* number of alpha accum bits */ +/* +** FBConfig-specific attributes +*/ +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_CONFIG_CAVEAT 0x20 /* Like visual_info VISUAL_CAVEAT_EXT */ +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_VISUAL_ID 0x800B /* ** Error return values from glXGetConfig. Success is indicated by @@ -59,9 +91,85 @@ extern "C" { #define GLX_BAD_ATTRIBUTE 2 /* attribute to get is bad */ #define GLX_NO_EXTENSION 3 /* no glx extension on server */ #define GLX_BAD_VISUAL 4 /* visual # not known by GLX */ -#define GLX_BAD_CONTEXT 5 -#define GLX_BAD_VALUE 6 -#define GLX_BAD_ENUM 7 +#define GLX_BAD_CONTEXT 5 /* returned only by import_context EXT? */ +#define GLX_BAD_VALUE 6 /* returned only by glXSwapIntervalSGI? */ +#define GLX_BAD_ENUM 7 /* unused? */ + +/* FBConfig attribute values */ + +/* +** Generic "don't care" value for glX ChooseFBConfig attributes (except +** GLX_LEVEL) +*/ +#define GLX_DONT_CARE 0xFFFFFFFF + +/* GLX_RENDER_TYPE bits */ +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 + +/* GLX_DRAWABLE_TYPE bits */ +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 + +/* GLX_CONFIG_CAVEAT attribute values */ +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_NON_CONFORMANT_CONFIG 0x800D + +/* GLX_X_VISUAL_TYPE attribute values */ +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 + +/* GLX_TRANSPARENT_TYPE attribute values */ +/* #define GLX_NONE 0x8000 */ +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 + +/* glXCreateGLXPbuffer attributes */ +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_PBUFFER_HEIGHT 0x8040 /* New for GLX 1.3 */ +#define GLX_PBUFFER_WIDTH 0x8041 /* New for GLX 1.3 */ + +/* glXQueryGLXPBuffer attributes */ +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F + +/* glXCreateNewContext render_type attribute values */ +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 + +/* glXQueryContext attributes */ +/* #define GLX_FBCONFIG_ID 0x8013 */ +/* #define GLX_RENDER_TYPE 0x8011 */ +#define GLX_SCREEN 0x800C + +/* glXSelectEvent event mask bits */ +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 + +/* GLXPbufferClobberEvent event_type values */ +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 + +/* GLXPbufferClobberEvent draw_type values */ +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 + +/* GLXPbufferClobberEvent buffer_mask bits */ +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 /* ** Extension return values from glXGetConfig. These are also @@ -71,27 +179,27 @@ extern "C" { #define GLX_X_VISUAL_TYPE_EXT 0x22 /* visual_info extension type */ #define GLX_TRANSPARENT_TYPE_EXT 0x23 /* visual_info extension */ #define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 /* visual_info extension */ -#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 /* visual_info extension */ +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 /* visual_info extension */ #define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 /* visual_info extension */ -#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 /* visual_info extension */ +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 /* visual_info extension */ #define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 /* visual_info extension */ /* Property values for visual_type */ -#define GLX_TRUE_COLOR_EXT 0x8002 -#define GLX_DIRECT_COLOR_EXT 0x8003 -#define GLX_PSEUDO_COLOR_EXT 0x8004 -#define GLX_STATIC_COLOR_EXT 0x8005 -#define GLX_GRAY_SCALE_EXT 0x8006 -#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 /* Property values for transparent pixel */ -#define GLX_NONE_EXT 0x8000 -#define GLX_TRANSPARENT_RGB_EXT 0x8008 -#define GLX_TRANSPARENT_INDEX_EXT 0x8009 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 /* Property values for visual_rating */ -#define GLX_VISUAL_CAVEAT_EXT 0x20 /* visual_rating extension type */ -#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_VISUAL_CAVEAT_EXT 0x20 /* visual_rating extension type */ +#define GLX_SLOW_VISUAL_EXT 0x8001 #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D /* @@ -109,11 +217,12 @@ extern "C" { #define GLX_SCREEN_EXT 0x800C /* screen number */ /* GLX Extension Strings */ -#define GLX_EXT_import_context 1 -#define GLX_EXT_visual_info 1 -#define GLX_EXT_visual_rating 1 +#define GLX_EXT_import_context 1 +#define GLX_EXT_visual_info 1 +#define GLX_EXT_visual_rating 1 #define GLX_ARB_get_proc_address 1 + #ifdef __cplusplus } #endif diff --git a/xc/lib/GL/Imakefile b/xc/lib/GL/Imakefile index dfc8231d2..c882109e1 100644 --- a/xc/lib/GL/Imakefile +++ b/xc/lib/GL/Imakefile @@ -134,6 +134,22 @@ REQUIREDLIBS += -lglide3x GLXSUBDIRS = glx dri mesa/dri mesa/include/GL mesa/src +#elif GlxBuiltInR128 + + R128OBJS = mesa/src/drv/r128/?*.o + R128UOBJS = mesa/src/drv/r128/unshared/?*.o + R128DOBJS = mesa/src/drv/r128/debugger/?*.o + R128POBJS = mesa/src/drv/r128/profiled/?*.o + R128DONES = mesa/src/drv/r128/DONE + + DRVOBJS = $(R128OBJS) $(MESAOBJS) $(DRIMESAOBJS) $(DRMOBJS) + DRVUOBJS = $(R128UOBJS) $(MESAUOBJS) $(DRIMESAUOBJS) $(DRMUOBJS) + DRVDOBJS = $(R128DOBJS) $(MESADOBJS) $(DRIMESADOBJS) $(DRMDOBJS) + DRVPOBJS = $(R128POBJS) $(MESAPOBJS) $(DRIMESAPOBJS) $(DRMPOBJS) + DRVDONES = $(R128DONES) $(MESADONES) $(DRIMESADONES) $(DRMDONES) + + GLXSUBDIRS = glx dri mesa/dri mesa/include/GL mesa/src + #elif GlxBuiltInMesa #ifndef GlxDriverUsesMesa diff --git a/xc/lib/GL/dri/XF86dri.c b/xc/lib/GL/dri/XF86dri.c index 51615556a..dd0ee56ff 100644 --- a/xc/lib/GL/dri/XF86dri.c +++ b/xc/lib/GL/dri/XF86dri.c @@ -276,7 +276,7 @@ Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion, *ddxDriverPatchVersion = rep.ddxDriverPatchVersion; if (rep.length) { - if (!(*clientDriverName = (char *)Xcalloc(rep.length + 1, 1))) { + if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) { _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3)); return False; } diff --git a/xc/lib/GL/dri/drm/Imakefile b/xc/lib/GL/dri/drm/Imakefile index 18619461b..42b6202d6 100644 --- a/xc/lib/GL/dri/drm/Imakefile +++ b/xc/lib/GL/dri/drm/Imakefile @@ -12,12 +12,17 @@ ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL DEFINES = $(ALLOC_DEFINES) INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) -I. - SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c - OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o + SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \ + xf86drmR128.c + OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o \ + xf86drmR128.o #if defined(LinuxArchitecture) OS_SUBDIR = linux #endif +#if defined(FreeBSDArchitecture) +OS_SUBDIR = bsd +#endif LinkSourceFile(xf86drm.c,$(XF86OSSRC)/$(OS_SUBDIR)/drm) LinkSourceFile(xf86drmHash.c,$(XF86OSSRC)/$(OS_SUBDIR)/drm) @@ -25,6 +30,11 @@ LinkSourceFile(xf86drmRandom.c,$(XF86OSSRC)/$(OS_SUBDIR)/drm) LinkSourceFile(xf86drmSL.c,$(XF86OSSRC)/$(OS_SUBDIR)/drm) LinkSourceFile(xf86drm.h,$(XF86OSSRC)) LinkSourceFile(drm.h,$(XF86OSSRC)/$(OS_SUBDIR)/drm/kernel) +LinkSourceFile(mga_drm.h,$(XF86OSSRC)/$(OS_SUBDIR)/drm/kernel) +LinkSourceFile(i810_drm.h,$(XF86OSSRC)/$(OS_SUBDIR)/drm/kernel) +LinkSourceFile(xf86drmR128.c,$(XF86OSSRC)/$(OS_SUBDIR)/drm) +LinkSourceFile(xf86drmR128.h,$(XF86OSSRC)) +LinkSourceFile(r128_drm.h,$(XF86OSSRC)/$(OS_SUBDIR)/drm/kernel) #include <Library.tmpl> diff --git a/xc/lib/GL/mesa/src/Imakefile b/xc/lib/GL/mesa/src/Imakefile index 7d9b1d8e8..1d42b4950 100644 --- a/xc/lib/GL/mesa/src/Imakefile +++ b/xc/lib/GL/mesa/src/Imakefile @@ -348,8 +348,12 @@ LinkSourceFile(zoom.h, ../../../../extras/Mesa/src) #ifdef i386Architecture ASM_SRCS = ASM_OBJS = +#ifdef MesaUse3DNow + ASM_DEFS = -DUSE_MMX_ASM -DUSE_X86_ASM -DUSE_3DNOW_ASM +#else ASM_DEFS = -DUSE_MMX_ASM -DUSE_X86_ASM #endif +#endif DEFINES = $(ALLOC_DEFINES) GlxDefines $(TDFX_DEFS) $(ASM_DEFS) INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) -I../include -I../../dri -I. -I../../../../include diff --git a/xc/lib/GL/mesa/src/X86/Imakefile b/xc/lib/GL/mesa/src/X86/Imakefile index 858f0cd73..53402ac67 100644 --- a/xc/lib/GL/mesa/src/X86/Imakefile +++ b/xc/lib/GL/mesa/src/X86/Imakefile @@ -16,7 +16,6 @@ LinkSourceFile(x86.h, ../../../../../extras/Mesa/src/X86) LinkSourceFile(x86a.S, ../../../../../extras/Mesa/src/X86) LinkSourceFile(vertex.S, ../../../../../extras/Mesa/src/X86) LinkSourceFile(x86flatregs.m4, ../../../../../extras/Mesa/src/X86) -LinkSourceFile(x86a.S.m4, ../../../../../extras/Mesa/src/X86) LinkSourceFile(mmx.h, ../../../../../extras/Mesa/src/X86) LinkSourceFile(mmx_blend.S, ../../../../../extras/Mesa/src/X86) @@ -55,9 +54,7 @@ XCOMM We'll learn at runtime whether 3dNow, MMX, etc are really present. MMX_DEFS = -DUSE_MMX_ASM - -XCOMM Disabling 3DNow code for the time being -#if 0 +#ifdef MesaUse3DNow 3DNOW_SRCS = 3dnow.c 3dnow_norm_raw.S 3dnow_xform_masked1.S \ 3dnow_xform_masked2.S 3dnow_xform_masked3.S \ 3dnow_xform_masked4.S 3dnow_xform_raw1.S \ @@ -73,6 +70,7 @@ XCOMM Disabling 3DNow code for the time being 3DNOW_DEFS = -DUSE_3DNOW_ASM #endif + #endif DEFINES = $(ALLOC_DEFINES) GlxDefines -DFX $(X86_DEFS) $(MMX_DEFS) $(3DNOW_DEFS) @@ -96,7 +94,7 @@ STD_CPP_DEFINES = StandardDefines $(PROJECT_DEFINES) SubdirLibraryRule($(OBJS)) NormalLintTarget($(SRCS)) -#ifdef HAVE_3DNOW +#ifdef MesaUse3DNow ObjectFromAsmSource(3dnow_norm_raw, NullParameter) ObjectFromAsmSource(3dnow_xform_masked1, NullParameter) ObjectFromAsmSource(3dnow_xform_masked2, NullParameter) @@ -109,9 +107,7 @@ ObjectFromAsmSource(3dnow_xform_raw4, NullParameter) ObjectFromAsmSource(vertex_3dnow, NullParameter) #endif -#ifdef HAVE_MMX ObjectFromAsmSource(mmx_blend, NullParameter) -#endif ObjectFromAsmSource(common_x86asm, NullParameter) ObjectFromAsmSource(vertex, NullParameter) @@ -119,6 +115,3 @@ ObjectFromAsmSource(x86a, NullParameter) DependTarget() -x86a.S: x86flatregs.m4 -x86a.S: x86a.S.m4 - m4 $< >$@ diff --git a/xc/lib/GL/mesa/src/drv/Imakefile b/xc/lib/GL/mesa/src/drv/Imakefile index fadb29bb2..ed30e7196 100644 --- a/xc/lib/GL/mesa/src/drv/Imakefile +++ b/xc/lib/GL/mesa/src/drv/Imakefile @@ -16,6 +16,15 @@ DRIVER += gamma #if GlxBuiltInTdfx DRIVER += tdfx #endif +#if GlxBuiltInMga +DRIVER += common mga +#endif +#if GlxBuiltInI810 +DRIVER += common i810 +#endif +#if GlxBuiltInR128 +DRIVER += r128 +#endif SUBDIRS = $(DRIVER) #else @@ -23,6 +32,10 @@ SUBDIRS += gamma #if HasGlide3 SUBDIRS += tdfx #endif +SUBDIRS += common +SUBDIRS += mga +SUBDIRS += i810 +SUBDIRS += r128 #endif MakeSubdirs($(SUBDIRS)) diff --git a/xc/lib/GL/mesa/src/drv/common/Imakefile b/xc/lib/GL/mesa/src/drv/common/Imakefile index 5c3d40dd7..d47b662e8 100644 --- a/xc/lib/GL/mesa/src/drv/common/Imakefile +++ b/xc/lib/GL/mesa/src/drv/common/Imakefile @@ -22,13 +22,12 @@ MESA_INCLUDES = -I. -I.. -I../../include DEFINES = $(ALLOC_DEFINES) $(DRI_DEFINES) - INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) \ - -I/usr/include/glide + INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) DRISRCS = hwlog.c mm.c DRIOBJS = hwlog.o mm.o - SRCS = $(DRISRCS) - OBJS = $(DRIOBJS) + SRCS = $(DRISRCS) + OBJS = $(DRIOBJS) #if !GlxUseBuiltInDRIDriver #undef DoNormalLib NormalLibGlx @@ -44,7 +43,8 @@ LibraryObjectRule() SubdirLibraryRule($(OBJS)) NormalLintTarget($(SRCS)) -#if !GlxUseBuiltInDRIDriver +XCOMM #if !GlxUseBuiltInDRIDriver +#if 0 LIBNAME = i810_dri.so ALL_OBJS = $(OBJS) ALL_DEPS = DONE diff --git a/xc/lib/GL/mesa/src/drv/gamma/Imakefile b/xc/lib/GL/mesa/src/drv/gamma/Imakefile index 05e35561e..0e9833177 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/Imakefile +++ b/xc/lib/GL/mesa/src/drv/gamma/Imakefile @@ -1,4 +1,5 @@ -XCOMM $XFree86: xc/lib/GL/mesa/src/drv/gamma/Imakefile,v 1.8 2000/03/02 16:07:35 martin Exp $ + +#include <Threads.tmpl> #define DoNormalLib NormalLibGlx #define DoSharedLib SharedLibGlx @@ -6,28 +7,35 @@ XCOMM $XFree86: xc/lib/GL/mesa/src/drv/gamma/Imakefile,v 1.8 2000/03/02 16:07:35 #define DoDebugLib DebugLibGlx #define DoProfileLib ProfileLibGlx -LinkSourceFile(xmesaP.h, ../../../../../../extras/Mesa/src/X) -LinkSourceFile(glapi.h, ../../../../../../extras/Mesa/src) - - #if Malloc0ReturnsNull ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL #endif #if BuildXF86DRI - DRI_DEFINES = GlxDefines + DRI_DEFINES = GlxDefines -DDRIVERTS DRI_INCLUDES = -I../../../../dri -I../../../../glx \ -I../../../dri \ -I$(TOP)/include -I$(TOP)/include/GL \ -I$(XF86OSSRC) -I$(SERVERSRC)/GL/dri \ -I$(XF86DRIVERSRC)/glint \ - -I../../../include -I../.. -I../../X + -I../../../include -I../.. -I../../X -I../common \ + -I$(XF86OSSRC)/linux/drm/kernel #endif MESA_INCLUDES = -I. -I.. -I../../include + + DEFINES = $(ALLOC_DEFINES) $(DRI_DEFINES) - INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) + INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) + +#if 0 + LOSRC = ../../../../lowpc.c + LOOBJ = ../../../../lowpc.o + + HISRC = ../../../../highpc.c + HIOBJ = ../../../../highpc.o +#endif DRISRCS = ../../../dri/dri_mesa.c \ ../../../../dri/dri_tmm.c @@ -46,16 +54,216 @@ MESA_INCLUDES = -I. -I.. -I../../include ../../../../dri/drm/xf86drmSL.o GAMMASRCS = gamma_gl.c gamma_xmesa.c gamma_init.c gamma_matrix.c \ - gamma_inithw.c gamma_texture.c + gamma_inithw.c gamma_texture.c /* gamma_dlist.c */ GAMMAOBJS = gamma_gl.o gamma_xmesa.o gamma_init.o gamma_matrix.o \ - gamma_inithw.o gamma_texture.o + gamma_inithw.o gamma_texture.o /* gamma_dlist.o */ + + MESASRCS = ../../aatriangle.c \ + ../../accum.c \ + ../../alpha.c \ + ../../alphabuf.c \ + ../../attrib.c \ + ../../bbox.c \ + ../../bitmap.c \ + ../../blend.c \ + ../../buffers.c \ + ../../clip.c \ + ../../colortab.c \ + ../../config.c \ + ../../context.c \ + ../../copypix.c \ + ../../cva.c \ + ../../debug_xform.c \ + ../../depth.c \ + ../../dlist.c \ + ../../drawpix.c \ + ../../enable.c \ + ../../enums.c \ + ../../eval.c \ + ../../extensions.c \ + ../../feedback.c \ + ../../fog.c \ + ../../get.c \ + ../../glapi.c \ + ../../glapinoop.c \ + ../../glthread.c \ + ../../hash.c \ + ../../image.c \ + ../../imaging.c \ + ../../light.c \ + ../../lines.c \ + ../../logic.c \ + ../../masking.c \ + ../../matrix.c \ + ../../mem.c \ + ../../mmath.c \ + ../../pb.c \ + ../../pipeline.c \ + ../../pixel.c \ + ../../pixeltex.c \ + ../../points.c \ + ../../polygon.c \ + ../../quads.c \ + ../../rastpos.c \ + ../../readpix.c \ + ../../rect.c \ + ../../scissor.c \ + ../../shade.c \ + ../../span.c \ + ../../stages.c \ + ../../state.c \ + ../../stencil.c \ + ../../teximage.c \ + ../../texobj.c \ + ../../texstate.c \ + ../../texture.c \ + ../../texutil.c \ + ../../translate.c \ + ../../triangle.c \ + ../../varray.c \ + ../../vb.c \ + ../../vbcull.c \ + ../../vbfill.c \ + ../../vbindirect.c \ + ../../vbrender.c \ + ../../vbxform.c \ + ../../vector.c \ + ../../vertices.c \ + ../../winpos.c \ + ../../xform.c \ + ../../zoom.c \ + ../../X86/common_x86.c + + MESAOBJS = ../../aatriangle.o \ + ../../accum.o \ + ../../alpha.o \ + ../../alphabuf.o \ + ../../attrib.o \ + ../../bbox.o \ + ../../bitmap.o \ + ../../blend.o \ + ../../buffers.o \ + ../../clip.o \ + ../../colortab.o \ + ../../config.o \ + ../../context.o \ + ../../copypix.o \ + ../../cva.o \ + ../../debug_xform.o \ + ../../depth.o \ + ../../dlist.o \ + ../../drawpix.o \ + ../../enable.o \ + ../../enums.o \ + ../../eval.o \ + ../../extensions.o \ + ../../feedback.o \ + ../../fog.o \ + ../../get.o \ + ../../hash.o \ + ../../hint.o \ + ../../image.o \ + ../../imaging.o \ + ../../light.o \ + ../../lines.o \ + ../../logic.o \ + ../../masking.o \ + ../../matrix.o \ + ../../mem.o \ + ../../mmath.o \ + ../../pb.o \ + ../../pipeline.o \ + ../../pixel.o \ + ../../pixeltex.o \ + ../../points.o \ + ../../polygon.o \ + ../../quads.o \ + ../../rastpos.o \ + ../../readpix.o \ + ../../rect.o \ + ../../scissor.o \ + ../../shade.o \ + ../../span.o \ + ../../stages.o \ + ../../state.o \ + ../../stencil.o \ + ../../teximage.o \ + ../../texobj.o \ + ../../texstate.o \ + ../../texture.o \ + ../../texutil.o \ + ../../translate.o \ + ../../triangle.o \ + ../../varray.o \ + ../../vb.o \ + ../../vbcull.o \ + ../../vbfill.o \ + ../../vbindirect.o \ + ../../vbrender.o \ + ../../vbxform.o \ + ../../vector.o \ + ../../vertices.o \ + ../../winpos.o \ + ../../xform.o \ + ../../zoom.o + +#ifdef i386Architecture + X86_SRCS = ../../X86/x86.c \ + ../../X86/x86a.S \ + ../../X86/common_x86.c \ + ../../X86/common_x86asm.S \ + ../../X86/vertex.S -XCOMM SRCS = $(DRISRCS) $(DRMSRCS) $(GAMMASRCS) -XCOMM OBJS = $(DRIOBJS) $(DRMOBJS) $(GAMMAOBJS) + X86_OBJS = ../../X86/x86.o \ + ../../X86/x86a.o \ + ../../X86/common_x86.o \ + ../../X86/common_x86asm.o \ + ../../X86/vertex.o - SRCS = $(GAMMASRCS) - OBJS = $(DRIOBJS) $(DRMOBJS) $(GAMMAOBJS) + MMX_SRCS = ../../X86/mmx_blend.S + + MMX_OBJS = ../../X86/mmx_blend.o + +XCOMM Disabling 3Dnow code for the time being. +#if 0 + 3DNOW_SRCS = ../../X86/3dnow.c \ + ../../X86/3dnow_norm_raw.S \ + ../../X86/3dnow_xform_masked1.S \ + ../../X86/3dnow_xform_masked2.S \ + ../../X86/3dnow_xform_masked3.S \ + ../../X86/3dnow_xform_masked4.S \ + ../../X86/3dnow_xform_raw1.S \ + ../../X86/3dnow_xform_raw2.S \ + ../../X86/3dnow_xform_raw3.S \ + ../../X86/3dnow_xform_raw4.S \ + ../../X86/vertex_3dnow.S + + 3DNOW_OBJS = ../../X86/3dnow.o \ + ../../X86/3dnow_norm_raw.o \ + ../../X86/3dnow_xform_masked1.o \ + ../../X86/3dnow_xform_masked2.o \ + ../../X86/3dnow_xform_masked3.o \ + ../../X86/3dnow_xform_masked4.o \ + ../../X86/3dnow_xform_raw1.o \ + ../../X86/3dnow_xform_raw2.o \ + ../../X86/3dnow_xform_raw3.o \ + ../../X86/3dnow_xform_raw4.o \ + ../../X86/vertex_3dnow.o +#endif + +#endif + + ASMSRCS = $(X86_SRCS) $(MMX_SRCS) $(3DNOW_SRCS) + ASMOBJS = $(X86_OBJS) $(MMX_OBJS) $(3DNOW_OBJS) + + SRCS = $(LOWSRC) $(DRISRCS) $(DRMSRCS) $(MESASRCS) $(ASMSRCS) $(GAMMASRCS) $(HISRC) + OBJS = $(LOWOBJ) $(DRIOBJS) $(DRMOBJS) $(MESAOBJS) $(ASMOBJS) $(GAMMAOBJS) $(HIOBJ) + +REQUIREDLIBS += -lm +#if !GlxBuiltInMga +REQUIREDLIBS += -L../../../.. -lGL +#endif #if !GlxUseBuiltInDRIDriver diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_gl.c b/xc/lib/GL/mesa/src/drv/gamma/gamma_gl.c index d72c642cf..61e59a7a9 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/gamma_gl.c +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_gl.c @@ -30,13 +30,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <kevin@precisioninsight.com> * Brian Paul <brian@precisioninsight.com> + * Alan Hourihane <Alan.Hourihane@btinternet.com> */ #ifdef GLX_DIRECT_RENDERING +#include <Xarch.h> #include <math.h> #include "gamma_gl.h" #include "gamma_init.h" +#include "glint_dri.h" #ifdef RANDOMIZE_COLORS #include <stdlib.h> #endif @@ -114,7 +117,7 @@ void _gamma_Begin(GLenum mode) DEBUG_GLCMDS(("Begin: %04x\n", (int)mode)); if ((gCCPriv->Begin & B_PrimType_Mask) != B_PrimType_Null) { - /* ERROR!!! */ + DEBUG_ERROR(("Begin: Error\n")); return; } @@ -177,8 +180,9 @@ void _gamma_BindTexture(GLenum target, GLuint texture) gCCPriv->curTexObj = gammaTOFind(texture); /* Make the new texture images resident */ - if (!driTMMMakeImagesResident(gCCPriv->tmm, MIPMAP_LEVELS, - gCCPriv->curTexObj->image, addrs)) { + if (driTMMMakeImagesResident(gCCPriv->tmm, MIPMAP_LEVELS, + gCCPriv->curTexObj->image, addrs) < 0) { + DEBUG_ERROR(("BindTexture: unable\n")); /* NOT_DONE: Handle error */ } @@ -358,8 +362,10 @@ void _gamma_CallLists(GLsizei n, GLenum type, const GLvoid *lists) void _gamma_Clear(GLbitfield mask) { + int temp; unsigned int depth = 0; int do_clear = 0; + GLINTDRIPtr gDRIPriv = (GLINTDRIPtr)gCC->driScreenPriv->pDevPriv; #ifdef DO_VALIDATE __DRIscreenPrivate *driScrnPriv = gCC->driScreenPriv; #endif @@ -437,11 +443,12 @@ void _gamma_Clear(GLbitfield mask) gCCPriv->FrameCount &= 0xff; #endif + temp = (gCCPriv->LBReadMode & LBPartialProdMask) | LBWindowOriginBot; + /* UGH - move this later ! */ + if (gDRIPriv->numMXDevices == 2) temp |= LBScanLineInt2; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); - WRITE(gCCPriv->buf, LBReadMode, - ((gCCPriv->LBReadMode & LBPartialProdMask) | - LBScanLineInt2 | - LBWindowOriginBot)); + WRITE(gCCPriv->buf, LBReadMode, temp); /* Force FCP to be written */ CHECK_DMA_BUFFER(gCC, gCCPriv, 1); @@ -627,34 +634,48 @@ void _gamma_ClipPlane(GLenum plane, const GLdouble *equation) void _gamma_Color3b(GLbyte red, GLbyte green, GLbyte blue) { + GLfloat r,g,b; + DEBUG_GLCMDS(("Color3b: %d %d %d\n", red, green, blue)); + + r = BYTE_TO_FLOAT(red); + g = BYTE_TO_FLOAT(green); + b = BYTE_TO_FLOAT(blue); + + _gamma_Color3f(r,g,b); } void _gamma_Color3bv(const GLbyte *v) { + GLfloat p[3]; + DEBUG_GLCMDS(("Color3bv: %d %d %d\n", v[0], v[1], v[2])); + + p[0] = BYTE_TO_FLOAT(v[0]); + p[1] = BYTE_TO_FLOAT(v[1]); + p[2] = BYTE_TO_FLOAT(v[2]); + + _gamma_Color3fv(p); } void _gamma_Color3d(GLdouble red, GLdouble green, GLdouble blue) { DEBUG_GLCMDS(("Color3d: %f %f %f\n", red, green, blue)); + + _gamma_Color3f((GLfloat)red,(GLfloat)green,(GLfloat)blue); } void _gamma_Color3dv(const GLdouble *v) { DEBUG_GLCMDS(("Color3dv: %f %f %f\n", v[0], v[1], v[2])); + + _gamma_Color3fv((GLfloat*)v); } void _gamma_Color3f(GLfloat red, GLfloat green, GLfloat blue) { DEBUG_GLCMDS(("Color3f: %f %f %f\n", red, green, blue)); -#ifdef RANDOMIZE_COLORS - red = (random() / (double)RAND_MAX); - green = (random() / (double)RAND_MAX); - blue = (random() / (double)RAND_MAX); -#endif - CHECK_DMA_BUFFER(gCC, gCCPriv, 3); WRITEF(gCCPriv->buf, Cb, blue); WRITEF(gCCPriv->buf, Cg, green); @@ -665,107 +686,188 @@ void _gamma_Color3fv(const GLfloat *v) { DEBUG_GLCMDS(("Color3fv: %f %f %f\n", v[0], v[1], v[2])); -#ifdef RANDOMIZE_COLORS - { - float r, g, b; - r = (random() / (double)RAND_MAX); - g = (random() / (double)RAND_MAX); - b = (random() / (double)RAND_MAX); - CHECK_DMA_BUFFER(gCC, gCCPriv, 3); - WRITEF(gCCPriv->buf, Cb, b); - WRITEF(gCCPriv->buf, Cg, g); - WRITEF(gCCPriv->buf, Cr3, r); - } -#else CHECK_DMA_BUFFER(gCC, gCCPriv, 3); WRITEF(gCCPriv->buf, Cb, v[2]); WRITEF(gCCPriv->buf, Cg, v[1]); WRITEF(gCCPriv->buf, Cr3, v[0]); -#endif } void _gamma_Color3i(GLint red, GLint green, GLint blue) { + GLfloat r,g,b; + DEBUG_GLCMDS(("Color3i: %d %d %d\n", (int)red, (int)green, (int)blue)); + + r = INT_TO_FLOAT(red); + g = INT_TO_FLOAT(green); + b = INT_TO_FLOAT(blue); + + _gamma_Color3f(r,g,b); } void _gamma_Color3iv(const GLint *v) { + GLfloat p[3]; + DEBUG_GLCMDS(("Color3iv: %d %d %d\n", (int)v[0], (int)v[1], (int)v[2])); + + p[0] = INT_TO_FLOAT(v[0]); + p[1] = INT_TO_FLOAT(v[1]); + p[2] = INT_TO_FLOAT(v[2]); + + _gamma_Color3fv(p); } void _gamma_Color3s(GLshort red, GLshort green, GLshort blue) { + GLfloat r,g,b; + DEBUG_GLCMDS(("Color3s: %d %d %d\n", red, green, blue)); + + r = SHORT_TO_FLOAT(red); + g = SHORT_TO_FLOAT(green); + b = SHORT_TO_FLOAT(blue); + + _gamma_Color3f(r,g,b); } void _gamma_Color3sv(const GLshort *v) { + GLfloat p[3]; + DEBUG_GLCMDS(("Color3sv: %d %d %d\n", v[0], v[1], v[2])); + + p[0] = SHORT_TO_FLOAT(v[0]); + p[1] = SHORT_TO_FLOAT(v[1]); + p[2] = SHORT_TO_FLOAT(v[2]); + + _gamma_Color3fv(p); } void _gamma_Color3ub(GLubyte red, GLubyte green, GLubyte blue) { + GLuint c; + DEBUG_GLCMDS(("Color3ub: %d %d %d\n", red, green, blue)); + + c = (blue << 16) | (green << 8) | red; + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, PackedColor3, c); } void _gamma_Color3ubv(const GLubyte *v) { + GLuint c; + DEBUG_GLCMDS(("Color3ubv: %d %d %d\n", v[0], v[1], v[2])); + + c = (v[2] << 16) | (v[1] << 8) | v[0]; + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, PackedColor3, c); } void _gamma_Color3ui(GLuint red, GLuint green, GLuint blue) { + GLfloat r,g,b; + DEBUG_GLCMDS(("Color3ui: %d %d %d\n", (unsigned int)red, (unsigned int)green, (unsigned int)blue)); + + r = UINT_TO_FLOAT(red); + g = UINT_TO_FLOAT(green); + b = UINT_TO_FLOAT(blue); + + _gamma_Color3f(r,g,b); } void _gamma_Color3uiv(const GLuint *v) { + GLfloat p[3]; + DEBUG_GLCMDS(("Color3uiv: %d %d %d\n", (unsigned int)v[0], (unsigned int)v[1], (unsigned int)v[2])); + + p[0] = UINT_TO_FLOAT(v[0]); + p[1] = UINT_TO_FLOAT(v[1]); + p[2] = UINT_TO_FLOAT(v[2]); + + _gamma_Color3fv(p); } void _gamma_Color3us(GLushort red, GLushort green, GLushort blue) { + GLuint c; + DEBUG_GLCMDS(("Color3us: %d %d %d\n", red, green, blue)); + + c = (USHORT_TO_UBYTE(blue) << 16) | (USHORT_TO_UBYTE(green) << 8) | + USHORT_TO_UBYTE(red); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, PackedColor3, c); } void _gamma_Color3usv(const GLushort *v) { + GLuint c; + DEBUG_GLCMDS(("Color3usv: %d %d %d\n", v[0], v[1], v[2])); + + c = (USHORT_TO_UBYTE(v[2]) << 16) | (USHORT_TO_UBYTE(v[1]) << 8) | + USHORT_TO_UBYTE(v[0]); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, PackedColor3, c); } void _gamma_Color4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) { + GLfloat r,g,b,a; + DEBUG_GLCMDS(("Color4b: %d %d %d %d\n", red, green, blue, alpha)); + + r = BYTE_TO_FLOAT(red); + g = BYTE_TO_FLOAT(green); + b = BYTE_TO_FLOAT(blue); + a = BYTE_TO_FLOAT(alpha); + + _gamma_Color4f(r,g,b,a); } void _gamma_Color4bv(const GLbyte *v) { + GLfloat p[4]; + DEBUG_GLCMDS(("Color4bv: %d %d %d %d\n", v[0], v[1], v[2], v[3])); + + p[0] = BYTE_TO_FLOAT(v[0]); + p[1] = BYTE_TO_FLOAT(v[1]); + p[2] = BYTE_TO_FLOAT(v[2]); + p[3] = BYTE_TO_FLOAT(v[3]); + + _gamma_Color4fv(p); } void _gamma_Color4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) { DEBUG_GLCMDS(("Color4d: %f %f %f %f\n", red, green, blue, alpha)); + + _gamma_Color4f((GLfloat)red,(GLfloat)green,(GLfloat)blue,(GLfloat)alpha); } void _gamma_Color4dv(const GLdouble *v) { DEBUG_GLCMDS(("Color4dv: %f %f %f %f\n", v[0], v[1], v[2], v[3])); + + _gamma_Color4fv((GLfloat*)v); } void _gamma_Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { DEBUG_GLCMDS(("Color4f: %f %f %f %f\n", red, green, blue, alpha)); -#ifdef RANDOMIZE_COLORS - red = (random() / (double)RAND_MAX); - green = (random() / (double)RAND_MAX); - blue = (random() / (double)RAND_MAX); -#endif - CHECK_DMA_BUFFER(gCC, gCCPriv, 4); WRITEF(gCCPriv->buf, Ca, alpha); WRITEF(gCCPriv->buf, Cb, blue); @@ -777,37 +879,41 @@ void _gamma_Color4fv(const GLfloat *v) { DEBUG_GLCMDS(("Color4fv: %f %f %f %f\n", v[0], v[1], v[2], v[3])); -#ifdef RANDOMIZE_COLORS - { - float r, g, b; - r = (random() / (double)RAND_MAX); - g = (random() / (double)RAND_MAX); - b = (random() / (double)RAND_MAX); - CHECK_DMA_BUFFER(gCC, gCCPriv, 4); - WRITEF(gCCPriv->buf, Ca, v[3]); - WRITEF(gCCPriv->buf, Cb, b); - WRITEF(gCCPriv->buf, Cg, g); - WRITEF(gCCPriv->buf, Cr3, r); - } -#else CHECK_DMA_BUFFER(gCC, gCCPriv, 4); WRITEF(gCCPriv->buf, Ca, v[3]); WRITEF(gCCPriv->buf, Cb, v[2]); WRITEF(gCCPriv->buf, Cg, v[1]); WRITEF(gCCPriv->buf, Cr4, v[0]); -#endif } void _gamma_Color4i(GLint red, GLint green, GLint blue, GLint alpha) { + GLfloat r,g,b,a; + DEBUG_GLCMDS(("Color4i: %d %d %d %d\n", (int)red, (int)green, (int)blue, (int)alpha)); + + r = INT_TO_FLOAT(red); + g = INT_TO_FLOAT(green); + b = INT_TO_FLOAT(blue); + a = INT_TO_FLOAT(alpha); + + _gamma_Color4f(r,g,b,a); } void _gamma_Color4iv(const GLint *v) { + GLfloat p[4]; + DEBUG_GLCMDS(("Color4iv: %d %d %d %d\n", (int)v[0], (int)v[1], (int)v[2], (int)v[3])); + + p[0] = INT_TO_FLOAT(v[0]); + p[1] = INT_TO_FLOAT(v[1]); + p[2] = INT_TO_FLOAT(v[2]); + p[3] = INT_TO_FLOAT(v[3]); + + _gamma_Color4fv(p); } void _gamma_Color4s(GLshort red, GLshort green, GLshort blue, GLshort alpha) @@ -826,11 +932,7 @@ void _gamma_Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) DEBUG_GLCMDS(("Color4ub: %d %d %d %d\n", red, green, blue, alpha)); -#ifdef RANDOMIZE_COLORS - c = (random() / (double)RAND_MAX) * 16777216; -#else c = (alpha << 24) | (blue << 16) | (green << 8) | red; -#endif CHECK_DMA_BUFFER(gCC, gCCPriv, 1); WRITE(gCCPriv->buf, PackedColor4, c); @@ -842,17 +944,7 @@ void _gamma_Color4ubv(const GLubyte *v) DEBUG_GLCMDS(("Color4ubv: %d %d %d %d\n", v[0], v[1], v[2], v[3])); -#ifdef RANDOMIZE_COLORS - c = (random() / (double)RAND_MAX) * 16777216; -#else -/* NOT_DONE: Is there a standard define for endianness? */ -#define IS_LITTLE_ENDIAN 1 -#if IS_LITTLE_ENDIAN - c = *((GLuint *)v); -#else c = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | v[0]; -#endif -#endif CHECK_DMA_BUFFER(gCC, gCCPriv, 1); WRITE(gCCPriv->buf, PackedColor4, c); @@ -890,6 +982,43 @@ void _gamma_ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean void _gamma_ColorMaterial(GLenum face, GLenum mode) { DEBUG_GLCMDS(("ColorMaterial: %04x %04x\n", (int)face, (int)mode)); + + gCCPriv->MaterialMode &= ~MaterialModeEnable; + gCCPriv->ColorMaterialMode = ColorMaterialModeDisable; + + switch (face) { + case GL_FRONT: + gCCPriv->ColorMaterialMode |= ColorMaterialModeFront; + break; + case GL_BACK: + gCCPriv->ColorMaterialMode |= ColorMaterialModeBack; + break; + case GL_FRONT_AND_BACK: + gCCPriv->ColorMaterialMode |= ColorMaterialModeFrontAndBack; + break; + } + + switch (mode) { + case GL_AMBIENT: + gCCPriv->ColorMaterialMode |= ColorMaterialModeAmbient; + break; + case GL_EMISSION: + gCCPriv->ColorMaterialMode |= ColorMaterialModeEmission; + break; + case GL_DIFFUSE: + gCCPriv->ColorMaterialMode |= ColorMaterialModeDiffuse; + break; + case GL_SPECULAR: + gCCPriv->ColorMaterialMode |= ColorMaterialModeSpecular; + break; + case GL_AMBIENT_AND_DIFFUSE: + gCCPriv->ColorMaterialMode |= ColorMaterialModeAmbAndDiff; + break; + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, ColorMaterialMode, gCCPriv->ColorMaterialMode); + WRITE(gCCPriv->buf, MaterialMode, gCCPriv->MaterialMode); } void _gamma_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) @@ -938,9 +1067,6 @@ void _gamma_CullFace(GLenum mode) gCCPriv->GeometryMode &= ~GM_PolyCullMask; -#ifdef CULL_ALL_PRIMS - gCCPriv->GeometryMode |= GM_PolyCullBoth; -#else switch (mode) { case GL_FRONT: gCCPriv->GeometryMode |= GM_PolyCullFront; @@ -955,7 +1081,7 @@ void _gamma_CullFace(GLenum mode) /* ERROR!! */ break; } -#endif + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); WRITE(gCCPriv->buf, GeometryMode, gCCPriv->GeometryMode); } @@ -980,7 +1106,8 @@ void _gamma_DeleteTextures(GLsizei n, const GLuint *textures) for (i = 0; i < n; i++) { gammaTexObj *t = gammaTOFind(textures[i]); - if (!driTMMDeleteImages(gCCPriv->tmm, MIPMAP_LEVELS, t->image)) { + if (driTMMDeleteImages(gCCPriv->tmm, MIPMAP_LEVELS, t->image) < 0) { + DEBUG_ERROR(("DeleteTextures: unable\n")); /* NOT_DONE: Handle error */ } gammaTODelete(textures[i]); @@ -1068,11 +1195,9 @@ void _gamma_Disable(GLenum cap) switch (cap) { case GL_CULL_FACE: -#ifdef CULL_ALL_PRIMS gCCPriv->GeometryMode &= ~GM_PolyCullEnable; CHECK_DMA_BUFFER(gCC, gCCPriv, 1); WRITE(gCCPriv->buf, GeometryMode, gCCPriv->GeometryMode); -#endif break; case GL_DEPTH_TEST: if (gCCPriv->Flags & GAMMA_DEPTH_BUFFER) { @@ -1106,6 +1231,35 @@ void _gamma_Disable(GLenum cap) WRITE(gCCPriv->buf, FBReadMode, (gCCPriv->FBReadMode | gCCPriv->AB_FBReadMode)); break; + case GL_COLOR_MATERIAL: + gCCPriv->ColorMaterialMode &= ~ColorMaterialModeEnable; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, ColorMaterialMode, gCCPriv->ColorMaterialMode); + break; + case GL_FOG: + gCCPriv->Begin &= ~B_FogEnable; + gCCPriv->GeometryMode &= ~GM_FogEnable; + gCCPriv->DeltaMode &= ~DM_FogEnable; + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, GeometryMode, gCCPriv->GeometryMode); + WRITE(gCCPriv->buf, DeltaMode, gCCPriv->DeltaMode); + WRITE(gCCPriv->buf, FogMode, FogModeDisable); + break; + case GL_LIGHTING: + gCCPriv->LightingMode &= ~LightingModeEnable; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, LightingMode, gCCPriv->LightingMode); + break; + case GL_LIGHT0: + gCCPriv->Light0Mode &= ~LNM_On; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, Light0Mode, gCCPriv->Light0Mode); + break; + case GL_LIGHT1: + gCCPriv->Light1Mode &= ~LNM_On; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, Light1Mode, gCCPriv->Light1Mode); + break; case GL_TEXTURE_2D: gCCPriv->Texture2DEnabled = GL_FALSE; gCCPriv->Begin &= ~B_TextureEnable; @@ -1227,6 +1381,35 @@ void _gamma_Enable(GLenum cap) WRITE(gCCPriv->buf, FBReadMode, (gCCPriv->FBReadMode | gCCPriv->AB_FBReadMode)); break; + case GL_COLOR_MATERIAL: + gCCPriv->ColorMaterialMode |= ColorMaterialModeEnable; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, ColorMaterialMode, gCCPriv->ColorMaterialMode); + break; + case GL_FOG: + gCCPriv->Begin |= B_FogEnable; + gCCPriv->GeometryMode |= GM_FogEnable; + gCCPriv->DeltaMode |= DM_FogEnable; + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, GeometryMode, gCCPriv->GeometryMode); + WRITE(gCCPriv->buf, DeltaMode, gCCPriv->DeltaMode); + WRITE(gCCPriv->buf, FogMode, FogModeEnable); + break; + case GL_LIGHTING: + gCCPriv->LightingMode |= LightingModeEnable | 16<<6; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, LightingMode, gCCPriv->LightingMode); + break; + case GL_LIGHT0: + gCCPriv->Light0Mode |= LNM_On; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, Light0Mode, gCCPriv->Light0Mode); + break; + case GL_LIGHT1: + gCCPriv->Light1Mode |= LNM_On; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, Light1Mode, gCCPriv->Light1Mode); + break; case GL_TEXTURE_2D: gCCPriv->Texture2DEnabled = GL_TRUE; #ifndef TURN_OFF_TEXTURES @@ -1294,34 +1477,42 @@ void _gamma_EvalCoord1d(GLdouble u) void _gamma_EvalCoord1dv(const GLdouble *u) { + DEBUG_GLCMDS(("EvalCoord1dv: %f\n", *u)); } void _gamma_EvalCoord1f(GLfloat u) { + DEBUG_GLCMDS(("EvalCoord1f: %f\n", u)); } void _gamma_EvalCoord1fv(const GLfloat *u) { + DEBUG_GLCMDS(("EvalCoord1fv: %f\n", *u)); } void _gamma_EvalCoord2d(GLdouble u, GLdouble v) { + DEBUG_GLCMDS(("EvalCoord2d: %f %f\n", u, v)); } void _gamma_EvalCoord2dv(const GLdouble *u) { + DEBUG_GLCMDS(("EvalCoord2dv: %f %f\n", u[0], u[1])); } void _gamma_EvalCoord2f(GLfloat u, GLfloat v) { + DEBUG_GLCMDS(("EvalCoord2f: %f %f\n", u, v)); } void _gamma_EvalCoord2fv(const GLfloat *u) { + DEBUG_GLCMDS(("EvalCoord1fv: %f %f\n", u[0], u[1])); } void _gamma_EvalMesh1(GLenum mode, GLint i1, GLint i2) { + DEBUG_GLCMDS(("EvalMesh1: %d %d %d\n", mode, i1, i2)); } void _gamma_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) @@ -1358,16 +1549,55 @@ void _gamma_Flush(void) void _gamma_Fogf(GLenum pname, GLfloat param) { DEBUG_GLCMDS(("Fogf: %04x %f\n", (int)pname, param)); + + switch (pname) { + case GL_FOG_DENSITY: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, FogDensity, param); + break; + } } void _gamma_Fogfv(GLenum pname, const GLfloat *params) { + int color; + DEBUG_GLCMDS(("Fogfv: %04x %f\n", (int)pname, *params)); + + switch (pname) { + case GL_FOG_COLOR: + color = ((int)params[3]<<24) | ((int)params[2]<<16) | + ((int)params[1]<<8) | ((int)params[0]); + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, FogColor, color); + break; + } } void _gamma_Fogi(GLenum pname, GLint param) { DEBUG_GLCMDS(("Fogi: %04x %d\n", (int)pname, (int)param)); + + gCCPriv->GeometryMode &= ~GM_FogMask; + + switch (pname) { + case GL_FOG_MODE: + switch (param) { + case GL_EXP: + gCCPriv->GeometryMode |= GM_FogExp; + break; + case GL_EXP2: + gCCPriv->GeometryMode |= GM_FogExpSquared; + break; + case GL_LINEAR: + gCCPriv->GeometryMode |= GM_FogLinear; + break; + } + break; + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, GeometryMode, gCCPriv->GeometryMode); } void _gamma_Fogiv(GLenum pname, const GLint *params) @@ -1378,6 +1608,16 @@ void _gamma_Fogiv(GLenum pname, const GLint *params) void _gamma_FrontFace(GLenum mode) { DEBUG_GLCMDS(("FrontFace: %04x\n", (int)mode)); + + gCCPriv->GeometryMode &= ~GM_FFMask; + + if (mode == GL_CCW) + gCCPriv->GeometryMode |= GM_FrontFaceCCW; + else + gCCPriv->GeometryMode |= GM_FrontFaceCW; + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, GeometryMode, gCCPriv->GeometryMode); } void _gamma_Frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) @@ -1463,14 +1703,24 @@ void _gamma_GetFloatv(GLenum val, GLfloat *f) void _gamma_GetIntegerv(GLenum val, GLint *i) { DEBUG_GLCMDS(("GetIntegerv: %04x\n", (int)val)); + + switch (val) { + case GL_MAX_TEXTURE_SIZE: + *i = 2048; + break; + } } void _gamma_GetLightfv(GLenum light, GLenum pname, GLfloat *params) { + DEBUG_GLCMDS(("GetLightfv: %04x %04x %f\n", + (int)light, (int)pname, *params)); } void _gamma_GetLightiv(GLenum light, GLenum pname, GLint *params) { + DEBUG_GLCMDS(("GetLightiv: %04x %04x %d\n", + (int)light, (int)pname, *params)); } void _gamma_GetMapdv(GLenum target, GLenum query, GLdouble *v) @@ -1654,6 +1904,12 @@ GLboolean _gamma_IsEnabled(GLenum cap) { DEBUG_GLCMDS(("IsEnabled: %04x\n", (int)cap)); + switch (cap) { + case GL_LIGHTING: + return ((gCCPriv->LightingMode & LightingModeEnable)?GL_TRUE:GL_FALSE); + break; + } + return GL_TRUE; } @@ -1673,10 +1929,44 @@ GLboolean _gamma_IsTexture(GLuint texture) void _gamma_LightModelf(GLenum pname, GLfloat param) { + DEBUG_GLCMDS(("LightModelf: %04x %f\n", + (int)pname, param)); } void _gamma_LightModelfv(GLenum pname, const GLfloat *params) { + DEBUG_GLCMDS(("LightModelfv: %04x %f\n", + (int)pname, *params)); + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + /* We don't do alpha */ + WRITEF(gCCPriv->buf, SceneAmbientColorBlue, params[2]); + WRITEF(gCCPriv->buf, SceneAmbientColorGreen, params[1]); + WRITEF(gCCPriv->buf, SceneAmbientColorRed, params[0]); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + if ((int)params[0] != 0) + gCCPriv->LightingMode |= LightingModeLocalViewer; + else + gCCPriv->LightingMode &= ~LightingModeLocalViewer; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, LightingMode, gCCPriv->LightingMode); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + if ((int)params[0] != 0) { + gCCPriv->LightingMode |= LightingModeTwoSides; + gCCPriv->MaterialMode |= MaterialModeTwoSides; + } else { + gCCPriv->LightingMode &= ~LightingModeTwoSides; + gCCPriv->MaterialMode &= ~MaterialModeTwoSides; + } + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, LightingMode, gCCPriv->LightingMode); + WRITE(gCCPriv->buf, MaterialMode, gCCPriv->MaterialMode); + break; + } } void _gamma_LightModeli(GLenum pname, GLint param) @@ -1689,10 +1979,173 @@ void _gamma_LightModeliv(GLenum pname, const GLint *params) void _gamma_Lightf(GLenum light, GLenum pname, GLfloat param) { + DEBUG_GLCMDS(("Lightf: %04x %04x %f\n", + (int)light, (int)pname, param)); } void _gamma_Lightfv(GLenum light, GLenum pname, const GLfloat *params) { + GLfloat l,x,y,z; + DEBUG_GLCMDS(("Lightfv: %04x %04x %f\n", + (int)light, (int)pname, *params)); + + switch(light) { + case GL_LIGHT0: + switch (pname) { + case GL_AMBIENT: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + /* We don't do alpha */ + WRITEF(gCCPriv->buf, Light0AmbientIntensityBlue, params[2]); + WRITEF(gCCPriv->buf, Light0AmbientIntensityGreen, params[1]); + WRITEF(gCCPriv->buf, Light0AmbientIntensityRed, params[0]); + break; + case GL_DIFFUSE: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + /* We don't do alpha */ + WRITEF(gCCPriv->buf, Light0DiffuseIntensityBlue, params[2]); + WRITEF(gCCPriv->buf, Light0DiffuseIntensityGreen, params[1]); + WRITEF(gCCPriv->buf, Light0DiffuseIntensityRed, params[0]); + break; + case GL_SPECULAR: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + /* We don't do alpha */ + WRITEF(gCCPriv->buf, Light0SpecularIntensityBlue, params[2]); + WRITEF(gCCPriv->buf, Light0SpecularIntensityGreen, params[1]); + WRITEF(gCCPriv->buf, Light0SpecularIntensityRed, params[0]); + break; + case GL_POSITION: + /* Normalize <x,y,z> */ + x = params[0]; y = params[1]; z = params[2]; + l = sqrt(x*x + y*y + z*z); + x /= l; + y /= l; + z /= l; + if ((int)params[3] != 0) { + gCCPriv->Light0Mode |= Light0ModeAttenuation; + gCCPriv->Light0Mode |= Light0ModeLocal; + } else { + gCCPriv->Light0Mode &= ~Light0ModeAttenuation; + gCCPriv->Light0Mode &= ~Light0ModeLocal; + } + CHECK_DMA_BUFFER(gCC, gCCPriv, 5); + WRITE(gCCPriv->buf, Light0Mode, gCCPriv->Light0Mode); + WRITEF(gCCPriv->buf, Light0PositionW, params[3]); + WRITEF(gCCPriv->buf, Light0PositionZ, z); + WRITEF(gCCPriv->buf, Light0PositionY, y); + WRITEF(gCCPriv->buf, Light0PositionX, x); + break; + case GL_SPOT_DIRECTION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Light0SpotlightDirectionZ, params[3]); + WRITEF(gCCPriv->buf, Light0SpotlightDirectionY, params[2]); + WRITEF(gCCPriv->buf, Light0SpotlightDirectionX, params[1]); + /* WRITEF(gCCPriv->buf, Light0SpotlightDirectionW, params[0]); */ + break; + case GL_SPOT_EXPONENT: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light0SpotlightExponent, params[0]); + break; + case GL_SPOT_CUTOFF: + if ((int)params[0] != -1) + gCCPriv->Light0Mode |= Light0ModeSpotLight; + else + gCCPriv->Light0Mode &= ~Light0ModeSpotLight; + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, Light0Mode, gCCPriv->Light0Mode); + WRITEF(gCCPriv->buf, Light0CosSpotlightCutoffAngle, params[0]); + break; + case GL_CONSTANT_ATTENUATION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light0ConstantAttenuation, params[0]); + break; + case GL_LINEAR_ATTENUATION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light0LinearAttenuation, params[0]); + break; + case GL_QUADRATIC_ATTENUATION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light0QuadraticAttenuation, params[0]); + break; + } + break; + case GL_LIGHT1: + switch (pname) { + case GL_AMBIENT: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + /* We don't do alpha */ + WRITEF(gCCPriv->buf, Light1AmbientIntensityBlue, params[2]); + WRITEF(gCCPriv->buf, Light1AmbientIntensityGreen, params[1]); + WRITEF(gCCPriv->buf, Light1AmbientIntensityRed, params[0]); + break; + case GL_DIFFUSE: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + /* We don't do alpha */ + WRITEF(gCCPriv->buf, Light1DiffuseIntensityBlue, params[2]); + WRITEF(gCCPriv->buf, Light1DiffuseIntensityGreen, params[1]); + WRITEF(gCCPriv->buf, Light1DiffuseIntensityRed, params[0]); + break; + case GL_SPECULAR: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + /* We don't do alpha */ + WRITEF(gCCPriv->buf, Light1SpecularIntensityBlue, params[2]); + WRITEF(gCCPriv->buf, Light1SpecularIntensityGreen, params[1]); + WRITEF(gCCPriv->buf, Light1SpecularIntensityRed, params[0]); + break; + case GL_POSITION: + /* Normalize <x,y,z> */ + x = params[0]; y = params[1]; z = params[2]; + l = sqrt(x*x + y*y + z*z); + x /= l; + y /= l; + z /= l; + if ((int)params[3] != 0) { + gCCPriv->Light1Mode |= Light1ModeAttenuation; + gCCPriv->Light1Mode |= Light1ModeLocal; + } else { + gCCPriv->Light0Mode &= ~Light0ModeAttenuation; + gCCPriv->Light0Mode &= ~Light0ModeLocal; + } + CHECK_DMA_BUFFER(gCC, gCCPriv, 5); + WRITE(gCCPriv->buf, Light1Mode, gCCPriv->Light1Mode); + WRITEF(gCCPriv->buf, Light1PositionW, params[3]); + WRITEF(gCCPriv->buf, Light1PositionZ, z); + WRITEF(gCCPriv->buf, Light1PositionY, y); + WRITEF(gCCPriv->buf, Light1PositionX, x); + break; + case GL_SPOT_DIRECTION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Light1SpotlightDirectionZ, params[3]); + WRITEF(gCCPriv->buf, Light1SpotlightDirectionY, params[2]); + WRITEF(gCCPriv->buf, Light1SpotlightDirectionX, params[1]); + /* WRITEF(gCCPriv->buf, Light1SpotlightDirectionW, params[0]); */ + break; + case GL_SPOT_EXPONENT: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light1SpotlightExponent, params[0]); + break; + case GL_SPOT_CUTOFF: + if ((int)params[0] != -1) + gCCPriv->Light1Mode |= Light1ModeSpotLight; + else + gCCPriv->Light1Mode &= ~Light1ModeSpotLight; + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, Light1Mode, gCCPriv->Light1Mode); + WRITEF(gCCPriv->buf, Light1CosSpotlightCutoffAngle, params[0]); + break; + case GL_CONSTANT_ATTENUATION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light1ConstantAttenuation, params[0]); + break; + case GL_LINEAR_ATTENUATION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light1LinearAttenuation, params[0]); + break; + case GL_QUADRATIC_ATTENUATION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, Light1QuadraticAttenuation, params[0]); + break; + } + } } void _gamma_Lighti(GLenum light, GLenum pname, GLint param) @@ -1817,6 +2270,104 @@ void _gamma_Materialfv(GLenum face, GLenum pname, const GLfloat *params) { DEBUG_GLCMDS(("Materialfv: %04x %04x %f\n", (int)face, (int)pname, *params)); + + gCCPriv->MaterialMode |= MaterialModeEnable; + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, MaterialMode, gCCPriv->MaterialMode); + + if ((face == GL_FRONT) || (face == GL_FRONT_AND_BACK)) { + switch (pname) { + case GL_AMBIENT: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, FrontAmbientColorBlue, params[2]); + WRITEF(gCCPriv->buf, FrontAmbientColorGreen, params[1]); + WRITEF(gCCPriv->buf, FrontAmbientColorRed, params[0]); + break; + case GL_DIFFUSE: + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, FrontAlpha, params[3]); + WRITEF(gCCPriv->buf, FrontDiffuseColorBlue, params[2]); + WRITEF(gCCPriv->buf, FrontDiffuseColorGreen, params[1]); + WRITEF(gCCPriv->buf, FrontDiffuseColorRed, params[0]); + break; + case GL_SPECULAR: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, FrontSpecularColorBlue, params[2]); + WRITEF(gCCPriv->buf, FrontSpecularColorGreen, params[1]); + WRITEF(gCCPriv->buf, FrontSpecularColorRed, params[0]); + break; + case GL_EMISSION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, FrontEmissiveColorBlue, params[2]); + WRITEF(gCCPriv->buf, FrontEmissiveColorGreen, params[1]); + WRITEF(gCCPriv->buf, FrontEmissiveColorRed, params[0]); + break; + case GL_SHININESS: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, FrontSpecularExponent, params[0]); + break; + case GL_AMBIENT_AND_DIFFUSE: + CHECK_DMA_BUFFER(gCC, gCCPriv, 7); + WRITEF(gCCPriv->buf, FrontAmbientColorBlue, params[2]); + WRITEF(gCCPriv->buf, FrontAmbientColorGreen, params[1]); + WRITEF(gCCPriv->buf, FrontAmbientColorRed, params[0]); + WRITEF(gCCPriv->buf, FrontAlpha, params[3]); + WRITEF(gCCPriv->buf, FrontDiffuseColorBlue, params[2]); + WRITEF(gCCPriv->buf, FrontDiffuseColorGreen, params[1]); + WRITEF(gCCPriv->buf, FrontDiffuseColorRed, params[0]); + break; + case GL_COLOR_INDEXES: + /* NOT_DONE */ + break; + } + } + + if ((face == GL_BACK) || (face == GL_FRONT_AND_BACK)) { + switch (pname) { + case GL_AMBIENT: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, BackAmbientColorBlue, params[2]); + WRITEF(gCCPriv->buf, BackAmbientColorGreen, params[1]); + WRITEF(gCCPriv->buf, BackAmbientColorRed, params[0]); + break; + case GL_DIFFUSE: + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, BackAlpha, params[3]); + WRITEF(gCCPriv->buf, BackDiffuseColorBlue, params[2]); + WRITEF(gCCPriv->buf, BackDiffuseColorGreen, params[1]); + WRITEF(gCCPriv->buf, BackDiffuseColorRed, params[0]); + break; + case GL_SPECULAR: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, BackSpecularColorBlue, params[2]); + WRITEF(gCCPriv->buf, BackSpecularColorGreen, params[1]); + WRITEF(gCCPriv->buf, BackSpecularColorRed, params[0]); + break; + case GL_EMISSION: + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, BackEmissiveColorBlue, params[2]); + WRITEF(gCCPriv->buf, BackEmissiveColorGreen, params[1]); + WRITEF(gCCPriv->buf, BackEmissiveColorRed, params[0]); + break; + case GL_SHININESS: + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITEF(gCCPriv->buf, BackSpecularExponent, params[0]); + break; + case GL_AMBIENT_AND_DIFFUSE: + CHECK_DMA_BUFFER(gCC, gCCPriv, 7); + WRITEF(gCCPriv->buf, BackAmbientColorBlue, params[2]); + WRITEF(gCCPriv->buf, BackAmbientColorGreen, params[1]); + WRITEF(gCCPriv->buf, BackAmbientColorRed, params[0]); + WRITEF(gCCPriv->buf, BackAlpha, params[3]); + WRITEF(gCCPriv->buf, BackDiffuseColorBlue, params[2]); + WRITEF(gCCPriv->buf, BackDiffuseColorGreen, params[1]); + WRITEF(gCCPriv->buf, BackDiffuseColorRed, params[0]); + break; + case GL_COLOR_INDEXES: + /* NOT_DONE */ + break; + } + } } void _gamma_Materiali(GLenum face, GLenum pname, GLint param) @@ -1837,9 +2388,9 @@ void _gamma_MatrixMode(GLenum mode) switch (mode) { case GL_TEXTURE: - /* Eanble the Texture transform */ + /* Enable the Texture transform */ CHECK_DMA_BUFFER(gCC, gCCPriv, 1); - WRITE(gCCPriv->buf, TransformModeOr, 0x00000010); + WRITE(gCCPriv->buf, TransformModeOr, XM_XformTexture); case GL_MODELVIEW: case GL_PROJECTION: gCCPriv->MatrixMode = mode; @@ -1878,52 +2429,114 @@ void _gamma_NewList(GLuint list, GLenum mode) void _gamma_Normal3b(GLbyte nx, GLbyte ny, GLbyte nz) { + GLfloat x,y,z; + DEBUG_GLCMDS(("Normal3b: %d %d %d\n", nx, ny, nz)); + + x = BYTE_TO_FLOAT(nx); + y = BYTE_TO_FLOAT(ny); + z = BYTE_TO_FLOAT(nz); + + _gamma_Normal3f(x,y,z); } void _gamma_Normal3bv(const GLbyte *v) { + GLfloat p[3]; + DEBUG_GLCMDS(("Normal3bv: %d %d %d\n", v[0], v[1], v[2])); + + p[0] = BYTE_TO_FLOAT(v[0]); + p[1] = BYTE_TO_FLOAT(v[1]); + p[2] = BYTE_TO_FLOAT(v[2]); + + _gamma_Normal3fv(p); } void _gamma_Normal3d(GLdouble nx, GLdouble ny, GLdouble nz) { DEBUG_GLCMDS(("Normal3d: %f %f %f\n", nx, ny, nz)); + + _gamma_Normal3f((GLfloat)nx,(GLfloat)ny,(GLfloat)nz); } void _gamma_Normal3dv(const GLdouble *v) { DEBUG_GLCMDS(("Normal3dv: %f %f %f\n", v[0], v[1], v[2])); + + _gamma_Normal3fv((GLfloat*)v); } void _gamma_Normal3f(GLfloat nx, GLfloat ny, GLfloat nz) { DEBUG_GLCMDS(("Normal3f: %f %f %f\n", nx, ny, nz)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Nz, nz); + WRITEF(gCCPriv->buf, Ny, ny); + WRITEF(gCCPriv->buf, Nx, nx); } void _gamma_Normal3fv(const GLfloat *v) { DEBUG_GLCMDS(("Normal3fv: %f %f %f\n", v[0], v[1], v[2])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Nz, v[2]); + WRITEF(gCCPriv->buf, Ny, v[1]); + WRITEF(gCCPriv->buf, Nx, v[0]); } void _gamma_Normal3i(GLint nx, GLint ny, GLint nz) { + GLfloat x,y,z; + DEBUG_GLCMDS(("Normal3i: %d %d %d\n", (int)nx, (int)ny, (int)nz)); + + x = INT_TO_FLOAT(nx); + y = INT_TO_FLOAT(ny); + z = INT_TO_FLOAT(nz); + + _gamma_Normal3f(x,y,z); } void _gamma_Normal3iv(const GLint *v) { + GLfloat p[3]; + DEBUG_GLCMDS(("Normal3iv: %d %d %d\n", (int)v[0], (int)v[1], (int)v[2])); + + p[0] = INT_TO_FLOAT(v[0]); + p[1] = INT_TO_FLOAT(v[1]); + p[2] = INT_TO_FLOAT(v[2]); + + _gamma_Normal3fv(p); } void _gamma_Normal3s(GLshort nx, GLshort ny, GLshort nz) { + GLfloat x,y,z; + DEBUG_GLCMDS(("Normal3s: %d %d %d\n", nx, ny, nz)); + + x = SHORT_TO_FLOAT(nx); + y = SHORT_TO_FLOAT(ny); + z = SHORT_TO_FLOAT(nz); + + _gamma_Normal3f(x,y,z); } void _gamma_Normal3sv(const GLshort *v) { + GLfloat p[3]; + DEBUG_GLCMDS(("Normal3sv: %d %d %d\n", v[0], v[1], v[2])); + + p[0] = SHORT_TO_FLOAT(v[0]); + p[1] = SHORT_TO_FLOAT(v[1]); + p[2] = SHORT_TO_FLOAT(v[2]); + + _gamma_Normal3fv(p); } void _gamma_NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) @@ -2020,6 +2633,56 @@ void _gamma_PointSize(GLfloat size) void _gamma_PolygonMode(GLenum face, GLenum mode) { DEBUG_GLCMDS(("PolygonMode: %04x %04x\n", (int)face, (int)mode)); + + gCCPriv->GeometryMode &= ~GM_FB_PolyMask; + + switch (mode) { + case GL_FILL: + switch (face) { + case GL_FRONT: + gCCPriv->GeometryMode |= GM_FrontPolyFill; + break; + case GL_BACK: + gCCPriv->GeometryMode |= GM_BackPolyFill; + break; + case GL_FRONT_AND_BACK: + gCCPriv->GeometryMode |= GM_FrontPolyFill; + gCCPriv->GeometryMode |= GM_BackPolyFill; + break; + } + break; + case GL_LINE: + switch (face) { + case GL_FRONT: + gCCPriv->GeometryMode |= GM_FrontPolyLine; + break; + case GL_BACK: + gCCPriv->GeometryMode |= GM_BackPolyLine; + break; + case GL_FRONT_AND_BACK: + gCCPriv->GeometryMode |= GM_FrontPolyLine; + gCCPriv->GeometryMode |= GM_BackPolyLine; + break; + } + break; + case GL_POINT: + switch (face) { + case GL_FRONT: + gCCPriv->GeometryMode |= GM_FrontPolyPoint; + break; + case GL_BACK: + gCCPriv->GeometryMode |= GM_BackPolyPoint; + break; + case GL_FRONT_AND_BACK: + gCCPriv->GeometryMode |= GM_FrontPolyPoint; + gCCPriv->GeometryMode |= GM_BackPolyPoint; + break; + } + break; + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, GeometryMode, gCCPriv->GeometryMode); } void _gamma_PolygonOffset(GLfloat factor, GLfloat units) @@ -2272,6 +2935,13 @@ void _gamma_Rectdv(const GLdouble *v1, const GLdouble *v2) void _gamma_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) { DEBUG_GLCMDS(("Rectf: %f %f %f %f\n", x1, y1, x2, y2)); + + _gamma_Begin(GL_POLYGON); + _gamma_Vertex2f(x1,y1); + _gamma_Vertex2f(x2,y1); + _gamma_Vertex2f(x2,y2); + _gamma_Vertex2f(x1,y2); + _gamma_End(); } void _gamma_Rectfv(const GLfloat *v1, const GLfloat *v2) @@ -2678,6 +3348,33 @@ void _gamma_TexEnvfv(GLenum target, GLenum pname, const GLfloat *params) { DEBUG_GLCMDS(("TexEnvfv: %04x %04x %f\n", (int)target, (int)pname, *params)); + + if (target != GL_TEXTURE_ENV) { + /* ERROR !! */ + } + + switch (pname) { + case GL_TEXTURE_ENV_MODE: + gCCPriv->curTexObj->TextureColorMode &= ~TCM_ApplicationMask; + switch ((int)params[0]) { + case GL_MODULATE: + gCCPriv->curTexObj->TextureColorMode |= TCM_Modulate; + break; + case GL_DECAL: + gCCPriv->curTexObj->TextureColorMode |= TCM_Decal; + break; + case GL_BLEND: + gCCPriv->curTexObj->TextureColorMode |= TCM_Blend; + break; + case GL_REPLACE: + gCCPriv->curTexObj->TextureColorMode |= TCM_Replace; + break; + } + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, TextureColorMode, + gCCPriv->curTexObj->TextureColorMode); } void _gamma_TexEnvi(GLenum target, GLenum pname, GLint param) @@ -2745,10 +3442,12 @@ void _gamma_TexImage2D(GLenum target, GLint level, GLint components, GLsizei wid if (target == GL_TEXTURE_1D) { /* NOT_DONE */ + DEBUG_ERROR(("TexImage2D: 1D requested - ERROR\n")); } else if (target == GL_TEXTURE_2D) { /* NOT_DONE: The follow are not currently supported... */ - if (border != 0 || format != GL_RGBA || type != GL_UNSIGNED_BYTE || + if (border != 0 /* || format != GL_RGBA */ || type != GL_UNSIGNED_BYTE || (components != 3 && components != 4)) { + DEBUG_ERROR(("TexImage2D: 2D op not supported - ERROR\n")); return; } @@ -2790,7 +3489,11 @@ void _gamma_TexImage2D(GLenum target, GLint level, GLint components, GLsizei wid break; } +#if X_BYTE_ORDER == X_LITTLE_ENDIAN t->TextureFormat = (TF_LittleEndian | +#else + t->TextureFormat = (TF_BigEndian | +#endif TF_ColorOrder_BGR | TF_Compnents_4 | TF_OutputFmt_Texel); @@ -2804,14 +3507,17 @@ void _gamma_TexImage2D(GLenum target, GLint level, GLint components, GLsizei wid t->image[level] = driTMMInsertImage(gCCPriv->tmm, width, height, 1<<l2d, image, NULL); + if (!t->image[level]) { /* NOT_DONE: Handle error */ + DEBUG_ERROR(("TexImage2D: unable1\n")); } /* Make the new image resident (and all of the other mipmaps) */ - if (!driTMMMakeImagesResident(gCCPriv->tmm, MIPMAP_LEVELS, - t->image, addrs)) { + if (driTMMMakeImagesResident(gCCPriv->tmm, MIPMAP_LEVELS, + t->image, addrs) < 0) { /* NOT_DONE: Handle error */ + DEBUG_ERROR(("TexImage2D: unable2\n")); } for (i = 0; i < MIPMAP_LEVELS; i++) @@ -3010,6 +3716,123 @@ void _gamma_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params) { DEBUG_GLCMDS(("TexParameterfv: %04x %04x %f\n", (int)target, (int)pname, *params)); + + if (target == GL_TEXTURE_1D) { + /* NOT_DONE */ + } else if (target == GL_TEXTURE_2D) { + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + gCCPriv->curTexObj2D->TextureReadMode &= ~TRM_Mag_Mask; + switch ((int)params[0]) { + case GL_NEAREST: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Mag_Nearest; + break; + case GL_LINEAR: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Mag_Linear; + break; + default: + break; + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 1); + WRITE(gCCPriv->buf, TextureReadMode, + gCCPriv->curTexObj2D->TextureReadMode); + break; + case GL_TEXTURE_MIN_FILTER: + gCCPriv->curTexObj2D->TextureReadMode &= ~TRM_Min_Mask; + gCCPriv->curTexObj2D->TextureReadMode |= TRM_MipMapEnable; + gCCPriv->curTexObj2D->TextureAddressMode |= TAM_LODEnable; + switch ((int)params[0]) { + case GL_NEAREST: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Min_Nearest; + gCCPriv->curTexObj2D->TextureReadMode &= ~TRM_MipMapEnable; + gCCPriv->curTexObj2D->TextureAddressMode &= ~TAM_LODEnable; + break; + case GL_LINEAR: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Min_Linear; + gCCPriv->curTexObj2D->TextureReadMode &= ~TRM_MipMapEnable; + gCCPriv->curTexObj2D->TextureAddressMode &= ~TAM_LODEnable; + break; + case GL_NEAREST_MIPMAP_NEAREST: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Min_NearestMMNearest; + break; + case GL_LINEAR_MIPMAP_NEAREST: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Min_NearestMMLinear; + break; + case GL_NEAREST_MIPMAP_LINEAR: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Min_LinearMMNearest; + break; + case GL_LINEAR_MIPMAP_LINEAR: + gCCPriv->curTexObj2D->TextureReadMode |= + TRM_Min_LinearMMLinear; + break; + default: + break; + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, TextureReadMode, + gCCPriv->curTexObj2D->TextureReadMode); + WRITE(gCCPriv->buf, TextureAddressMode, + gCCPriv->curTexObj2D->TextureAddressMode); + break; + case GL_TEXTURE_WRAP_S: + gCCPriv->curTexObj2D->TextureAddressMode &= ~TAM_SWrap_Mask; + gCCPriv->curTexObj2D->TextureReadMode &= ~TRM_UWrap_Mask; + switch ((int)params[0]) { + case GL_CLAMP: + gCCPriv->curTexObj2D->TextureAddressMode |= TAM_SWrap_Clamp; + gCCPriv->curTexObj2D->TextureReadMode |= TRM_UWrap_Clamp; + break; + case GL_REPEAT: + gCCPriv->curTexObj2D->TextureAddressMode |= TAM_SWrap_Repeat; + gCCPriv->curTexObj2D->TextureReadMode |= TRM_UWrap_Repeat; + break; + default: + break; + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, TextureReadMode, + gCCPriv->curTexObj2D->TextureReadMode); + WRITE(gCCPriv->buf, TextureAddressMode, + gCCPriv->curTexObj2D->TextureAddressMode); + break; + case GL_TEXTURE_WRAP_T: + gCCPriv->curTexObj2D->TextureAddressMode &= ~TAM_TWrap_Mask; + gCCPriv->curTexObj2D->TextureReadMode &= ~TRM_VWrap_Mask; + switch ((int)params[0]) { + case GL_CLAMP: + gCCPriv->curTexObj2D->TextureAddressMode |= TAM_TWrap_Clamp; + gCCPriv->curTexObj2D->TextureReadMode |= TRM_VWrap_Clamp; + break; + case GL_REPEAT: + gCCPriv->curTexObj2D->TextureAddressMode |= TAM_TWrap_Repeat; + gCCPriv->curTexObj2D->TextureReadMode |= TRM_VWrap_Repeat; + break; + default: + break; + } + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITE(gCCPriv->buf, TextureReadMode, + gCCPriv->curTexObj2D->TextureReadMode); + WRITE(gCCPriv->buf, TextureAddressMode, + gCCPriv->curTexObj2D->TextureAddressMode); + break; + default: + break; + } + } else { + /* ERROR !! */ + } } void _gamma_TexParameteri(GLenum target, GLenum pname, GLint param) @@ -3054,8 +3877,8 @@ void _gamma_TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffs ** format for the image that it is replacing. */ - if (!driTMMSubImage(gCCPriv->tmm, gCCPriv->curTexObj2D->image[level], - xoffset, yoffset, width, height, image)) { + if (driTMMSubImage(gCCPriv->tmm, gCCPriv->curTexObj2D->image[level], + xoffset, yoffset, width, height, image) < 0) { /* NOT_DONE: Handle error */ } } else { @@ -3089,7 +3912,7 @@ void _gamma_Translatef(GLfloat x, GLfloat y, GLfloat z) GLfloat m[16]; int i; - DEBUG_GLCMDS(("Tranlatef: %f %f %f\n", x, y, z)); + DEBUG_GLCMDS(("Translatef: %f %f %f\n", x, y, z)); for (i = 0; i < 16; i++) if (i % 5 == 0) @@ -3108,26 +3931,25 @@ void _gamma_Translatef(GLfloat x, GLfloat y, GLfloat z) void _gamma_Vertex2d(GLdouble x, GLdouble y) { DEBUG_GLCMDS(("Vertex2d: %f %f\n", x, y)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx2, (GLfloat)x); } void _gamma_Vertex2dv(const GLdouble *v) { DEBUG_GLCMDS(("Vertex2dv: %f %f\n", v[0], v[1])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx2, (GLfloat)v[0]); } void _gamma_Vertex2f(GLfloat x, GLfloat y) { DEBUG_GLCMDS(("Vertex2f: %f %f\n", x, y)); -#ifdef RANDOMIZE_COLORS - { - GLuint c; - c = (random() / (double)RAND_MAX) * 16777216; - CHECK_DMA_BUFFER(gCC, gCCPriv, 1); - WRITE(gCCPriv->buf, PackedColor4, c); - } -#endif - CHECK_DMA_BUFFER(gCC, gCCPriv, 2); WRITEF(gCCPriv->buf, Vy, y); WRITEF(gCCPriv->buf, Vx2, x); @@ -3136,51 +3958,72 @@ void _gamma_Vertex2f(GLfloat x, GLfloat y) void _gamma_Vertex2fv(const GLfloat *v) { DEBUG_GLCMDS(("Vertex2fv: %f %f\n", v[0], v[1])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITEF(gCCPriv->buf, Vy, v[1]); + WRITEF(gCCPriv->buf, Vx2, v[0]); } void _gamma_Vertex2i(GLint x, GLint y) { DEBUG_GLCMDS(("Vertex2i: %d %d\n", (int)x, (int)y)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx2, (GLfloat)x); } void _gamma_Vertex2iv(const GLint *v) { DEBUG_GLCMDS(("Vertex2iv: %d %d\n", (int)v[0], (int)v[1])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx2, (GLfloat)v[0]); } void _gamma_Vertex2s(GLshort x, GLshort y) { DEBUG_GLCMDS(("Vertex2s: %d %d\n", x, y)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx2, (GLfloat)x); } void _gamma_Vertex2sv(const GLshort *v) { DEBUG_GLCMDS(("Vertex2sv: %d %d\n", v[0], v[1])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 2); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx2, (GLfloat)v[0]); } void _gamma_Vertex3d(GLdouble x, GLdouble y, GLdouble z) { DEBUG_GLCMDS(("Vertex3d: %f %f %f\n", x, y, z)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Vz, (GLfloat)z); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx3, (GLfloat)x); } void _gamma_Vertex3dv(const GLdouble *v) { DEBUG_GLCMDS(("Vertex2fv: %f %f %f\n", v[0], v[1], v[2])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Vz, (GLfloat)v[2]); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx3, (GLfloat)v[0]); } void _gamma_Vertex3f(GLfloat x, GLfloat y, GLfloat z) { DEBUG_GLCMDS(("Vertex3f: %f %f %f\n", x, y, z)); -#ifdef RANDOMIZE_COLORS - { - GLuint c; - c = (random() / (double)RAND_MAX) * 16777216; - CHECK_DMA_BUFFER(gCC, gCCPriv, 1); - WRITE(gCCPriv->buf, PackedColor4, c); - } -#endif - CHECK_DMA_BUFFER(gCC, gCCPriv, 3); WRITEF(gCCPriv->buf, Vz, z); WRITEF(gCCPriv->buf, Vy, y); @@ -3191,15 +4034,6 @@ void _gamma_Vertex3fv(const GLfloat *v) { DEBUG_GLCMDS(("Vertex3fv: %f %f %f\n", v[0], v[1], v[2])); -#ifdef RANDOMIZE_COLORS - { - GLuint c; - c = (random() / (double)RAND_MAX) * 16777216; - CHECK_DMA_BUFFER(gCC, gCCPriv, 1); - WRITE(gCCPriv->buf, PackedColor4, c); - } -#endif - CHECK_DMA_BUFFER(gCC, gCCPriv, 3); WRITEF(gCCPriv->buf, Vz, v[2]); WRITEF(gCCPriv->buf, Vy, v[1]); @@ -3209,62 +4043,130 @@ void _gamma_Vertex3fv(const GLfloat *v) void _gamma_Vertex3i(GLint x, GLint y, GLint z) { DEBUG_GLCMDS(("Vertex3i: %d %d %d\n", (int)x, (int)y, (int)z)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Vz, (GLfloat)z); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx3, (GLfloat)x); } void _gamma_Vertex3iv(const GLint *v) { DEBUG_GLCMDS(("Vertex3iv: %d %d %d\n", (int)v[0], (int)v[1], (int)v[2])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Vz, (GLfloat)v[2]); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx3, (GLfloat)v[0]); } void _gamma_Vertex3s(GLshort x, GLshort y, GLshort z) { DEBUG_GLCMDS(("Vertex3s: %d %d %d\n", x, y, z)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Vz, (GLfloat)z); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx3, (GLfloat)x); } void _gamma_Vertex3sv(const GLshort *v) { DEBUG_GLCMDS(("Vertex3sv: %d %d %d\n", v[0], v[1], v[2])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 3); + WRITEF(gCCPriv->buf, Vz, (GLfloat)v[2]); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx3, (GLfloat)v[0]); } void _gamma_Vertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) { DEBUG_GLCMDS(("Vertex4d: %f %f %f %f\n", x, y, z, w)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, (GLfloat)w); + WRITEF(gCCPriv->buf, Vz, (GLfloat)z); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx4,(GLfloat)x); } void _gamma_Vertex4dv(const GLdouble *v) { DEBUG_GLCMDS(("Vertex4dv: %f %f %f %f\n", v[0], v[1], v[2], v[3])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, (GLfloat)v[3]); + WRITEF(gCCPriv->buf, Vz, (GLfloat)v[2]); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx4, (GLfloat)v[0]); } void _gamma_Vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) { DEBUG_GLCMDS(("Vertex4f: %f %f %f %f\n", x, y, z, w)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, w); + WRITEF(gCCPriv->buf, Vz, z); + WRITEF(gCCPriv->buf, Vy, y); + WRITEF(gCCPriv->buf, Vx4, x); } void _gamma_Vertex4fv(const GLfloat *v) { DEBUG_GLCMDS(("Vertex4fv: %f %f %f %f\n", v[0], v[1], v[2], v[3])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, v[3]); + WRITEF(gCCPriv->buf, Vz, v[2]); + WRITEF(gCCPriv->buf, Vy, v[1]); + WRITEF(gCCPriv->buf, Vx4, v[0]); } void _gamma_Vertex4i(GLint x, GLint y, GLint z, GLint w) { DEBUG_GLCMDS(("Vertex4i: %d %d %d %d\n", (int)x, (int)y, (int)z, (int)w)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, (GLfloat)w); + WRITEF(gCCPriv->buf, Vz, (GLfloat)z); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx4, (GLfloat)x); } void _gamma_Vertex4iv(const GLint *v) { DEBUG_GLCMDS(("Vertex4iv: %d %d %d %d\n", (int)v[0], (int)v[1], (int)v[2], (int)v[3])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, (GLfloat)v[3]); + WRITEF(gCCPriv->buf, Vz, (GLfloat)v[2]); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx4, (GLfloat)v[0]); } void _gamma_Vertex4s(GLshort x, GLshort y, GLshort z, GLshort w) { DEBUG_GLCMDS(("Vertex4s: %d %d %d %d\n", x, y, z, w)); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, (GLfloat)w); + WRITEF(gCCPriv->buf, Vz, (GLfloat)z); + WRITEF(gCCPriv->buf, Vy, (GLfloat)y); + WRITEF(gCCPriv->buf, Vx4,(GLfloat)x); } void _gamma_Vertex4sv(const GLshort *v) { DEBUG_GLCMDS(("Vertex4sv: %d %d %d %d\n", v[0], v[1], v[2], v[3])); + + CHECK_DMA_BUFFER(gCC, gCCPriv, 4); + WRITEF(gCCPriv->buf, Vw, (GLfloat)v[3]); + WRITEF(gCCPriv->buf, Vz, (GLfloat)v[2]); + WRITEF(gCCPriv->buf, Vy, (GLfloat)v[1]); + WRITEF(gCCPriv->buf, Vx4, (GLfloat)v[0]); } void _gamma_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) @@ -3296,10 +4198,13 @@ void _gamma_Viewport(GLint x, GLint y, GLsizei width, GLsizei height) oy = y + sy; CHECK_DMA_BUFFER(gCC, gCCPriv, 4); - WRITEF(gCCPriv->buf, ViewPortOffsetX, ox); - WRITEF(gCCPriv->buf, ViewPortOffsetY, oy); WRITEF(gCCPriv->buf, ViewPortScaleX, sx); WRITEF(gCCPriv->buf, ViewPortScaleY, sy); + WRITEF(gCCPriv->buf, ViewPortOffsetX, ox); + WRITEF(gCCPriv->buf, ViewPortOffsetY, oy); +#if 1 /* Err - this shouldn't be needed, but something isn't flushing */ + FLUSH_DMA_BUFFER(gCC,gCCPriv); +#endif } diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_init.h b/xc/lib/GL/mesa/src/drv/gamma/gamma_init.h index ce804d018..e8fd5a0df 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/gamma_init.h +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_init.h @@ -43,7 +43,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "gamma_regs.h" #include "gamma_macros.h" #include "gamma_texture.h" -#include "xmesaP.h" typedef struct { int regionCount; /* Count of register regions */ @@ -109,6 +108,12 @@ typedef struct { int AB_FBReadMode; int AB_FBReadMode_Save; int DeltaMode; + int ColorMaterialMode; + int MaterialMode; + int LightingMode; + int Light0Mode; + int Light1Mode; + int ScissorMode; int Window; /* GID part probably should be in draw priv */ gammaTexObj *curTexObj; @@ -140,8 +145,8 @@ extern void gammaLoadHWMatrix(void); extern void gammaInitHW(gammaContextPrivate *gcp); extern float IdentityMatrix[16]; -extern XMesaContext nullCC; -extern XMesaContext gCC; +extern __DRIcontextPrivate *nullCC; +extern __DRIcontextPrivate *gCC; extern gammaContextPrivate *gCCPriv; #endif diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_inithw.c b/xc/lib/GL/mesa/src/drv/gamma/gamma_inithw.c index edb1d3da0..87d68278b 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/gamma_inithw.c +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_inithw.c @@ -29,27 +29,32 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* * Authors: * Kevin E. Martin <kevin@precisioninsight.com> + * Alan Hourihane <Alan.Hourihane@btinternet.com> * */ #ifdef GLX_DIRECT_RENDERING #include "gamma_init.h" +#include "glint_dri.h" void gammaInitHW(gammaContextPrivate *gcp) { __DRIscreenPrivate *driScrnPriv = gcp->gammaScrnPriv->driScrnPriv; + GLINTDRIPtr gDRIPriv = (GLINTDRIPtr)driScrnPriv->pDevPriv; - /* Set up each MX's ScanLineOwnership for OpenGL */ - CHECK_DMA_BUFFER(nullCC, gcp, 4); - WRITE(gcp->buf, BroadcastMask, 1); - WRITE(gcp->buf, ScanLineOwnership, 5); /* Use bottom left as [0,0] */ - WRITE(gcp->buf, BroadcastMask, 2); - WRITE(gcp->buf, ScanLineOwnership, 1); /* Use bottom left as [0,0] */ + if (gDRIPriv->numMXDevices == 2) { + /* Set up each MX's ScanLineOwnership for OpenGL */ + CHECK_DMA_BUFFER(nullCC, gcp, 4); + WRITE(gcp->buf, BroadcastMask, 1); + WRITE(gcp->buf, ScanLineOwnership, 5); /* Use bottom left as [0,0] */ + WRITE(gcp->buf, BroadcastMask, 2); + WRITE(gcp->buf, ScanLineOwnership, 1); /* Use bottom left as [0,0] */ - /* Broadcast to both MX's */ - CHECK_DMA_BUFFER(nullCC, gcp, 1); - WRITE(gcp->buf, BroadcastMask, 3); + /* Broadcast to both MX's */ + CHECK_DMA_BUFFER(nullCC, gcp, 1); + WRITE(gcp->buf, BroadcastMask, 3); + } /* Set MXs to known state */ CHECK_DMA_BUFFER(nullCC, gcp, 27); @@ -82,6 +87,7 @@ void gammaInitHW(gammaContextPrivate *gcp) WRITE(gcp->buf, PixelSize, 0); /* Set Gamma to known state */ + CHECK_DMA_BUFFER(nullCC, gcp, 10); WRITE(gcp->buf, TriangleMode, 0); WRITE(gcp->buf, GeometryMode, 0); WRITE(gcp->buf, NormalizeMode, 0); @@ -136,7 +142,10 @@ void gammaInitHW(gammaContextPrivate *gcp) WRITE(gcp->buf, AlphaTestMode, gcp->AlphaTestMode); WRITE(gcp->buf, AlphaBlendMode, gcp->AlphaBlendMode); WRITE(gcp->buf, DitherMode, DitherModeEnable | DM_ColorOrder_RGB); - WRITE(gcp->buf, RasterizerMode, RM_MultiGLINT | RM_BiasCoordNearHalf); + if (gDRIPriv->numMXDevices == 2) + WRITE(gcp->buf, RasterizerMode, RM_MultiGLINT | RM_BiasCoordNearHalf); + else + WRITE(gcp->buf, RasterizerMode, RM_BiasCoordNearHalf); WRITE(gcp->buf, GLINTWindow, gcp->Window); WRITE(gcp->buf, FastClearDepth, 0xffffffff); WRITE(gcp->buf, GLINTDepth, 0xffffffff); @@ -242,7 +251,7 @@ void gammaInitHW(gammaContextPrivate *gcp) CHECK_DMA_BUFFER(nullCC, gcp, 5); WRITE(gcp->buf, GeometryMode, gcp->GeometryMode); WRITE(gcp->buf, NormalizeMode, NormalizeModeDisable); - WRITE(gcp->buf, LightingMode, LightingModeDisable); + WRITE(gcp->buf, LightingMode, gcp->LightingMode); WRITE(gcp->buf, ColorMaterialMode, ColorMaterialModeDisable); WRITE(gcp->buf, MaterialMode, MaterialModeDisable); @@ -251,18 +260,18 @@ void gammaInitHW(gammaContextPrivate *gcp) WRITE(gcp->buf, BackSpecularExponent, 0); /* fixed point */ CHECK_DMA_BUFFER(nullCC, gcp, 29); - WRITEF(gcp->buf, FrontAmbientColorRed, 0.0); - WRITEF(gcp->buf, FrontAmbientColorGreen, 0.0); - WRITEF(gcp->buf, FrontAmbientColorBlue, 0.0); - WRITEF(gcp->buf, BackAmbientColorRed, 0.0); - WRITEF(gcp->buf, BackAmbientColorGreen, 0.0); - WRITEF(gcp->buf, BackAmbientColorBlue, 0.0); - WRITEF(gcp->buf, FrontDiffuseColorRed, 0.0); - WRITEF(gcp->buf, FrontDiffuseColorGreen, 0.0); - WRITEF(gcp->buf, FrontDiffuseColorBlue, 0.0); - WRITEF(gcp->buf, BackDiffuseColorRed, 0.0); - WRITEF(gcp->buf, BackDiffuseColorGreen, 0.0); - WRITEF(gcp->buf, BackDiffuseColorBlue, 0.0); + WRITEF(gcp->buf, FrontAmbientColorRed, 0.2); + WRITEF(gcp->buf, FrontAmbientColorGreen, 0.2); + WRITEF(gcp->buf, FrontAmbientColorBlue, 0.2); + WRITEF(gcp->buf, BackAmbientColorRed, 0.2); + WRITEF(gcp->buf, BackAmbientColorGreen, 0.2); + WRITEF(gcp->buf, BackAmbientColorBlue, 0.2); + WRITEF(gcp->buf, FrontDiffuseColorRed, 0.8); + WRITEF(gcp->buf, FrontDiffuseColorGreen, 0.8); + WRITEF(gcp->buf, FrontDiffuseColorBlue, 0.8); + WRITEF(gcp->buf, BackDiffuseColorRed, 0.8); + WRITEF(gcp->buf, BackDiffuseColorGreen, 0.8); + WRITEF(gcp->buf, BackDiffuseColorBlue, 0.8); WRITEF(gcp->buf, FrontSpecularColorRed, 0.0); WRITEF(gcp->buf, FrontSpecularColorGreen, 0.0); WRITEF(gcp->buf, FrontSpecularColorBlue, 0.0); @@ -275,11 +284,11 @@ void gammaInitHW(gammaContextPrivate *gcp) WRITEF(gcp->buf, BackEmissiveColorRed, 0.0); WRITEF(gcp->buf, BackEmissiveColorGreen, 0.0); WRITEF(gcp->buf, BackEmissiveColorBlue, 0.0); - WRITEF(gcp->buf, SceneAmbientColorRed, 0.0); - WRITEF(gcp->buf, SceneAmbientColorGreen, 0.0); - WRITEF(gcp->buf, SceneAmbientColorBlue, 0.0); - WRITEF(gcp->buf, FrontAlpha, 0.0); - WRITEF(gcp->buf, BackAlpha, 0.0); + WRITEF(gcp->buf, SceneAmbientColorRed, 0.2); + WRITEF(gcp->buf, SceneAmbientColorGreen, 0.2); + WRITEF(gcp->buf, SceneAmbientColorBlue, 0.2); + WRITEF(gcp->buf, FrontAlpha, 1.0); + WRITEF(gcp->buf, BackAlpha, 1.0); CHECK_DMA_BUFFER(nullCC, gcp, 8); WRITE(gcp->buf, PointMode, (PM_AntialiasDisable | @@ -319,28 +328,28 @@ void gammaInitHW(gammaContextPrivate *gcp) WRITE(gcp->buf, Light14Mode, LNM_Off); WRITE(gcp->buf, Light15Mode, LNM_Off); - CHECK_DMA_BUFFER(nullCC, gcp, 21); - WRITEF(gcp->buf, FrontAmbientColorRed, 1.0); - WRITEF(gcp->buf, FrontAmbientColorGreen, 1.0); - WRITEF(gcp->buf, FrontAmbientColorBlue, 1.0); - WRITEF(gcp->buf, BackAmbientColorRed, 1.0); - WRITEF(gcp->buf, BackAmbientColorGreen, 1.0); - WRITEF(gcp->buf, BackAmbientColorBlue, 1.0); - WRITEF(gcp->buf, FrontDiffuseColorRed, 1.0); - WRITEF(gcp->buf, FrontDiffuseColorGreen, 1.0); - WRITEF(gcp->buf, FrontDiffuseColorBlue, 1.0); - WRITEF(gcp->buf, BackDiffuseColorRed, 1.0); - WRITEF(gcp->buf, BackDiffuseColorGreen, 1.0); - WRITEF(gcp->buf, BackDiffuseColorBlue, 1.0); - WRITEF(gcp->buf, FrontSpecularColorRed, 0.0); - WRITEF(gcp->buf, FrontSpecularColorGreen, 0.0); - WRITEF(gcp->buf, FrontSpecularColorBlue, 0.0); - WRITEF(gcp->buf, BackSpecularColorRed, 0.0); - WRITEF(gcp->buf, BackSpecularColorGreen, 0.0); - WRITEF(gcp->buf, BackSpecularColorBlue, 0.0); - WRITEF(gcp->buf, SceneAmbientColorRed, 0.0); - WRITEF(gcp->buf, SceneAmbientColorGreen, 0.0); - WRITEF(gcp->buf, SceneAmbientColorBlue, 0.0); + CHECK_DMA_BUFFER(nullCC, gcp, 22); + WRITEF(gcp->buf, Light0AmbientIntensityBlue, 0.0); + WRITEF(gcp->buf, Light0AmbientIntensityGreen, 0.0); + WRITEF(gcp->buf, Light0AmbientIntensityRed, 0.0); + WRITEF(gcp->buf, Light0DiffuseIntensityBlue, 1.0); + WRITEF(gcp->buf, Light0DiffuseIntensityGreen, 1.0); + WRITEF(gcp->buf, Light0DiffuseIntensityRed, 1.0); + WRITEF(gcp->buf, Light0SpecularIntensityBlue, 1.0); + WRITEF(gcp->buf, Light0SpecularIntensityGreen, 1.0); + WRITEF(gcp->buf, Light0SpecularIntensityRed, 1.0); + WRITEF(gcp->buf, Light0SpotlightDirectionZ, 0.0); + WRITEF(gcp->buf, Light0SpotlightDirectionY, 0.0); + WRITEF(gcp->buf, Light0SpotlightDirectionX, -1.0); + WRITEF(gcp->buf, Light0SpotlightExponent, 0.0); + WRITEF(gcp->buf, Light0PositionZ, 0.0); + WRITEF(gcp->buf, Light0PositionY, 0.0); + WRITEF(gcp->buf, Light0PositionX, 1.0); + WRITEF(gcp->buf, Light0PositionW, 0.0); + WRITEF(gcp->buf, Light0CosSpotlightCutoffAngle, -1.0); + WRITEF(gcp->buf, Light0ConstantAttenuation, 1.0); + WRITEF(gcp->buf, Light0LinearAttenuation, 0.0); + WRITEF(gcp->buf, Light0QuadraticAttenuation,0.0); CHECK_DMA_BUFFER(nullCC, gcp, 6); WRITEF(gcp->buf, ViewPortScaleX, (gcp->w)/2.0); diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_matrix.c b/xc/lib/GL/mesa/src/drv/gamma/gamma_matrix.c index f6c166609..17220fbb4 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/gamma_matrix.c +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_matrix.c @@ -163,9 +163,7 @@ void gammaLoadHWMatrix(void) WRITEF(gCCPriv->buf, ModelViewMatrix13, gCCPriv->ModelView[13]); WRITEF(gCCPriv->buf, ModelViewMatrix14, gCCPriv->ModelView[14]); WRITEF(gCCPriv->buf, ModelViewMatrix15, gCCPriv->ModelView[15]); - /* Fall through to load ModelViewProjectionMatrix */ #endif - case GL_PROJECTION: CHECK_DMA_BUFFER(gCC, gCCPriv, 16); WRITEF(gCCPriv->buf, diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_regs.h b/xc/lib/GL/mesa/src/drv/gamma/gamma_regs.h index 3dd4b8783..b13dbdba5 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/gamma_regs.h +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_regs.h @@ -163,6 +163,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FBWriteModeEnable 0x00000001 #define FBW_UploadColorData 0x00000008 +/* FogMode */ +#define FogModeDisable 0x00000000 +#define FogModeEnable 0x00000001 + /* LBWriteMode */ #define LBWriteModeDisable 0x00000000 #define LBWriteModeEnable 0x00000001 @@ -391,14 +395,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define GM_FogLinear 0x00000000 #define GM_FogExp 0x00000004 #define GM_FogExpSquared 0x00000008 +#define GM_FogMask 0x0000000C #define GM_FrontPolyPoint 0x00000000 #define GM_FrontPolyLine 0x00000010 #define GM_FrontPolyFill 0x00000020 #define GM_BackPolyPoint 0x00000000 #define GM_BackPolyLine 0x00000040 #define GM_BackPolyFill 0x00000080 +#define GM_FB_PolyMask 0x000000F0 #define GM_FrontFaceCW 0x00000000 #define GM_FrontFaceCCW 0x00000100 +#define GM_FFMask 0x00000100 #define GM_PolyCullDisable 0x00000000 #define GM_PolyCullEnable 0x00000200 #define GM_PolyCullFront 0x00000000 @@ -480,18 +487,44 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* LightingMode */ #define LightingModeDisable 0x00000000 #define LightingModeEnable 0x00000001 +#define LightingModeTwoSides 0x00000002 +#define LightingModeLocalViewer 0x00000008 + +/* Light0Mode */ +#define Light0ModeDisable 0x00000000 +#define Light0ModeEnable 0x00000001 +#define Light0ModeSpotLight 0x00000002 +#define Light0ModeAttenuation 0x00000004 +#define Light0ModeLocal 0x00000008 + +/* Light0Mode */ +#define Light1ModeDisable 0x00000000 +#define Light1ModeEnable 0x00000001 +#define Light1ModeSpotLight 0x00000002 +#define Light1ModeAttenuation 0x00000004 +#define Light1ModeLocal 0x00000008 /* ColorMaterialMode */ #define ColorMaterialModeDisable 0x00000000 #define ColorMaterialModeEnable 0x00000001 +#define ColorMaterialModeFront 0x00000000 +#define ColorMaterialModeBack 0x00000002 +#define ColorMaterialModeFrontAndBack 0x00000004 +#define ColorMaterialModeEmission 0x00000000 +#define ColorMaterialModeAmbient 0x00000008 +#define ColorMaterialModeDiffuse 0x00000010 +#define ColorMaterialModeSpecular 0x00000018 +#define ColorMaterialModeAmbAndDiff 0x00000020 +#define ColorMaterialModeMask 0x0000003e /* MaterialMode */ #define MaterialModeDisable 0x00000000 #define MaterialModeEnable 0x00000001 +#define MaterialModeTwoSides 0x00000080 /* DeltaMode */ #define DM_Target300SX 0x00000000 -#define DM_Target300TXMX 0x00000001 +#define DM_Target500TXMX 0x00000001 #define DM_Depth16 0x00000004 #define DM_Depth24 0x00000008 #define DM_Depth32 0x0000000c diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_texture.c b/xc/lib/GL/mesa/src/drv/gamma/gamma_texture.c index 14a993969..ffa437ed2 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/gamma_texture.c +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_texture.c @@ -34,6 +34,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING +#include <Xarch.h> #include <X11/Xlibint.h> #include "gamma_init.h" #include <string.h> @@ -74,7 +75,11 @@ void gammaTOInit(gammaTexObj *t) t->TextureFilterMode = (TextureFilterModeDisable); +#if X_BYTE_ORDER == X_LITTLE_ENDIAN t->TextureFormat = (TF_LittleEndian | +#else + t->TextureFormat = (TF_BigEndian | +#endif TF_16Bit_565 | TF_ColorOrder_RGB | TF_Compnents_4 | diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_xmesa.c b/xc/lib/GL/mesa/src/drv/gamma/gamma_xmesa.c index 450b081a3..b199bc073 100644 --- a/xc/lib/GL/mesa/src/drv/gamma/gamma_xmesa.c +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_xmesa.c @@ -30,6 +30,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <kevin@precisioninsight.com> * Brian Paul <brian@precisioninsight.com> + * Alan Hourihane <Alan.Hourihane@btinternet.com> */ #ifdef GLX_DIRECT_RENDERING @@ -38,6 +39,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "gamma_init.h" #include "gamma_gl.h" #include "glapi.h" +#include "glint_dri.h" #include "context.h" #include "mmath.h" @@ -144,6 +146,7 @@ GLboolean XMesaCreateContext( Display *dpy, gammaContextPrivate *cPriv; __DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv; gammaScreenPrivate *gPriv = (gammaScreenPrivate *)driScrnPriv->private; + GLINTDRIPtr gDRIPriv = (GLINTDRIPtr)driScrnPriv->pDevPriv; if (!Dispatch) { GLuint size = _glapi_get_dispatch_table_size() * sizeof(GLvoid *); @@ -194,27 +197,26 @@ GLboolean XMesaCreateContext( Display *dpy, cPriv->ModelViewProj[i] = cPriv->Texture[i] = 0.0; - /* - ** NOT_DONE: The 0xe4 in LBReadMode and FBReadMode refers to the - ** partial products for the 640x480 mode. We will need to look up - ** the partial products in a table (c.f., glint_driver.c) to support - ** other FB sizes. - */ cPriv->LBReadMode = (LBReadSrcDisable | LBReadDstDisable | LBDataTypeDefault | LBWindowOriginBot | - LBScanLineInt2 | - 0xe4); /* NOT_DONE: 640x480 partial products */ + gDRIPriv->pprod); cPriv->FBReadMode = (FBReadSrcDisable | FBReadDstDisable | FBDataTypeDefault | FBWindowOriginBot | - FBScanLineInt2 | - 0xe4); /* NOT_DONE: 640x480 partial products */ - - cPriv->FBWindowBase = driScrnPriv->fbWidth * (driScrnPriv->fbHeight/2 - 1); - cPriv->LBWindowBase = driScrnPriv->fbWidth * (driScrnPriv->fbHeight/2 - 1); + gDRIPriv->pprod); + + if (gDRIPriv->numMXDevices == 2) { + cPriv->LBReadMode |= LBScanLineInt2; + cPriv->FBReadMode |= FBScanLineInt2; + cPriv->FBWindowBase =driScrnPriv->fbWidth*(driScrnPriv->fbHeight/2 - 1); + cPriv->LBWindowBase =driScrnPriv->fbWidth*(driScrnPriv->fbHeight/2 - 1); + } else { + cPriv->FBWindowBase = driScrnPriv->fbWidth * driScrnPriv->fbHeight; + cPriv->LBWindowBase = driScrnPriv->fbWidth * driScrnPriv->fbHeight; + } cPriv->Begin = (B_AreaStippleDisable | B_LineStippleDisable | @@ -306,7 +308,7 @@ GLboolean XMesaCreateContext( Display *dpy, 4, 1, gammaTOLoad, gammaTOLoadSub); - + cPriv->curTexObj = gammaTOFind(0); cPriv->curTexObj1D = cPriv->curTexObj; cPriv->curTexObj2D = cPriv->curTexObj; @@ -334,7 +336,7 @@ GLboolean XMesaCreateContext( Display *dpy, cPriv->DeltaMode = (DM_SubPixlCorrectionEnable | DM_SmoothShadingEnable | - DM_Target300TXMX); + DM_Target500TXMX); switch (cPriv->DepthSize) { case 16: @@ -352,6 +354,14 @@ GLboolean XMesaCreateContext( Display *dpy, cPriv->gammaScrnPriv = gPriv; + cPriv->LightingMode = LightingModeDisable; + cPriv->Light0Mode = LNM_Off; + cPriv->Light1Mode = LNM_Off; + + cPriv->MaterialMode = MaterialModeDisable; + + cPriv->ScissorMode = UserScissorDisable | ScreenScissorDisable; + driContextPriv->driverPrivate = cPriv; /* Initialize the HW to a known state */ @@ -491,7 +501,6 @@ GLboolean XMesaMakeCurrent(__DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driDrawPriv, __DRIdrawablePrivate *driReadPriv) { - if (driContextPriv) { gCC = driContextPriv; gCCPriv = (gammaContextPrivate *) driContextPriv->driverPrivate; @@ -503,6 +512,8 @@ GLboolean XMesaMakeCurrent(__DRIcontextPrivate *driContextPriv, WRITE(gCCPriv->buf, GLINTWindow, gCCPriv->Window); _glapi_set_dispatch(Dispatch); + + _gamma_Viewport(0, 0, driDrawPriv->w, driDrawPriv->h); } else { gCC = NULL; gCCPriv = NULL; diff --git a/xc/lib/GL/mesa/src/drv/i810/Imakefile b/xc/lib/GL/mesa/src/drv/i810/Imakefile index 7260846fd..6b72c80e4 100644 --- a/xc/lib/GL/mesa/src/drv/i810/Imakefile +++ b/xc/lib/GL/mesa/src/drv/i810/Imakefile @@ -1,4 +1,6 @@ +#include <Threads.tmpl> + #define DoNormalLib NormalLibGlx #define DoSharedLib SharedLibGlx #define DoExtraLib SharedLibGlx @@ -9,13 +11,22 @@ ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL #endif +#if defined(LinuxArchitecture) +OS_SUBDIR = linux +#endif +#if defined(FreeBSDArchitecture) +OS_SUBDIR = bsd +#endif + #if BuildXF86DRI DRI_DEFINES = GlxDefines -DDRIVERTS DRI_INCLUDES = -I../../../../dri -I../../../../glx \ + -I../../../dri \ -I$(TOP)/include -I$(TOP)/include/GL \ -I$(XF86OSSRC) -I$(SERVERSRC)/GL/dri \ -I$(XF86DRIVERSRC)/i810 \ - -I../../../include -I../.. -I../common -I../../X + -I../../../include -I../.. -I../common -I../../X \ + -I$(XF86OSSRC)/$(OS_SUBDIR)/drm/kernel #endif MESA_INCLUDES = -I. -I.. -I../../include @@ -23,20 +34,244 @@ MESA_INCLUDES = -I. -I.. -I../../include DEFINES = $(ALLOC_DEFINES) $(DRI_DEFINES) - INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) \ - -I/usr/include/glide - DRISRCS = i810_xmesa.c i810clear.c \ - i810dd.c i810depth.c i810dma.c i810ring.c \ - i810pipeline.c i810span.c i810state.c i810swap.c \ - i810tex.c i810tris.c i810vb.c i810fastpath.c + INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) + + DRISRCS = ../../../dri/dri_mesa.c \ + ../../../../dri/dri_tmm.c + + DRIOBJS = ../../../dri/dri_mesa.o \ + ../../../../dri/dri_tmm.o + + DRMSRCS = ../../../../dri/drm/xf86drm.c \ + ../../../../dri/drm/xf86drmHash.c \ + ../../../../dri/drm/xf86drmRandom.c \ + ../../../../dri/drm/xf86drmSL.c + + DRMOBJS = ../../../../dri/drm/xf86drm.o \ + ../../../../dri/drm/xf86drmHash.o \ + ../../../../dri/drm/xf86drmRandom.o \ + ../../../../dri/drm/xf86drmSL.o + + + I810SRCS = i810_xmesa.c \ + i810dd.c \ + i810pipeline.c i810span.c i810state.c \ + i810tex.c i810tris.c i810vb.c i810fastpath.c i810ioctl.c + + I810OBJS = i810_xmesa.o \ + i810dd.o \ + i810pipeline.o i810span.o i810state.o \ + i810tex.o i810tris.o i810vb.o i810fastpath.o i810ioctl.o + + MESASRCS = ../../aatriangle.c \ + ../../accum.c \ + ../../alpha.c \ + ../../alphabuf.c \ + ../../attrib.c \ + ../../bbox.c \ + ../../bitmap.c \ + ../../blend.c \ + ../../buffers.c \ + ../../clip.c \ + ../../colortab.c \ + ../../config.c \ + ../../context.c \ + ../../copypix.c \ + ../../cva.c \ + ../../debug_xform.c \ + ../../depth.c \ + ../../dlist.c \ + ../../drawpix.c \ + ../../enable.c \ + ../../enums.c \ + ../../eval.c \ + ../../extensions.c \ + ../../feedback.c \ + ../../fog.c \ + ../../get.c \ + ../../glapi.c \ + ../../glapinoop.c \ + ../../glthread.c \ + ../../hash.c \ + ../../image.c \ + ../../imaging.c \ + ../../light.c \ + ../../lines.c \ + ../../logic.c \ + ../../masking.c \ + ../../matrix.c \ + ../../mem.c \ + ../../mmath.c \ + ../../pb.c \ + ../../pipeline.c \ + ../../pixel.c \ + ../../pixeltex.c \ + ../../points.c \ + ../../polygon.c \ + ../../quads.c \ + ../../rastpos.c \ + ../../readpix.c \ + ../../rect.c \ + ../../scissor.c \ + ../../shade.c \ + ../../span.c \ + ../../stages.c \ + ../../state.c \ + ../../stencil.c \ + ../../teximage.c \ + ../../texobj.c \ + ../../texstate.c \ + ../../texture.c \ + ../../texutil.c \ + ../../translate.c \ + ../../triangle.c \ + ../../varray.c \ + ../../vb.c \ + ../../vbcull.c \ + ../../vbfill.c \ + ../../vbindirect.c \ + ../../vbrender.c \ + ../../vbxform.c \ + ../../vector.c \ + ../../vertices.c \ + ../../winpos.c \ + ../../xform.c \ + ../../zoom.c \ + ../../X86/common_x86.c + + MESAOBJS = ../../aatriangle.o \ + ../../accum.o \ + ../../alpha.o \ + ../../alphabuf.o \ + ../../attrib.o \ + ../../bbox.o \ + ../../bitmap.o \ + ../../blend.o \ + ../../buffers.o \ + ../../clip.o \ + ../../colortab.o \ + ../../config.o \ + ../../context.o \ + ../../copypix.o \ + ../../cva.o \ + ../../debug_xform.o \ + ../../depth.o \ + ../../dlist.o \ + ../../drawpix.o \ + ../../enable.o \ + ../../enums.o \ + ../../eval.o \ + ../../extensions.o \ + ../../feedback.o \ + ../../fog.o \ + ../../get.o \ + ../../hash.o \ + ../../hint.o \ + ../../image.o \ + ../../imaging.o \ + ../../light.o \ + ../../lines.o \ + ../../logic.o \ + ../../masking.o \ + ../../matrix.o \ + ../../mem.o \ + ../../mmath.o \ + ../../pb.o \ + ../../pipeline.o \ + ../../pixel.o \ + ../../pixeltex.o \ + ../../points.o \ + ../../polygon.o \ + ../../quads.o \ + ../../rastpos.o \ + ../../readpix.o \ + ../../rect.o \ + ../../scissor.o \ + ../../shade.o \ + ../../span.o \ + ../../stages.o \ + ../../state.o \ + ../../stencil.o \ + ../../teximage.o \ + ../../texobj.o \ + ../../texstate.o \ + ../../texture.o \ + ../../texutil.o \ + ../../translate.o \ + ../../triangle.o \ + ../../varray.o \ + ../../vb.o \ + ../../vbcull.o \ + ../../vbfill.o \ + ../../vbindirect.o \ + ../../vbrender.o \ + ../../vbxform.o \ + ../../vector.o \ + ../../vertices.o \ + ../../winpos.o \ + ../../xform.o \ + ../../zoom.o - DRIOBJS = i810_xmesa.o i810clear.o \ - i810dd.o i810depth.o i810dma.o i810ring.o \ - i810pipeline.o i810span.o i810state.o i810swap.o \ - i810tex.o i810tris.o i810vb.o i810fastpath.o +#ifdef i386Architecture + X86_SRCS = ../../X86/x86.c \ + ../../X86/x86a.S \ + ../../X86/common_x86.c \ + ../../X86/common_x86asm.S \ + ../../X86/vertex.S + + X86_OBJS = ../../X86/x86.o \ + ../../X86/x86a.o \ + ../../X86/common_x86.o \ + ../../X86/common_x86asm.o \ + ../../X86/vertex.o + + MMX_SRCS = ../../X86/mmx_blend.S + + MMX_OBJS = ../../X86/mmx_blend.o + +XCOMM Disabling 3Dnow code for the time being. +#if 0 + 3DNOW_SRCS = ../../X86/3dnow.c \ + ../../X86/3dnow_norm_raw.S \ + ../../X86/3dnow_xform_masked1.S \ + ../../X86/3dnow_xform_masked2.S \ + ../../X86/3dnow_xform_masked3.S \ + ../../X86/3dnow_xform_masked4.S \ + ../../X86/3dnow_xform_raw1.S \ + ../../X86/3dnow_xform_raw2.S \ + ../../X86/3dnow_xform_raw3.S \ + ../../X86/3dnow_xform_raw4.S \ + ../../X86/vertex_3dnow.S + + 3DNOW_OBJS = ../../X86/3dnow.o \ + ../../X86/3dnow_norm_raw.o \ + ../../X86/3dnow_xform_masked1.o \ + ../../X86/3dnow_xform_masked2.o \ + ../../X86/3dnow_xform_masked3.o \ + ../../X86/3dnow_xform_masked4.o \ + ../../X86/3dnow_xform_raw1.o \ + ../../X86/3dnow_xform_raw2.o \ + ../../X86/3dnow_xform_raw3.o \ + ../../X86/3dnow_xform_raw4.o \ + ../../X86/vertex_3dnow.o +#endif + +#endif + + ASMSRCS = $(X86_SRCS) $(MMX_SRCS) $(3DNOW_SRCS) + ASMOBJS = $(X86_OBJS) $(MMX_OBJS) $(3DNOW_OBJS) + + COMMONSRCS = ../common/mm.c ../common/hwlog.c + COMMONOBJS = ../common/mm.o ../common/hwlog.o + + SRCS = $(DRISRCS) $(DRMSRCS) $(MESASRCS) $(ASMSRCS) $(COMMONSRCS) $(I810SRCS) + OBJS = $(DRIOBJS) $(DRMOBJS) $(MESAOBJS) $(ASMOBJS) $(COMMONOBJS) $(I810OBJS) + +REQUIREDLIBS += -lm +#if !GlxBuiltInI810 +REQUIREDLIBS += -L../../../.. -lGL +#endif - SRCS = $(DRISRCS) - OBJS = $(DRIOBJS) #if !GlxUseBuiltInDRIDriver #undef DoNormalLib NormalLibGlx @@ -57,7 +292,7 @@ LIBNAME = i810_dri.so ALL_OBJS = $(OBJS) ALL_DEPS = DONE SharedDepModuleTarget($(LIBNAME),$(ALL_DEPS),$(ALL_OBJS)) -InstallDynamicModule($(LIBNAME),$(MODULEDIR),.) +InstallDynamicModule($(LIBNAME),$(MODULEDIR)/dri,.) #endif DependTarget() diff --git a/xc/lib/GL/mesa/src/drv/i810/i810_3d_reg.h b/xc/lib/GL/mesa/src/drv/i810/i810_3d_reg.h index 8e6942497..a4b947b30 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810_3d_reg.h +++ b/xc/lib/GL/mesa/src/drv/i810/i810_3d_reg.h @@ -108,6 +108,8 @@ #define LCS_UPDATE_LINEWIDTH (0x1<<15) #define LCS_LINEWIDTH_MASK (0x7<<12) #define LCS_LINEWIDTH_SHIFT 12 +#define LCS_LINEWIDTH_0_5 (0x1<<12) +#define LCS_LINEWIDTH_1_0 (0x2<<12) #define LCS_UPDATE_ALPHA_INTERP (0x1<<11) #define LCS_ALPHA_FLAT (0x0<<10) #define LCS_ALPHA_INTERP (0x1<<10) @@ -616,9 +618,6 @@ typedef struct { #define DV_PF_555 (0x1<<8) #define DV_PF_565 (0x2<<8) - - - #define GFX_OP_ANTIALIAS ((0x3<<29)|(0x6<<24)) #define AA_UPDATE_EDGEFLAG (1<<13) #define AA_ENABLE_EDGEFLAG (1<<12) @@ -641,84 +640,16 @@ typedef struct { #define ST1_ENABLE (1<<16) #define ST1_MASK (0xffff) +#define I810_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value) -/* Indices into buf.Setup where various bits of state are mirrored per - * context and per buffer. These can be fired at the card as a unit, - * or in a piecewise fashion as required. - */ - -/* Destbuffer state - * - backbuffer linear offset and pitch -- invarient in the current dri - * - zbuffer linear offset and pitch -- also invarient - * - drawing origin in back and depth buffers. - * - * Keep the depth/back buffer state here to acommodate private buffers - * in the future. - */ -#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */ -#define I810_DESTREG_DI1 1 -#define I810_DESTREG_ZB0 2 /* CMD_OP_Z_BUFFER_INFO */ -#define I810_DESTREG_ZB1 3 /* CMD_OP_Z_BUFFER_INFO */ -#define I810_DESTREG_DV0 4 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */ -#define I810_DESTREG_DV1 5 -#define I810_DESTREG_DR0 6 /* GFX_OP_DRAWRECT_INFO (4 dwords) */ -#define I810_DESTREG_DR1 7 -#define I810_DESTREG_DR2 8 -#define I810_DESTREG_DR3 9 -#define I810_DESTREG_DR4 10 - -#define I810_DEST_SETUP_SIZE (11+1) - -/* Context state - */ -#define I810_CTXREG_VF 0 /* GFX_OP_VERTEX_FMT */ -#define I810_CTXREG_MT 1 /* GFX_OP_MAP_TEXELS */ -#define I810_CTXREG_MC0 2 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */ -#define I810_CTXREG_MC1 3 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */ -#define I810_CTXREG_MC2 4 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */ -#define I810_CTXREG_MA0 5 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */ -#define I810_CTXREG_MA1 6 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */ -#define I810_CTXREG_MA2 7 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */ -#define I810_CTXREG_SDM 8 /* GFX_OP_SRC_DEST_MONO */ -#define I810_CTXREG_CF0 9 /* GFX_OP_COLOR_FACTOR */ -#define I810_CTXREG_CF1 10 -#define I810_CTXREG_FOG 11 /* GFX_OP_FOG_COLOR */ -#define I810_CTXREG_B1 12 /* GFX_OP_BOOL_1 */ -#define I810_CTXREG_B2 13 /* GFX_OP_BOOL_2 */ -#define I810_CTXREG_LCS 14 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */ -#define I810_CTXREG_PV 15 /* GFX_OP_PV_RULE -- Invarient! */ -#define I810_CTXREG_ZA 16 /* GFX_OP_ZBIAS_ALPHAFUNC */ -#define I810_CTXREG_ST0 17 /* GFX_OP_STIPPLE */ -#define I810_CTXREG_ST1 18 -#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */ -#define I810_CTX_SETUP_SIZE (20) /* pad to qword */ - - -/* Cliprect state - keep seperate from context as it is used for - * drawing triangles to the shared backbuffer, and - * changes more frequently than the 'normal' context. - */ -#define I810_CLIPREG_SCI0 0 /* GFX_OP_SCISSOR_INFO (3 dwords) */ -#define I810_CLIPREG_SCI1 1 -#define I810_CLIPREG_SCI2 2 -#define I810_CLIPREG_SC 3 /* GFX_OP_SCISSOR */ - -#define I810_CLIP_SETUP_SIZE 4 - -/* Texture state (per tex_buffer) - */ -#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */ -#define I810_TEXREG_MI1 1 -#define I810_TEXREG_MI2 2 -#define I810_TEXREG_MI3 3 -#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */ -#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */ -#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */ -#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */ - -#define I810_TEX_SETUP_SIZE 8 +#define I810PACKCOLOR4444(r,g,b,a) \ + ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) +#define I810PACKCOLOR1555(r,g,b,a) \ + ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ + ((a) ? 0x8000 : 0)) -#define I810_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value) +#define I810PACKCOLOR565(r,g,b) \ + ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) #endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810_xmesa.c b/xc/lib/GL/mesa/src/drv/i810/i810_xmesa.c index 7545a325f..8b439e52c 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810_xmesa.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810_xmesa.c @@ -47,7 +47,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i810tex.h" #include "i810span.h" #include "i810tris.h" -#include "i810swap.h" #include "i810pipeline.h" #include "i810ioctl.h" @@ -74,8 +73,40 @@ int I810_DEBUG = (0 static i810ContextPtr i810Ctx = 0; -i810Glx_t i810glx; +/* These functions are accessed externally to the driver: + * + * XMesaInitDriver + * XMesaResetDriver + * XMesaCreateVisual + * XMesaDestroyVisual + * XMesaCreateContext + * XMesaDestroyContext + * XMesaCreateWindowBuffer + * XMesaCreatePixmapBuffer + * XMesaDestroyBuffer + * XMesaSwapBuffers + * XMesaMakeCurrent + * + */ + + +static drmBufMapPtr i810_create_empty_buffers(void) +{ + drmBufMapPtr retval; + + retval = (drmBufMapPtr)Xmalloc(sizeof(drmBufMap)); + if(retval == NULL) return NULL; + memset(retval, 0, sizeof(drmBufMap)); + retval->list = (drmBufPtr)Xmalloc(sizeof(drmBuf) * I810_DMA_BUF_NR); + if(retval->list == NULL) { + Xfree(retval); + return NULL; + } + memset(retval->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR); + fprintf(stderr, "retval : %p, retval->list : %p\n", retval, retval->list); + return retval; +} GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) { @@ -148,13 +179,13 @@ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) fprintf(stderr, "Tex heap size %x, granularity %x bytes\n", i810Screen->textureSize, 1<<(i810Screen->logTextureGranularity)); - i810Screen->bufs = drmMapBufs(sPriv->fd); - if (!i810Screen->bufs) { + i810Screen->bufs = i810_create_empty_buffers(); + if(i810Screen->bufs == NULL) + { Xfree(i810Screen); - sPriv->private = NULL; return GL_FALSE; } - + i810Screen->back.handle = gDRIPriv->backbuffer; i810Screen->back.size = gDRIPriv->backbufferSize; @@ -198,11 +229,6 @@ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) } - /* Ditch i810glx in favor of i810Screen? - */ - memset(&i810glx, 0, sizeof(i810glx)); - i810glx.texVirtual = i810Screen->tex.map; - i810DDFastPathInit(); i810DDTrifuncInit(); i810DDSetupInit(); @@ -274,13 +300,13 @@ GLboolean XMesaCreateContext( Display *dpy, GLvisual *mesaVis, * in memory at once. */ if (i810Screen->textureSize < 2*1024*1024) { - ctx->Const.MaxTextureLevels = 8; + ctx->Const.MaxTextureLevels = 9; ctx->Const.MaxTextureSize = 1<<8; } else if (i810Screen->textureSize < 8*1024*1024) { - ctx->Const.MaxTextureLevels = 9; + ctx->Const.MaxTextureLevels = 10; ctx->Const.MaxTextureSize = 1<<9; } else { - ctx->Const.MaxTextureLevels = 10; + ctx->Const.MaxTextureLevels = 11; ctx->Const.MaxTextureSize = 1<<10; } @@ -415,23 +441,6 @@ void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv) i810SwapBuffers(imesa); } -static void i810InitClipRects( i810ContextPtr imesa ) -{ - switch (imesa->numClipRects) { - case 0: - imesa->ClipSetup[I810_CLIPREG_SC] = ( GFX_OP_SCISSOR | - SC_UPDATE_SCISSOR ); - imesa->ClipSetup[I810_CLIPREG_SCI1] = 0; - imesa->ClipSetup[I810_CLIPREG_SCI2] = 0; - break; - case 1: - break; - default: - break; - } - imesa->dirty |= I810_EMIT_CLIPRECT; -} - void i810XMesaSetFrontClipRects( i810ContextPtr imesa ) @@ -440,12 +449,12 @@ void i810XMesaSetFrontClipRects( i810ContextPtr imesa ) imesa->numClipRects = dPriv->numClipRects; imesa->pClipRects = dPriv->pClipRects; + imesa->dirty |= I810_UPLOAD_CLIPRECTS; imesa->drawX = dPriv->x; imesa->drawY = dPriv->y; imesa->drawMap = imesa->driScreen->pFB; i810EmitDrawingRectangle( imesa ); - i810InitClipRects( imesa ); } @@ -477,7 +486,7 @@ void i810XMesaSetBackClipRects( i810ContextPtr imesa ) imesa->drawMap = imesa->i810Screen->back.map; i810EmitDrawingRectangle( imesa ); - i810InitClipRects( imesa ); + imesa->dirty |= I810_UPLOAD_CLIPRECTS; if (I810_DEBUG & DEBUG_VERBOSE_DRI) for (i = 0 ; i < imesa->numClipRects ; i++) @@ -519,29 +528,27 @@ GLboolean XMesaUnbindContext(__DRIcontextPrivate *driContextPriv) } -/* This looks buggy to me - the 'b' variable isn't used anywhere... - * Hmm - It seems that the drawable is already hooked in to - * driDrawablePriv. - */ GLboolean XMesaMakeCurrent(__DRIcontextPrivate *driContextPriv, - __DRIdrawablePrivate *driDrawPriv, - __DRIdrawablePrivate *driReadPriv) + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) { if (driContextPriv) { i810Ctx = (i810ContextPtr) driContextPriv->driverPrivate; - - gl_make_current2(i810Ctx->glCtx, driDrawPriv->mesaBuffer, driReadPriv->mesaBuffer); - + + gl_make_current2(i810Ctx->glCtx, driDrawPriv->mesaBuffer, + driReadPriv->mesaBuffer); + + i810Ctx->driDrawable = driDrawPriv; i810Ctx->dirty = ~0; - + i810XMesaWindowMoved( i810Ctx ); - + if (!i810Ctx->glCtx->Viewport.Width) gl_Viewport(i810Ctx->glCtx, 0, 0, driDrawPriv->w, driDrawPriv->h); - } - else { + else + { gl_make_current(0,0); i810Ctx = NULL; } @@ -588,10 +595,11 @@ void i810GetLock( i810ContextPtr imesa, GLuint flags ) * more broken than usual. */ if (sarea->ctxOwner != me) { - i810glx.c_ctxlost++; - imesa->dirty |= I810_UPLOAD_CTX; - imesa->dirty |= I810_EMIT_CLIPRECT; - imesa->dirty |= I810_UPLOAD_BUFFERS; + imesa->dirty |= (I810_UPLOAD_CTX | + I810_UPLOAD_CLIPRECTS | + I810_UPLOAD_BUFFERS | + I810_UPLOAD_TEX0 | + I810_UPLOAD_TEX1); sarea->ctxOwner = me; } diff --git a/xc/lib/GL/mesa/src/drv/i810/i810clear.c b/xc/lib/GL/mesa/src/drv/i810/i810clear.c deleted file mode 100644 index 5ba264059..000000000 --- a/xc/lib/GL/mesa/src/drv/i810/i810clear.c +++ /dev/null @@ -1,193 +0,0 @@ - - -#include "types.h" -#include "vbrender.h" -#include "i810log.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "mm.h" -#include "i810lib.h" -#include "i810dd.h" -#include "i810clear.h" -#include "i810state.h" -#include "i810tris.h" - - - -/* Clear the depthbuffer. Always uses the auxillary cliprects and - * origin from 'dPriv'. - */ -static void i810_clear_depthbuffer( GLcontext *ctx, - GLboolean all, - GLint cx, GLint cy, - GLint cwidth, GLint cheight ) -{ - i810ContextPtr imesa = I810_CONTEXT( ctx ); - GLuint zval = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE); - i810ScreenPrivate *i810Screen = imesa->i810Screen; - __DRIdrawablePrivate *dPriv = imesa->driDrawable; - -/* int _nc = dPriv->numAuxClipRects; */ -/* XF86DRIClipRectPtr box = dPriv->pAuxClipRects; */ - - int _nc = imesa->numClipRects; - XF86DRIClipRectPtr box = imesa->pClipRects; - - cy = dPriv->h-cy-cheight; - cx += dPriv->auxX; - cy += dPriv->auxY; - - while (_nc--) { - GLint x = box[_nc].x1; - GLint y = box[_nc].y1; - GLint width = box[_nc].x2 - x; - GLint height = box[_nc].y2 - y; - - 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 (I810_DEBUG&DEBUG_VERBOSE_2D) - fprintf(stderr, "clear depth rect %d,%d %dx%d\n", - (int) x, (int) y, (int) width, (int) height); - - { - int start = (i810Screen->depthOffset + - y * i810Screen->auxPitch + - x * 2); - - BEGIN_BATCH(imesa, 6); - - OUT_BATCH( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); - OUT_BATCH( BR13_SOLID_PATTERN | - (0xF0 << 16) | - i810Screen->auxPitch ); - OUT_BATCH( (height << 16) | (width * 2)); - OUT_BATCH( start ); - OUT_BATCH( zval ); - OUT_BATCH( 0 ); - - ADVANCE_BATCH(); - } - } -} - - -/* Clear the current drawbuffer. Checks 'imesa' to determine which set of - * cliprects and origin to use. - */ -static void i810_clear_colorbuffer( GLcontext *ctx, - GLboolean all, - GLint cx, GLint cy, - GLint cwidth, GLint cheight ) -{ - i810ContextPtr imesa = I810_CONTEXT( ctx ); - GLushort c = imesa->ClearColor; - i810ScreenPrivate *i810Screen = imesa->i810Screen; - __DRIdrawablePrivate *dPriv = imesa->driDrawable; - - int _nc = imesa->numClipRects; - XF86DRIClipRectPtr box = imesa->pClipRects; - - cy = dPriv->h-cy-cheight; - cx += imesa->drawX; - cy += imesa->drawY; - - while (_nc--) { - GLint x = box[_nc].x1; - GLint y = box[_nc].y1; - GLint width = box[_nc].x2 - x; - GLint height = box[_nc].y2 - y; - - 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 (I810_DEBUG&DEBUG_VERBOSE_2D) - fprintf(stderr, "clear color rect %d,%d %dx%d\n", - (int) x, (int) y, (int) width, (int) height); - - - { - int start = (imesa->drawOffset + - y * i810Screen->auxPitch + - x * i810Screen->cpp); - - BEGIN_BATCH( imesa, 6 ); - - OUT_BATCH( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); - OUT_BATCH( BR13_SOLID_PATTERN | - (0xF0 << 16) | - i810Screen->auxPitch ); - OUT_BATCH( (height << 16) | (width * i810Screen->cpp)); - OUT_BATCH( start ); - OUT_BATCH( c ); - OUT_BATCH( 0 ); - - ADVANCE_BATCH(); - } - } -} - - - - -/* - * i810Clear - * - * Clear the color and/or depth buffers. If 'all' is GL_TRUE, clear - * whole buffer, otherwise clear the region defined by the remaining - * parameters. - */ -GLbitfield i810Clear( GLcontext *ctx, GLbitfield mask, GLboolean all, - GLint cx, GLint cy, GLint cwidth, GLint cheight ) -{ - i810ContextPtr imesa = I810_CONTEXT( ctx ); - - if (I810_DEBUG&DEBUG_VERBOSE_API) - fprintf(stderr, "i810Clear( %d, %d, %d, %d, %d )\n", - (int)mask, (int)cx, (int)cy, (int)cwidth, (int)cheight ); - - LOCK_HARDWARE(imesa); - - { - BEGIN_BATCH( imesa, 2 ); - OUT_BATCH( INST_PARSER_CLIENT | INST_OP_FLUSH ); - OUT_BATCH( 0 ); - ADVANCE_BATCH(); - } - - if (mask & GL_COLOR_BUFFER_BIT) { - i810_clear_colorbuffer( ctx, all, cx, cy, cwidth, cheight ); - mask &= ~GL_COLOR_BUFFER_BIT; - } - - if ( (mask & GL_DEPTH_BUFFER_BIT) && ctx->Depth.Mask ) { - i810_clear_depthbuffer( ctx, all, cx, cy, cwidth, cheight ); - mask &= ~GL_DEPTH_BUFFER_BIT; - } - - { - BEGIN_BATCH( imesa, 2 ); - OUT_BATCH( INST_PARSER_CLIENT | INST_OP_FLUSH ); - OUT_BATCH( 0 ); - ADVANCE_BATCH(); - } - - UNLOCK_HARDWARE( imesa ); - return mask; -} - diff --git a/xc/lib/GL/mesa/src/drv/i810/i810clear.h b/xc/lib/GL/mesa/src/drv/i810/i810clear.h deleted file mode 100644 index aedbf84d9..000000000 --- a/xc/lib/GL/mesa/src/drv/i810/i810clear.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _I810_CLEAR_H -#define _I810_CLEAR_H - -extern GLbitfield i810Clear( GLcontext *ctx, GLbitfield mask, GLboolean all, - GLint x, GLint y, GLint width, GLint height ); - -#endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810context.h b/xc/lib/GL/mesa/src/drv/i810/i810context.h index 9f316f6fd..629abf0b8 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810context.h +++ b/xc/lib/GL/mesa/src/drv/i810/i810context.h @@ -28,24 +28,32 @@ typedef struct i810_context_t i810Context; typedef struct i810_context_t *i810ContextPtr; +typedef struct i810_texture_object_t *i810TextureObjectPtr; #include <X11/Xlibint.h> #include "dri_tmm.h" #include "dri_mesaint.h" #include "dri_mesa.h" -#include "xmesaP.h" #include "types.h" #include "i810_init.h" -#include "i810_sarea.h" +#include "drm.h" +#include "mm.h" +#include "i810log.h" #include "i810tex.h" #include "i810vb.h" - -#define I810_FALLBACK_TEXTURE 0x1 -#define I810_FALLBACK_BUFFER 0x2 +/* Reasons to fallback on all primitives. (see also + * imesa->IndirectTriangles). + */ +#define I810_FALLBACK_TEXTURE 0x1 +#define I810_FALLBACK_DRAW_BUFFER 0x2 +#define I810_FALLBACK_READ_BUFFER 0x4 +#define I810_FALLBACK_COLORMASK 0x8 +#define I810_FALLBACK_STIPPLE 0x10 +#define I810_FALLBACK_SPECULAR 0x20 @@ -53,17 +61,6 @@ typedef struct i810_context_t *i810ContextPtr; */ #define I810_NEW_TEXTURE 0x1 -/* for i810ctx.dirty - manage driver->hw state changes, including - * lost contexts. - */ -#define I810_REQUIRE_QUIESCENT 0x1 -#define I810_UPLOAD_TEX0IMAGE 0x2 -#define I810_UPLOAD_TEX1IMAGE 0x4 -#define I810_UPLOAD_CTX 0x8 -#define I810_UPLOAD_BUFFERS 0x10 -#define I810_REFRESH_RING 0x20 -#define I810_EMIT_CLIPRECT 0x40 - typedef void (*i810_interp_func)( GLfloat t, GLfloat *result, @@ -88,7 +85,6 @@ struct i810_context_t { */ GLuint Setup[I810_CTX_SETUP_SIZE]; GLuint BufferSetup[I810_DEST_SETUP_SIZE]; - GLuint ClipSetup[I810_CLIP_SETUP_SIZE]; /* Support for CVA and the fast paths. @@ -125,24 +121,38 @@ struct i810_context_t { /* DRI stuff */ + drmBufPtr vertex_dma_buffer; + GLuint vertex_prim; + GLframebuffer *glBuffer; + /* Two flags to keep track of fallbacks. + */ + GLuint IndirectTriangles; GLuint Fallback; + + GLuint needClip; /* These refer to the current draw (front vs. back) buffer: */ - int drawOffset; /* draw buffer address in agp space */ + char *drawMap; /* draw buffer address in virtual mem */ + char *readMap; int drawX; /* origin of drawable in draw buffer */ int drawY; GLuint numClipRects; /* cliprects for that buffer */ XF86DRIClipRectPtr pClipRects; - int lastSwap; + int secondLastSwap; int texAge; + int ctxAge; + int dirtyAge; + int any_contend; /* throttle me harder */ - XF86DRIClipRectRec draw_rect; + int scissor; + drm_clip_rect_t draw_rect; + drm_clip_rect_t scissor_rect; drmContext hHWContext; drmLock *driHwLock; @@ -152,7 +162,7 @@ struct i810_context_t { __DRIdrawablePrivate *driDrawable; __DRIscreenPrivate *driScreen; i810ScreenPrivate *i810Screen; - I810SAREAPriv *sarea; + drm_i810_sarea_t *sarea; }; @@ -161,7 +171,7 @@ struct i810_context_t { */ #define I810_DEBUG 0 #ifndef I810_DEBUG -/* #warning "Debugging enabled - expect reduced performance" */ +#warning "Debugging enabled - expect reduced performance" extern int I810_DEBUG; #endif @@ -176,6 +186,7 @@ extern int I810_DEBUG; #define DEBUG_VALIDATE_RING 0x800 #define DEBUG_VERBOSE_LRU 0x1000 #define DEBUG_VERBOSE_DRI 0x2000 +#define DEBUG_VERBOSE_IOCTL 0x4000 diff --git a/xc/lib/GL/mesa/src/drv/i810/i810dd.c b/xc/lib/GL/mesa/src/drv/i810/i810dd.c index c1fbda734..583eb630c 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810dd.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810dd.c @@ -29,8 +29,6 @@ #include <stdio.h> #include "mm.h" -#include "i810lib.h" -#include "i810clear.h" #include "i810dd.h" #include "i810log.h" #include "i810state.h" diff --git a/xc/lib/GL/mesa/src/drv/i810/i810dma.h b/xc/lib/GL/mesa/src/drv/i810/i810dma.h deleted file mode 100644 index 9d472719a..000000000 --- a/xc/lib/GL/mesa/src/drv/i810/i810dma.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - GLX Hardware Device Driver for Intel i810 - Copyright (C) 1999 Keith Whitwell <keithw@precisioninsight.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - original by Jeff Hartmann <slicer@ionet.net> - 6/16/99: rewrite by John Carmack <johnc@idsoftware.com> - Oct 99: port to i180 by Keith Whitwell <keithw@precisioninsight.com> -*/ - -#ifndef I810DMA_H -#define I810DMA_H - -#include "i810lib.h" -#include "mm.h" - -/* a flush command will guarantee that all data added to the dma buffer -is on its way to the card, and will eventually complete with no more -intervention. -*/ -void i810DmaFlush( i810ContextPtr imesa ); - -/* the overflow function is called when a block can't be allocated -in the current dma buffer. It flushes the current buffer and -records some information */ -void i810DmaOverflow(int newDwords); - -/* a finish command will guarantee that all dma commands have actually -been consumed by the card. Note that there may still be a couple primitives -that have not yet been executed out of the internal FIFO, so this does not -guarantee that the drawing engine is idle. */ -void i810DmaFinish( i810ContextPtr imesa ); - - - -typedef struct { - unsigned long Start; - unsigned long End; - unsigned long Size; -} I810MemRange; - - - -typedef struct i810_batch_buffer { - I810MemRange mem; - char *virtual_start; - int head; - int space; - int additional_space; - int texture_age; -} i810BatchBuffer; - - - -#define I810_USE_BATCH 0 -#if I810_USE_BATCH - -#define BEGIN_BATCH( imesa, n ) \ - unsigned int outbatch; \ - volatile char *virt; \ - if (I810_DEBUG & DEBUG_VERBOSE_RING) \ - fprintf(stderr, \ - "BEGIN_BATCH(%d) in %s\n" \ - "(spc left %d/%ld, head %x vstart %p start %lx)\n", \ - n, __FUNCTION__, i810glx.dma_buffer->space, \ - i810glx.dma_buffer->mem.Size - i810glx.dma_buffer->head, \ - i810glx.dma_buffer->head, \ - i810glx.dma_buffer->virtual_start, \ - i810glx.dma_buffer->mem.Start ); \ - if (i810glx.dma_buffer->space < n*4) \ - i810DmaOverflow(n); \ - outbatch = i810glx.dma_buffer->head; \ - virt = i810glx.dma_buffer->virtual_start; - - -#define OUT_BATCH(val) { \ - *(volatile unsigned int *)(virt + outbatch) = val; \ - if (I810_DEBUG & DEBUG_VERBOSE_RING) \ - fprintf(stderr, "OUT_BATCH %x: %x\n", (int)(outbatch/4), (int)(val)); \ - outbatch += 4; \ -} - - -#define ADVANCE_BATCH() { \ - if (I810_DEBUG & DEBUG_VERBOSE_RING) \ - fprintf(stderr, "ADVANCE_BATCH(%f) in %s\n", \ - (outbatch - i810glx.dma_buffer->head) / 4.0, \ - __FUNCTION__); \ - i810glx.dma_buffer->space -= outbatch - i810glx.dma_buffer->head; \ - i810glx.dma_buffer->head = outbatch; \ -} - -#define FINISH_PRIM() - -#else - - -/* As an alternate path to dma, we can export the registers (and hence - * ringbuffer) to the client. For security we should alloc these - * things in agp memory which isn't exported to the client. But then - * again, the client could blit over such things if it wanted to hang - * the system. - * - * Malicious clients aren't really delt with by the DRI. - */ - - -extern void _I810RefreshLpRing( i810ContextPtr imesa, int update ); -extern int _I810WaitLpRing( i810ContextPtr imesa, int n, int timeout_usec ); -extern int _I810Sync( i810ContextPtr imesa ); - - -#define OUT_RING(n) { \ - if (I810_DEBUG & DEBUG_VERBOSE_RING) \ - fprintf(stderr, "OUT_RING %x: %x\n", outring, (int)(n)); \ - if (!(I810_DEBUG & DEBUG_NO_OUTRING)) { \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ - } \ -} - -#define ADVANCE_LP_RING() { \ - i810glx.LpRing.tail = outring; \ - OUTREG(LP_RING + RING_TAIL, outring); \ -} - -#define BEGIN_LP_RING(imesa, n) \ - unsigned int outring, ringmask; \ - volatile char *virt; \ - if ((I810_DEBUG&DEBUG_ALWAYS_SYNC) && n>2) _I810Sync( imesa ); \ - if (i810glx.LpRing.space < n*4) _I810WaitLpRing( imesa, n*4, 0); \ - i810glx.LpRing.space -= n*4; \ - if (I810_DEBUG & DEBUG_VERBOSE_RING) \ - fprintf(stderr, "BEGIN_LP_RING %d in %s\n", n, __FUNCTION__); \ - if (I810_DEBUG & DEBUG_VALIDATE_RING) { \ - CARD32 tail = INREG(LP_RING+RING_TAIL); \ - if (tail != i810glx.LpRing.tail) { \ - fprintf(stderr, "tail %x pI810->LpRing.tail %x\n", \ - (int) tail, (int) i810glx.LpRing.tail); \ - exit(1); \ - } \ - } \ - i810glx.LpRing.synced = 0; \ - outring = i810glx.LpRing.tail; \ - ringmask = i810glx.LpRing.tail_mask; \ - virt = i810glx.LpRing.virtual_start; - - -#define EXTRAAA \ - -#define INREG(addr) *(volatile CARD32 *)(i810glx.MMIOBase + (addr)) -#define INREG16(addr) *(volatile CARD16 *)(i810glx.MMIOBase + (addr)) -#define INREG8(addr) *(volatile CARD8 *)(i810glx.MMIOBase + (addr)) - -#define OUTREG(addr, val) do { \ - if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) \ - fprintf(stderr, "OUTREG(%x, %x)\n", addr, val); \ - if (!(I810_DEBUG&DEBUG_NO_OUTREG)) \ - *(volatile CARD32 *)(i810glx.MMIOBase + (addr)) = (val); \ -} while (0) - - -#define BEGIN_BATCH(imesa, n) BEGIN_LP_RING(imesa, n) -#define ADVANCE_BATCH() ADVANCE_LP_RING() -#define OUT_BATCH(val) OUT_RING(val) -#define FINISH_PRIM() OUTREG(LP_RING + RING_TAIL, i810glx.LpRing.tail) - -#endif - - - -#endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810ioctl.c b/xc/lib/GL/mesa/src/drv/i810/i810ioctl.c new file mode 100644 index 000000000..b4e86cff2 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/i810/i810ioctl.c @@ -0,0 +1,477 @@ +#include <stdio.h> +#include <unistd.h> + + +#include "types.h" +#include "pb.h" +#include "dd.h" + +#include "mm.h" +#include "i810context.h" +#include "i810log.h" +#include "i810ioctl.h" + +#include "drm.h" +#include <sys/ioctl.h> + +static drmBufPtr i810_get_buffer_ioctl( i810ContextPtr imesa ) +{ + drm_i810_dma_t dma; + drmBufPtr buf; + int retcode; + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Getting dma buffer\n"); + + while (1) { + retcode = ioctl(imesa->driFd, DRM_IOCTL_I810_GETBUF, &dma); + + if (dma.granted == 1 && retcode == 0) + break; + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Retcode : %d, granted : %d\n", retcode, dma.granted); + + ioctl(imesa->driFd, DRM_IOCTL_I810_FLUSH); + } + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, + "imesa->i810Screen->bufs->list : %p, " + "dma.request_idx : %d\n", + imesa->i810Screen->bufs->list, dma.request_idx); + + buf = &(imesa->i810Screen->bufs->list[dma.request_idx]); + buf->idx = dma.request_idx; + buf->used = 0; + buf->total = dma.request_size; + buf->address = (drmAddress)dma.virtual; + return buf; +} + + + +#define DEPTH_SCALE ((1<<16)-1) + +GLbitfield i810Clear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch ) +{ + i810ContextPtr imesa = I810_CONTEXT( ctx ); + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); + drm_i810_clear_t clear; + int i; + + clear.flags = 0; + clear.clear_color = imesa->ClearColor; + clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE); + + FLUSH_BATCH( imesa ); + + if ((mask & DD_FRONT_LEFT_BIT) && colorMask == ~0) { + clear.flags |= I810_FRONT; + mask &= ~DD_FRONT_LEFT_BIT; + } + + if ((mask & DD_BACK_LEFT_BIT) && colorMask == ~0) { + clear.flags |= I810_BACK; + mask &= ~DD_BACK_LEFT_BIT; + } + + if ((mask & DD_DEPTH_BIT) && ctx->Depth.Mask) { + clear.flags |= I810_DEPTH; + mask &= ~DD_DEPTH_BIT; + } + + if (!clear.flags) + return mask; + + LOCK_HARDWARE( imesa ); + + /* flip top to bottom */ + cy = dPriv->h-cy-ch; + cx += imesa->drawX; + cy += imesa->drawY; + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Clear, bufs %x nbox %d\n", + (int)clear.flags, (int)imesa->numClipRects); + + for (i = 0 ; i < imesa->numClipRects ; ) + { + int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, imesa->numClipRects); + XF86DRIClipRectRec *box = imesa->pClipRects; + drm_clip_rect_t *b = imesa->sarea->boxes; + int n = 0; + + if (!all) { + for ( ; i < nr ; i++) { + GLint x = box[i].x1; + GLint y = box[i].y1; + GLint w = box[i].x2 - x; + GLint h = box[i].y2 - y; + + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + if (w <= 0) continue; + if (h <= 0) continue; + + b->x1 = x; + b->y1 = y; + b->x2 = x + w; + b->y2 = y + h; + b++; + n++; + } + } else { + for ( ; i < nr ; i++) { + *b++ = *(drm_clip_rect_t *)&box[i]; + n++; + } + } + + imesa->sarea->nbox = n; + ioctl(imesa->driFd, DRM_IOCTL_I810_CLEAR, &clear); + } + + UNLOCK_HARDWARE( imesa ); + imesa->dirty |= I810_UPLOAD_CLIPRECTS; + + return mask; +} + + + + +/* + * Copy the back buffer to the front buffer. + */ +void i810SwapBuffers( i810ContextPtr imesa ) +{ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + XF86DRIClipRectPtr pbox; + int nbox; + int i; + int tmp; + + FLUSH_BATCH( imesa ); + LOCK_HARDWARE( imesa ); + + pbox = dPriv->pClipRects; + nbox = dPriv->numClipRects; + + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)imesa->sarea->boxes; + + imesa->sarea->nbox = nr - i; + + for ( ; i < nr ; i++) + *b++ = pbox[i]; + + ioctl(imesa->driFd, DRM_IOCTL_I810_SWAP); + } + + tmp = GET_ENQUEUE_AGE(imesa); + UNLOCK_HARDWARE( imesa ); + + if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) + i810WaitAge(imesa, imesa->lastSwap); + + imesa->lastSwap = tmp; + imesa->dirty |= I810_UPLOAD_CLIPRECTS; +} + + + + + + +/* This waits for *everybody* to finish rendering -- overkill. + */ +void i810DmaFinish( i810ContextPtr imesa ) +{ + FLUSH_BATCH( imesa ); + + if (imesa->sarea->last_quiescent != imesa->sarea->last_enqueue) { + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "i810DmaFinish\n"); + + LOCK_HARDWARE( imesa ); + i810RegetLockQuiescent( imesa ); + UNLOCK_HARDWARE( imesa ); + imesa->sarea->last_quiescent = imesa->sarea->last_enqueue; + } +} + + +void i810RegetLockQuiescent( i810ContextPtr imesa ) +{ + if (imesa->sarea->last_quiescent != imesa->sarea->last_enqueue) { + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "i810RegetLockQuiescent\n"); + + drmUnlock(imesa->driFd, imesa->hHWContext); + i810GetLock( imesa, DRM_LOCK_QUIESCENT ); + imesa->sarea->last_quiescent = imesa->sarea->last_enqueue; + } +} + +void i810WaitAgeLocked( i810ContextPtr imesa, int age ) +{ + int i = 0; + + + while (++i < 500000 && GET_DISPATCH_AGE(imesa) < age) { + ioctl(imesa->driFd, DRM_IOCTL_I810_GETAGE); + } + + if (GET_DISPATCH_AGE(imesa) < age) { + if (0) + fprintf(stderr, "wait locked %d %d\n", age, GET_DISPATCH_AGE(imesa)); + ioctl(imesa->driFd, DRM_IOCTL_I810_FLUSH); + } +} + + +void i810WaitAge( i810ContextPtr imesa, int age ) +{ + int i = 0; + + while (++i < 500000 && GET_DISPATCH_AGE(imesa) < age) { + ioctl(imesa->driFd, DRM_IOCTL_I810_GETAGE); + } + + if (GET_DISPATCH_AGE(imesa) >= age) + return; + + i = 0; + while (++i < 1000 && GET_DISPATCH_AGE(imesa) < age) { + ioctl(imesa->driFd, DRM_IOCTL_I810_GETAGE); + usleep(1000); + } + + /* To be effective at letting other clients at the hardware, + * particularly the X server which regularly needs quiescence to + * touch the framebuffer, we really need to sleep *beyond* the + * point where our last buffer clears the hardware. + */ + if (imesa->any_contend) { + usleep(3000); + } + + imesa->any_contend = 0; + + if (GET_DISPATCH_AGE(imesa) < age) { + LOCK_HARDWARE(imesa); + if (GET_DISPATCH_AGE(imesa) < age) + ioctl(imesa->driFd, DRM_IOCTL_I810_FLUSH); + UNLOCK_HARDWARE(imesa); + } +} + + + +void i810FlushVertices( i810ContextPtr imesa ) +{ + if (!imesa->vertex_dma_buffer) return; + + LOCK_HARDWARE( imesa ); + i810FlushVerticesLocked( imesa ); + UNLOCK_HARDWARE( imesa ); +} + + +static int intersect_rect( drm_clip_rect_t *out, + drm_clip_rect_t *a, + drm_clip_rect_t *b ) +{ + *out = *a; + if (b->x1 > out->x1) out->x1 = b->x1; + if (b->y1 > out->y1) out->y1 = b->y1; + if (b->x2 < out->x2) out->x2 = b->x2; + if (b->y2 < out->y2) out->y2 = b->y2; + if (out->x1 >= out->x2) return 0; + if (out->y1 >= out->y2) return 0; + return 1; +} + + +static void age_imesa( i810ContextPtr imesa, int age ) +{ + if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->age = age; + if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->age = age; +} + +void i810FlushVerticesLocked( i810ContextPtr imesa ) +{ + drm_clip_rect_t *pbox = (drm_clip_rect_t *)imesa->pClipRects; + int nbox = imesa->numClipRects; + drmBufPtr buffer = imesa->vertex_dma_buffer; + drm_i810_vertex_t vertex; + int i; + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "i810FlushVerticesLocked, buf->used %d\n", + buffer->used); + + if (!buffer) + return; + + if (imesa->dirty & ~I810_UPLOAD_CLIPRECTS) + i810EmitHwStateLocked( imesa ); + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "i810FlushVerticesLocked, used %d\n", + buffer->used); + + imesa->vertex_dma_buffer = 0; + + vertex.idx = buffer->idx; + vertex.used = buffer->used; + vertex.discard = 0; + + if (!nbox) + vertex.used = 0; + + if (nbox > I810_NR_SAREA_CLIPRECTS) + imesa->dirty |= I810_UPLOAD_CLIPRECTS; + + imesa->sarea->vertex_prim = imesa->vertex_prim; + + if (!nbox || !(imesa->dirty & I810_UPLOAD_CLIPRECTS)) + { + if (nbox == 1) + imesa->sarea->nbox = 0; + else + imesa->sarea->nbox = nbox; + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "DRM_IOCTL_I810_VERTEX CASE1 nbox %d used %d\n", + nbox, vertex.used); + + vertex.discard = 1; + ioctl(imesa->driFd, DRM_IOCTL_I810_VERTEX, &vertex); + age_imesa(imesa, imesa->sarea->last_enqueue); + } + else + { + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, nbox); + drm_clip_rect_t *b = imesa->sarea->boxes; + + if (imesa->scissor) { + imesa->sarea->nbox = 0; + + for ( ; i < nr ; i++) { + b->x1 = pbox[i].x1 - imesa->drawX; + b->y1 = pbox[i].y1 - imesa->drawY; + b->x2 = pbox[i].x2 - imesa->drawX; + b->y2 = pbox[i].y2 - imesa->drawY; + + if (intersect_rect(b, b, &imesa->scissor_rect)) { + imesa->sarea->nbox++; + b++; + } + } + + /* Culled? + */ + if (!imesa->sarea->nbox) { + if (nr < nbox) continue; + vertex.used = 0; + } + } else { + imesa->sarea->nbox = nr - i; + for ( ; i < nr ; i++, b++) { + b->x1 = pbox[i].x1 - imesa->drawX; + b->y1 = pbox[i].y1 - imesa->drawY; + b->x2 = pbox[i].x2 - imesa->drawX; + b->y2 = pbox[i].y2 - imesa->drawY; + } + } + + /* Finished with the buffer? + */ + if (nr == nbox) + vertex.discard = 1; + + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "DRM_IOCTL_I810_VERTEX nbox %d used %d\n", + nbox, vertex.used); + + ioctl(imesa->driFd, DRM_IOCTL_I810_VERTEX, &vertex); + age_imesa(imesa, imesa->sarea->last_enqueue); + } + } + + imesa->dirty = 0; + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished i810FlushVerticesLocked\n"); +} + + +GLuint *i810AllocDwords( i810ContextPtr imesa, int dwords, GLuint prim ) +{ + GLuint *start; + + if (!imesa->vertex_dma_buffer) + { + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "i810AllocPrimitiveVerts -- get buf\n"); + LOCK_HARDWARE(imesa); + imesa->vertex_dma_buffer = i810_get_buffer_ioctl( imesa ); + imesa->vertex_dma_buffer->used = 4; + imesa->vertex_prim = prim; + UNLOCK_HARDWARE(imesa); + } + else if (imesa->vertex_prim != prim || + imesa->vertex_dma_buffer->used + dwords * 4 > + imesa->vertex_dma_buffer->total) + { + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "i810AllocPrimitiveVerts -- flush\n"); + i810FlushVertices( imesa ); + LOCK_HARDWARE(imesa); + imesa->vertex_dma_buffer = i810_get_buffer_ioctl( imesa ); + imesa->vertex_dma_buffer->used = 4; + imesa->vertex_prim = prim; + UNLOCK_HARDWARE(imesa); + } + + + if (0) + fprintf(stderr, "i810AllocPrimitiveVerts %d, buf %d, used %d\n", + dwords, imesa->vertex_dma_buffer->idx, + imesa->vertex_dma_buffer->used); + + start = (GLuint *)((char *)imesa->vertex_dma_buffer->address + + imesa->vertex_dma_buffer->used); + + imesa->vertex_dma_buffer->used += dwords * 4; + + return start; +} + +static void i810DDFlush( GLcontext *ctx ) +{ + i810ContextPtr imesa = I810_CONTEXT( ctx ); + FLUSH_BATCH( imesa ); +} + +static void i810DDFinish( GLcontext *ctx ) +{ + i810ContextPtr imesa = I810_CONTEXT( ctx ); + i810DmaFinish( imesa ); +} + +void i810DDInitIoctlFuncs( GLcontext *ctx ) +{ + ctx->Driver.Flush = i810DDFlush; + ctx->Driver.Finish = i810DDFinish; +} diff --git a/xc/lib/GL/mesa/src/drv/i810/i810ioctl.h b/xc/lib/GL/mesa/src/drv/i810/i810ioctl.h new file mode 100644 index 000000000..004b723b4 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/i810/i810ioctl.h @@ -0,0 +1,36 @@ +#ifndef MGA_IOCTL_H +#define MGA_IOCTL_H + +#include "i810context.h" + + +GLuint *i810AllocDwords( i810ContextPtr imesa, int dwords, GLuint prim ); + +void i810GetGeneralDmaBufferLocked( i810ContextPtr mmesa ); + +void i810FlushVertices( i810ContextPtr mmesa ); +void i810FlushVerticesLocked( i810ContextPtr mmesa ); + +void i810FlushGeneralLocked( i810ContextPtr imesa ); +void i810WaitAgeLocked( i810ContextPtr imesa, int age ); +void i810WaitAge( i810ContextPtr imesa, int age ); + +void i810DmaFinish( i810ContextPtr imesa ); + +void i810RegetLockQuiescent( i810ContextPtr imesa ); + +void i810DDInitIoctlFuncs( GLcontext *ctx ); + +void i810SwapBuffers( i810ContextPtr imesa ); + +GLbitfield i810Clear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch ); + +#define FLUSH_BATCH(imesa) do { \ + if (I810_DEBUG&DEBUG_VERBOSE_IOCTL) \ + fprintf(stderr, "FLUSH_BATCH in %s\n", __FUNCTION__); \ + if (imesa->vertex_dma_buffer) i810FlushVertices(imesa); \ +} while (0) + + +#endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810lib.h b/xc/lib/GL/mesa/src/drv/i810/i810lib.h deleted file mode 100644 index ad80674f0..000000000 --- a/xc/lib/GL/mesa/src/drv/i810/i810lib.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * GLX Hardware Device Driver for Intel i810 - * Copyright (C) 1999 Keith Whitwell - * - * 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 - * KEITH WHITWELL, 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. - * - * - */ - -#ifndef I810LIB_INC -#define I810LIB_INC - -#include <stdio.h> - -#include "i810context.h" -#include "mm.h" -#include "i810log.h" - - -struct i810_mem_range { - unsigned long Start; - unsigned long End; - unsigned long Size; -}; - -struct i810_batch_buffer; - -struct i810_ring_buffer { - int tail_mask; - struct i810_mem_range mem; - char *virtual_start; - int head; - int tail; - int space; - int synced; -}; - -typedef struct { - /* logging stuff */ - GLuint logLevel; - FILE *logFile; - - /* bookkeeping for texture swaps */ - GLuint dma_buffer_age; - GLuint current_texture_age; - - /* options */ - GLuint nullprims; /* skip all primitive generation */ - GLuint boxes; /* draw performance boxes */ - GLuint noFallback; /* don't fall back to software */ - GLuint skipDma; /* don't send anything to hardware */ - - /* performance counters */ - GLuint c_setupPointers; - GLuint c_triangles; - GLuint c_points; - GLuint c_lines; - GLuint c_drawWaits; - GLuint c_textureSwaps; - GLuint c_dmaFlush; - GLuint c_overflows; - - GLuint c_ringlost; - GLuint c_texlost; - GLuint c_ctxlost; - - GLuint hardwareWentIdle; /* cleared each swapbuffers, set if a - waitfordmacompletion ever exited - without having to wait */ - - unsigned char *texVirtual; - - - struct i810_batch_buffer *dma_buffer; - struct i810_ring_buffer LpRing; - unsigned char *MMIOBase; - -} i810Glx_t; - -extern i810Glx_t i810glx; - - -#define I810PACKCOLOR1555(r,g,b,a) \ - ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ - ((a) ? 0x8000 : 0)) - -#define I810PACKCOLOR565(r,g,b) \ - ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) - -#define I810PACKCOLOR4444(r,g,b,a) \ - ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) - - -#include "i810_3d_reg.h" - -static __inline__ GLuint i810PackColor(GLuint format, - GLubyte r, GLubyte g, - GLubyte b, GLubyte a) -{ - switch (format) { - case DV_PF_555: - return I810PACKCOLOR1555(r,g,b,a); - case DV_PF_565: - return I810PACKCOLOR565(r,g,b); - default: - fprintf(stderr, "unknown format %d\n", (int)format); - return 0; - } -} - - - - -#endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810pipeline.c b/xc/lib/GL/mesa/src/drv/i810/i810pipeline.c index fb2d368fe..34171d943 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810pipeline.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810pipeline.c @@ -1,13 +1,15 @@ /* #include "i810pipeline.h" */ #include <stdio.h> + +#include "types.h" +#include "fog.h" + #include "i810vb.h" #include "i810dd.h" -#include "i810lib.h" #include "i810tris.h" #include "i810pipeline.h" -#include "fog.h" static struct gl_pipeline_stage i810_fast_stage = { "I810 fast path", diff --git a/xc/lib/GL/mesa/src/drv/i810/i810span.c b/xc/lib/GL/mesa/src/drv/i810/i810span.c index 20c463b9b..aa4f22d0c 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810span.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810span.c @@ -1,7 +1,5 @@ #include "types.h" #include "i810dd.h" -#include "i810lib.h" -#include "i810dma.h" #include "i810log.h" #include "i810span.h" #include "i810ioctl.h" @@ -127,7 +125,7 @@ do { \ /* 16 bit depthbuffer functions. */ #define WRITE_DEPTH( _x, _y, d ) \ - *(GLushort *)(buf + _x*2 + _y*pitch) = d; + *(GLushort *)(buf + _x*2 + _y*pitch) = d; #define READ_DEPTH( d, _x, _y ) \ d = *(GLushort *)(buf + _x*2 + _y*pitch); diff --git a/xc/lib/GL/mesa/src/drv/i810/i810state.c b/xc/lib/GL/mesa/src/drv/i810/i810state.c index bc3391e42..80332e3b3 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810state.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810state.c @@ -7,24 +7,40 @@ #include "dd.h" #include "mm.h" -#include "i810lib.h" #include "i810dd.h" #include "i810context.h" #include "i810state.h" -#include "i810depth.h" #include "i810tex.h" #include "i810log.h" #include "i810vb.h" #include "i810tris.h" +#include "i810ioctl.h" + + +static __inline__ GLuint i810PackColor(GLuint format, + GLubyte r, GLubyte g, + GLubyte b, GLubyte a) +{ + switch (format) { + case DV_PF_555: + return I810PACKCOLOR1555(r,g,b,a); + case DV_PF_565: + return I810PACKCOLOR565(r,g,b); + default: + fprintf(stderr, "unknown format %d\n", (int)format); + return 0; + } +} static void i810DDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) { i810ContextPtr imesa = I810_CONTEXT(ctx); - CARD32 a = (ZA_UPDATE_ALPHAFUNC|ZA_UPDATE_ALPHAREF); + FLUSH_BATCH(imesa); + switch (ctx->Color.AlphaFunc) { case GL_NEVER: a |= ZA_ALPHA_NEVER; break; case GL_LESS: a |= ZA_ALPHA_LESS; break; @@ -44,10 +60,6 @@ static void i810DDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) imesa->Setup[I810_CTXREG_ZA] |= a; } -/* This shouldn't get called, as the extension is disabled. However, - * there are internal Mesa calls, and rogue use of the api which must be - * caught. - */ static void i810DDBlendEquation(GLcontext *ctx, GLenum mode) { if (mode != GL_FUNC_ADD_EXT) { @@ -60,9 +72,8 @@ static void i810DDBlendEquation(GLcontext *ctx, GLenum mode) static void i810DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) { i810ContextPtr imesa = I810_CONTEXT(ctx); - GLuint a; - - a = SDM_UPDATE_SRC_BLEND | SDM_UPDATE_DST_BLEND; + GLuint a = SDM_UPDATE_SRC_BLEND | SDM_UPDATE_DST_BLEND; + FLUSH_BATCH(imesa); switch (ctx->Color.BlendSrcRGB) { case GL_ZERO: a |= SDM_SRC_ZERO; break; @@ -73,13 +84,8 @@ static void i810DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) case GL_ONE_MINUS_SRC_ALPHA: a |= SDM_SRC_INV_SRC_ALPHA; break; case GL_DST_ALPHA: a |= SDM_SRC_ONE; break; case GL_ONE_MINUS_DST_ALPHA: a |= SDM_SRC_ZERO; break; - case GL_SRC_ALPHA_SATURATE: - a |= SDM_SRC_SRC_ALPHA; /* use GFXRENDERSTATE_COLOR_FACTOR ??? */ - break; - default: - i810Error("unknown blend source func"); - exit(1); - return; + case GL_SRC_ALPHA_SATURATE: a |= SDM_SRC_SRC_ALPHA; break; + default: return; } switch (ctx->Color.BlendDstRGB) { @@ -91,10 +97,7 @@ static void i810DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) case GL_ONE_MINUS_SRC_COLOR: a |= SDM_DST_INV_SRC_COLOR; break; case GL_DST_ALPHA: a |= SDM_DST_ONE; break; case GL_ONE_MINUS_DST_ALPHA: a |= SDM_DST_ZERO; break; - default: - i810Error( "unknown blend dst func"); - exit(1); - return; + default: return; } imesa->dirty |= I810_UPLOAD_CTX; @@ -123,6 +126,8 @@ static void i810DDDepthFunc(GLcontext *ctx, GLenum func) i810ContextPtr imesa = I810_CONTEXT(ctx); int zmode; + FLUSH_BATCH(imesa); + switch(func) { case GL_NEVER: zmode = LCS_Z_NEVER; break; case GL_ALWAYS: zmode = LCS_Z_ALWAYS; break; @@ -134,9 +139,9 @@ static void i810DDDepthFunc(GLcontext *ctx, GLenum func) case GL_NOTEQUAL: zmode = LCS_Z_NOTEQUAL; break; default: return; } - + imesa->Setup[I810_CTXREG_LCS] &= ~LCS_Z_MASK; - imesa->Setup[I810_CTXREG_LCS] |= LCS_UPDATE_ZMODE | zmode; + imesa->Setup[I810_CTXREG_LCS] |= LCS_UPDATE_ZMODE | zmode; imesa->dirty |= I810_UPLOAD_CTX; } @@ -144,20 +149,62 @@ static void i810DDDepthMask(GLcontext *ctx, GLboolean flag) { i810ContextPtr imesa = I810_CONTEXT(ctx); + FLUSH_BATCH(imesa); + imesa->dirty |= I810_UPLOAD_CTX; imesa->Setup[I810_CTXREG_B2] &= ~B2_ZB_WRITE_ENABLE; - imesa->Setup[I810_CTXREG_B2] |= B2_UPDATE_ZB_WRITE_ENABLE; if (flag) imesa->Setup[I810_CTXREG_B2] |= B2_ZB_WRITE_ENABLE; } +/* ============================================================= + * Polygon stipple + * + * The i810 supports a 4x4 stipple natively, GL wants 32x32. + * Fortunately stipple is usually a repeating pattern. Could + * also consider using a multitexturing mechanism for this, but + * that has real issues, too. + */ +static void i810DDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + const GLubyte *m = mask; + GLubyte p[4]; + int i,j,k; + int active = (ctx->Polygon.StippleFlag && ctx->PB->primitive == GL_POLYGON); + FLUSH_BATCH(imesa); + ctx->Driver.TriangleCaps |= DD_TRI_STIPPLE; + if (active) { + imesa->dirty |= I810_UPLOAD_CTX; + imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE; + } - - + p[0] = mask[0] & 0xf; p[0] |= p[0] << 4; + p[1] = mask[4] & 0xf; p[1] |= p[1] << 4; + p[2] = mask[8] & 0xf; p[2] |= p[2] << 4; + p[3] = mask[12] & 0xf; p[3] |= p[3] << 4; + + for (k = 0 ; k < 8 ; k++) + for (j = 0 ; j < 4; j++) + for (i = 0 ; i < 4 ; i++) + if (*m++ != p[j]) { + ctx->Driver.TriangleCaps &= ~DD_TRI_STIPPLE; + return; + } + + imesa->Setup[I810_CTXREG_ST1] &= ~0xffff; + imesa->Setup[I810_CTXREG_ST1] |= ( ((p[0] & 0xf) << 0) | + ((p[1] & 0xf) << 4) | + ((p[2] & 0xf) << 8) | + ((p[3] & 0xf) << 12) ); + + if (active) + imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE; +} @@ -167,40 +214,26 @@ static void i810DDDepthMask(GLcontext *ctx, GLboolean flag) static void i810DDScissor( GLcontext *ctx, GLint x, GLint y, - GLsizei w, GLsizei h ) + GLsizei w, GLsizei h ) { i810ContextPtr imesa = I810_CONTEXT(ctx); - __DRIdrawablePrivate *dPriv = imesa->driDrawable; - int x1,x2,y1,y2; - x1 = ctx->Scissor.X; - x2 = ctx->Scissor.X + ctx->Scissor.Width - 1; - y1 = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height; - y2 = dPriv->h - ctx->Scissor.Y - 1; - - if (x1 < 0) x1 = 0; - if (y1 < 0) y1 = 0; - if (x2 >= dPriv->w) x2 = dPriv->w-1; - if (y2 >= dPriv->h) y2 = dPriv->h-1; - - if (x1 > x2 || y1 > y2) { - x1 = 0; x2 = 0; - y2 = 0; y1 = 1; - } + FLUSH_BATCH(imesa); + imesa->scissor_rect.x1 = x; + imesa->scissor_rect.y1 = imesa->driDrawable->h - (y+h); + imesa->scissor_rect.x2 = x+w; + imesa->scissor_rect.y2 = imesa->driDrawable->h - y; - /* Need to push this into drawing rectangle. - */ -#if 0 - imesa->Setup[I810_CTXREG_SCI0] = GFX_OP_SCISSOR_INFO; - imesa->Setup[I810_CTXREG_SCI1] = (y1<<16)|x1; - imesa->Setup[I810_CTXREG_SCI2] = (y2<<16)|x2; + if (I810_DEBUG&DEBUG_VERBOSE_2D) + fprintf(stderr, "SET SCISSOR %d,%d-%d,%d\n", + imesa->scissor_rect.x1, + imesa->scissor_rect.y1, + imesa->scissor_rect.x2, + imesa->scissor_rect.y2); - /* Need to intersect with cliprects??? - */ - imesa->dirty |= I810_UPLOAD_CTX; -#endif + imesa->dirty |= I810_UPLOAD_CLIPRECTS; } @@ -209,38 +242,56 @@ static void i810DDDither(GLcontext *ctx, GLboolean enable) } -static GLboolean i810DDSetBuffer(GLcontext *ctx, GLenum mode ) +static GLboolean i810DDSetDrawBuffer(GLcontext *ctx, GLenum mode ) { i810ContextPtr imesa = I810_CONTEXT(ctx); + FLUSH_BATCH(imesa); - fprintf(stderr, "i810DDSetBuffer %s\n", gl_lookup_enum_by_nr( mode )); - - imesa->Fallback &= ~I810_FALLBACK_BUFFER; + imesa->Fallback &= ~I810_FALLBACK_DRAW_BUFFER; if (mode == GL_FRONT_LEFT) { - imesa->drawOffset = imesa->i810Screen->fbOffset; + imesa->drawMap = imesa->driScreen->pFB; imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->fbOffset | - imesa->i810Screen->auxPitchBits); + imesa->i810Screen->backPitchBits); imesa->dirty |= I810_UPLOAD_BUFFERS; i810XMesaSetFrontClipRects( imesa ); return GL_TRUE; } else if (mode == GL_BACK_LEFT) { - imesa->drawOffset = imesa->i810Screen->backOffset; + imesa->drawMap = imesa->i810Screen->back.map; imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->backOffset | - imesa->i810Screen->auxPitchBits); + imesa->i810Screen->backPitchBits); imesa->dirty |= I810_UPLOAD_BUFFERS; i810XMesaSetBackClipRects( imesa ); return GL_TRUE; } - imesa->Fallback |= I810_FALLBACK_BUFFER; + imesa->Fallback |= I810_FALLBACK_DRAW_BUFFER; return GL_FALSE; } +static void i810DDSetReadBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, + GLenum mode ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + + if (mode == GL_FRONT_LEFT) + { + imesa->readMap = imesa->driScreen->pFB; + imesa->Fallback &= ~I810_FALLBACK_READ_BUFFER; + } + else if (mode == GL_BACK_LEFT) + { + imesa->readMap = imesa->i810Screen->back.map; + imesa->Fallback &= ~I810_FALLBACK_READ_BUFFER; + } + else + imesa->Fallback |= I810_FALLBACK_READ_BUFFER; +} + static void i810DDSetColor(GLcontext *ctx, @@ -248,9 +299,7 @@ static void i810DDSetColor(GLcontext *ctx, GLubyte b, GLubyte a ) { i810ContextPtr imesa = I810_CONTEXT(ctx); - - imesa->MonoColor = i810PackColor( imesa->i810Screen->fbFormat, - r, g, b, a ); + imesa->MonoColor = i810PackColor( imesa->i810Screen->fbFormat, r, g, b, a ); } @@ -259,9 +308,7 @@ static void i810DDClearColor(GLcontext *ctx, GLubyte b, GLubyte a ) { i810ContextPtr imesa = I810_CONTEXT(ctx); - - imesa->ClearColor = i810PackColor( imesa->i810Screen->fbFormat, - r, g, b, a ); + imesa->ClearColor = i810PackColor( imesa->i810Screen->fbFormat, r, g, b, a ); } @@ -274,6 +321,8 @@ static void i810DDCullFaceFrontFace(GLcontext *ctx, GLenum unused) i810ContextPtr imesa = I810_CONTEXT(ctx); GLuint mode = LCS_CULL_BOTH; + FLUSH_BATCH(imesa); + if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { mode = LCS_CULL_CW; if (ctx->Polygon.CullFaceMode == GL_FRONT) @@ -288,27 +337,49 @@ static void i810DDCullFaceFrontFace(GLcontext *ctx, GLenum unused) { imesa->dirty |= I810_UPLOAD_CTX; imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK; - imesa->Setup[I810_CTXREG_LCS] |= (LCS_UPDATE_CULL_MODE | mode); + imesa->Setup[I810_CTXREG_LCS] |= mode; } } static void i810DDReducedPrimitiveChange( GLcontext *ctx, GLenum prim ) { - if (ctx->Polygon.CullFlag) { - i810ContextPtr imesa = I810_CONTEXT(ctx); - GLuint mode = imesa->LcsCullMode; - - if (ctx->PB->primitive != GL_POLYGON) - mode = LCS_CULL_DISABLE; - - imesa->dirty |= I810_UPLOAD_CTX; - imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK; - imesa->Setup[I810_CTXREG_LCS] |= (LCS_UPDATE_CULL_MODE | mode); + i810ContextPtr imesa = I810_CONTEXT(ctx); + FLUSH_BATCH(imesa); - LOCK_HARDWARE(imesa); - i810EmitHwStateLocked( imesa ); - UNLOCK_HARDWARE(imesa); + imesa->dirty |= I810_UPLOAD_CTX; + imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK; + imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE; + imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; + + switch (ctx->PB->primitive) { + case GL_POLYGON: + if (ctx->Polygon.StippleFlag && + (ctx->Driver.TriangleCaps & DD_TRI_STIPPLE)) + imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE; + if (ctx->Polygon.CullFlag) + imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsCullMode; + else + imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; + if (ctx->Polygon.SmoothFlag) + imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; + break; + case GL_LINES: + imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5; + if (ctx->Line.SmoothFlag) { + imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; + imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5; + } + imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; + break; + case GL_POINTS: + if (ctx->Point.SmoothFlag) + imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; + imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; + break; + default: + imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; + break; } } @@ -318,15 +389,36 @@ static void i810DDReducedPrimitiveChange( GLcontext *ctx, GLenum prim ) * Color masks */ -/* Mesa calls this from the wrong place. +/* Mesa calls this from the wrong place - it is called a very large + * number of redundant times. * - * Its a fallback... + * Colormask can be simulated by multipass or multitexture techniques. */ static GLboolean i810DDColorMask(GLcontext *ctx, GLboolean r, GLboolean g, GLboolean b, GLboolean a ) { - return 1; + i810ContextPtr imesa = I810_CONTEXT( ctx ); + GLuint tmp = 0; + GLuint rv = 1; + + imesa->Fallback &= ~I810_FALLBACK_COLORMASK; + + if (r && g && b) { + tmp = imesa->Setup[I810_CTXREG_B2] | B2_FB_WRITE_ENABLE; + } else if (!r && !g && !b) { + tmp = imesa->Setup[I810_CTXREG_B2] & ~B2_FB_WRITE_ENABLE; + } else { + rv = 0; + imesa->Fallback |= I810_FALLBACK_COLORMASK; + } + + if (tmp != imesa->Setup[I810_CTXREG_B2]) { + FLUSH_BATCH(imesa); + imesa->Setup[I810_CTXREG_B2] = tmp; + } + + return rv; } /* Seperate specular not fully implemented in hardware... Needs @@ -336,8 +428,14 @@ static GLboolean i810DDColorMask(GLcontext *ctx, static void i810DDLightModelfv(GLcontext *ctx, GLenum pname, const GLfloat *param) { - if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { - I810_CONTEXT(ctx)->new_state |= I810_NEW_TEXTURE; + if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) + { + i810ContextPtr imesa = I810_CONTEXT( ctx ); + FLUSH_BATCH(imesa); + + imesa->Fallback &= ~I810_FALLBACK_SPECULAR; + if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) + imesa->Fallback |= I810_FALLBACK_SPECULAR; } } @@ -372,64 +470,105 @@ static void i810DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) switch(cap) { case GL_ALPHA_TEST: + FLUSH_BATCH(imesa); imesa->dirty |= I810_UPLOAD_CTX; imesa->Setup[I810_CTXREG_B1] &= ~B1_ALPHA_TEST_ENABLE; - imesa->Setup[I810_CTXREG_B1] |= B1_UPDATE_ALPHA_TEST_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_ALPHA_TEST_ENABLE; break; case GL_BLEND: + FLUSH_BATCH(imesa); imesa->dirty |= I810_UPLOAD_CTX; imesa->Setup[I810_CTXREG_B1] &= ~B1_BLEND_ENABLE; - imesa->Setup[I810_CTXREG_B1] |= B1_UPDATE_BLEND_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_BLEND_ENABLE; break; case GL_DEPTH_TEST: + FLUSH_BATCH(imesa); imesa->dirty |= I810_UPLOAD_CTX; imesa->Setup[I810_CTXREG_B1] &= ~B1_Z_TEST_ENABLE; - imesa->Setup[I810_CTXREG_B1] |= B1_UPDATE_Z_TEST_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_Z_TEST_ENABLE; break; case GL_SCISSOR_TEST: -#if 0 - imesa->dirty |= I810_UPLOAD_CTX; - imesa->Setup[I810_CTXREG_SC] &= ~SC_ENABLE_MASK; - imesa->Setup[I810_CTXREG_SC] |= SC_UPDATE_SCISSOR; - if (state) - imesa->Setup[I810_CTXREG_SC] |= SC_ENABLE; -#endif + FLUSH_BATCH(imesa); + imesa->scissor = state; + imesa->dirty |= I810_UPLOAD_CLIPRECTS; + break; + case GL_POLYGON_STIPPLE: + if ((ctx->Driver.TriangleCaps & DD_TRI_STIPPLE) && + ctx->PB->primitive == GL_POLYGON) + { + FLUSH_BATCH(imesa); + imesa->dirty |= I810_UPLOAD_CTX; + imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE; + if (state) + imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE; + } + break; + case GL_LINE_SMOOTH: + if (ctx->PB->primitive == GL_LINE) { + FLUSH_BATCH(imesa); + imesa->dirty |= I810_UPLOAD_CTX; + imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; + imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5; + if (state) { + imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; + imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5; + } + } + break; + case GL_POINT_SMOOTH: + if (ctx->PB->primitive == GL_POINT) { + FLUSH_BATCH(imesa); + imesa->dirty |= I810_UPLOAD_CTX; + imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; + if (state) + imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; + } + break; + case GL_POLYGON_SMOOTH: + if (ctx->PB->primitive == GL_POLYGON) { + FLUSH_BATCH(imesa); + imesa->dirty |= I810_UPLOAD_CTX; + imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; + if (state) + imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; + } break; case GL_FOG: + FLUSH_BATCH(imesa); imesa->dirty |= I810_UPLOAD_CTX; imesa->Setup[I810_CTXREG_B1] &= ~B1_FOG_ENABLE; - imesa->Setup[I810_CTXREG_B1] |= B1_UPDATE_FOG_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_FOG_ENABLE; break; case GL_CULL_FACE: if (ctx->PB->primitive == GL_POLYGON) { + FLUSH_BATCH(imesa); imesa->dirty |= I810_UPLOAD_CTX; imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK; - imesa->Setup[I810_CTXREG_LCS] |= LCS_UPDATE_CULL_MODE; if (state) imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsCullMode; else imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; } break; + case GL_TEXTURE_1D: + case GL_TEXTURE_3D: + FLUSH_BATCH(imesa); + imesa->new_state |= I810_NEW_TEXTURE; + break; case GL_TEXTURE_2D: + FLUSH_BATCH(imesa); imesa->new_state |= I810_NEW_TEXTURE; imesa->dirty |= I810_UPLOAD_CTX; if (ctx->Texture.CurrentUnit == 0) { imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL0_ENABLE; - imesa->Setup[I810_CTXREG_MT] |= MT_UPDATE_TEXEL0_STATE; if (state) imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL0_ENABLE; } else { imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL1_ENABLE; - imesa->Setup[I810_CTXREG_MT] |= MT_UPDATE_TEXEL1_STATE; if (state) imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL1_ENABLE; } @@ -444,92 +583,20 @@ static void i810DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) /* ============================================================= */ -/* Delightfully few possibilities: - */ -void i810DDPrintState( const char *msg, GLuint state ) -{ - fprintf(stderr, "%s (0x%x): %s\n", - msg, - (unsigned int) state, - (state & I810_NEW_TEXTURE) ? "texture, " : ""); -} void i810DDUpdateHwState( GLcontext *ctx ) { i810ContextPtr imesa = I810_CONTEXT(ctx); - if (imesa->new_state & I810_NEW_TEXTURE) + if (imesa->new_state & I810_NEW_TEXTURE) { + FLUSH_BATCH(imesa); i810UpdateTextureState( ctx ); - - imesa->new_state = 0; - - if (imesa->dirty) { - LOCK_HARDWARE(imesa); - i810EmitHwStateLocked( imesa ); - UNLOCK_HARDWARE(imesa); - } -} - - - -/* - * i810DmaExecute - * Add a block of data to the dma buffer - * - * -- In ring buffer mode, must be called with lock held, and translates to - * OUT_RING rather than outbatch - * - * -- In dma mode, probably won't be used because state updates will have - * to be done via the kernel for security... - */ -static void i810DmaExecute( i810ContextPtr imesa, - GLuint *code, int dwords, const char *where ) -{ - if (I810_DEBUG & DEBUG_VERBOSE_RING) - fprintf(stderr, "i810DmaExecute (%s)\n", where); - - if (dwords & 1) { - i810Error( "Misaligned buffer in i810DmaExecute\n" ); - exit(1); } - { - int i; - BEGIN_BATCH( imesa, dwords); - - for ( i = 0 ; i < dwords ; i++ ) { - if (0) fprintf(stderr, "%d: %x\n", i, code[i]); - OUT_BATCH( code[i] ); - } - - ADVANCE_BATCH(); - } + imesa->new_state = 0; } - -void i810EmitScissorValues( i810ContextPtr imesa, int nr, int emit ) -{ - int x1 = imesa->pClipRects[nr].x1 - imesa->drawX; - int y1 = imesa->pClipRects[nr].y1 - imesa->drawY; - int x2 = imesa->pClipRects[nr].x2 - imesa->drawX; - int y2 = imesa->pClipRects[nr].y2 - imesa->drawY; - - if (I810_DEBUG&DEBUG_VERBOSE_DRI) - fprintf(stderr, "i810EmitScissorValues %d,%d - %d,%d\n", - x1,y1,x2,y2); - - imesa->ClipSetup[I810_CLIPREG_SCI1] = (x1 | (y1 << 16)); - imesa->ClipSetup[I810_CLIPREG_SCI2] = (x2 | (y2 << 16)); - imesa->ClipSetup[I810_CLIPREG_SC] = ( GFX_OP_SCISSOR | - SC_UPDATE_SCISSOR | - SC_ENABLE ); - - if (emit) - i810DmaExecute( imesa, - imesa->ClipSetup, I810_CLIP_SETUP_SIZE, "cliprect" ); -} - void i810EmitDrawingRectangle( i810ContextPtr imesa ) { __DRIdrawablePrivate *dPriv = imesa->driDrawable; @@ -545,7 +612,6 @@ void i810EmitDrawingRectangle( i810ContextPtr imesa ) */ imesa->BufferSetup[I810_DESTREG_DR4] = ((y0<<16) | (((unsigned)x0)&0xFFFF)); - /* Clip to screen. */ @@ -556,74 +622,74 @@ void i810EmitDrawingRectangle( i810ContextPtr imesa ) /* Onscreen drawing rectangle. - * - * TODO: clip again to GL scissor values. */ imesa->BufferSetup[I810_DESTREG_DR2] = ((y0<<16) | x0); - imesa->BufferSetup[I810_DESTREG_DR3] = ((y1<<16) | x1); + imesa->BufferSetup[I810_DESTREG_DR3] = (((y1+1)<<16) | (x1+1)); imesa->dirty |= I810_UPLOAD_BUFFERS; } static void i810DDPrintDirty( const char *msg, GLuint state ) { - fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n", + fprintf(stderr, "%s (0x%x): %s%s%s%s%s\n", msg, (unsigned int) state, - (state & I810_REFRESH_RING) ? "read-lp-ring, " : "", - (state & I810_REQUIRE_QUIESCENT) ? "req-quiescent, " : "", (state & I810_UPLOAD_TEX0IMAGE) ? "upload-tex0, " : "", (state & I810_UPLOAD_TEX1IMAGE) ? "upload-tex1, " : "", (state & I810_UPLOAD_CTX) ? "upload-ctx, " : "", (state & I810_UPLOAD_BUFFERS) ? "upload-bufs, " : "", - (state & I810_EMIT_CLIPRECT) ? "emit-single-cliprect, " : "" + (state & I810_UPLOAD_CLIPRECTS) ? "upload-cliprects, " : "" ); } -/* Spew the state onto the ringbuffer and/or texture memory. +/* Push the state into the sarea and/or texture memory. */ void i810EmitHwStateLocked( i810ContextPtr imesa ) { if (I810_DEBUG & DEBUG_VERBOSE_API) - i810DDPrintDirty( "i810EmitHwStateLocked", imesa->dirty ); - - if (imesa->dirty & I810_REQUIRE_QUIESCENT) { - i810glx.c_drawWaits += _I810Sync( imesa ); - } + i810DDPrintDirty( "\n\n\ni810EmitHwStateLocked", imesa->dirty ); - /* TODO: Refine mechanism to be equivalent to UploadSubImage - */ - if ((imesa->dirty & I810_UPLOAD_TEX0IMAGE) && imesa->CurrentTexObj[0]) - i810UploadTexImages(imesa, imesa->CurrentTexObj[0]); + if (imesa->dirty & ~I810_UPLOAD_CLIPRECTS) + { + if ((imesa->dirty & I810_UPLOAD_TEX0IMAGE) && imesa->CurrentTexObj[0]) + i810UploadTexImages(imesa, imesa->CurrentTexObj[0]); - if ((imesa->dirty & I810_UPLOAD_TEX1IMAGE) && imesa->CurrentTexObj[1]) - i810UploadTexImages(imesa, imesa->CurrentTexObj[1]); + if ((imesa->dirty & I810_UPLOAD_TEX1IMAGE) && imesa->CurrentTexObj[1]) + i810UploadTexImages(imesa, imesa->CurrentTexObj[1]); - if ((imesa->dirty & I810_UPLOAD_CTX)) { - i810DmaExecute( imesa, imesa->Setup, I810_CTX_SETUP_SIZE, "context" ); - - if (imesa->CurrentTexObj[0]) - i810DmaExecute( imesa, imesa->CurrentTexObj[0]->Setup, - I810_TEX_SETUP_SIZE, "tex-0"); + if (imesa->dirty & I810_UPLOAD_CTX) + memcpy( imesa->sarea->ContextState, + imesa->Setup, + sizeof(imesa->Setup) ); + + if ((imesa->dirty & I810_UPLOAD_TEX0) && imesa->CurrentTexObj[0]) { + imesa->sarea->dirty |= I810_UPLOAD_TEX0; + memcpy(imesa->sarea->TexState[0], + imesa->CurrentTexObj[0]->Setup, + sizeof(imesa->sarea->TexState[0])); + } - if (imesa->CurrentTexObj[1]) - i810DmaExecute( imesa, imesa->CurrentTexObj[1]->Setup, - I810_TEX_SETUP_SIZE, "tex-1"); + if ((imesa->dirty & I810_UPLOAD_TEX1) && imesa->CurrentTexObj[1]) { + imesa->sarea->dirty |= I810_UPLOAD_TEX1; + memcpy(imesa->sarea->TexState[1], + imesa->CurrentTexObj[1]->Setup, + sizeof(imesa->sarea->TexState[1])); + } + + if (imesa->dirty & I810_UPLOAD_BUFFERS) + memcpy( imesa->sarea->BufferState, + imesa->BufferSetup, + sizeof(imesa->BufferSetup) ); + + imesa->sarea->dirty |= (imesa->dirty & + ~(I810_UPLOAD_TEX1|I810_UPLOAD_TEX0)); + imesa->dirty &= I810_UPLOAD_CLIPRECTS; } - - if (imesa->dirty & I810_UPLOAD_BUFFERS) - i810DmaExecute( imesa, imesa->BufferSetup, - I810_DEST_SETUP_SIZE, "buffers" ); - - if (imesa->dirty & I810_EMIT_CLIPRECT) - i810DmaExecute( imesa, imesa->ClipSetup, - I810_CLIP_SETUP_SIZE, "cliprect" ); - - imesa->dirty = 0; } + void i810DDInitState( i810ContextPtr imesa ) { i810ScreenPrivate *i810Screen = imesa->i810Screen; @@ -797,7 +863,7 @@ void i810DDInitState( i810ContextPtr imesa ) LCS_UPDATE_ZMODE | LCS_Z_LESS | LCS_UPDATE_LINEWIDTH | - (0x2<<LCS_LINEWIDTH_SHIFT) | + LCS_LINEWIDTH_1_0 | LCS_UPDATE_ALPHA_INTERP | LCS_ALPHA_INTERP | LCS_UPDATE_FOG_INTERP | @@ -825,11 +891,9 @@ void i810DDInitState( i810ContextPtr imesa ) imesa->Setup[I810_CTXREG_ST0] = GFX_OP_STIPPLE; imesa->Setup[I810_CTXREG_ST1] = 0; - - imesa->Setup[I810_CTXREG_AA] = ( GFX_OP_ANTIALIAS | AA_UPDATE_EDGEFLAG | - 0 | + AA_ENABLE_EDGEFLAG | /* ? */ AA_UPDATE_POLYWIDTH | AA_POLYWIDTH_05 | AA_UPDATE_LINEWIDTH | @@ -839,38 +903,29 @@ void i810DDInitState( i810ContextPtr imesa ) AA_UPDATE_AA_ENABLE | 0 ); - - - memset(imesa->ClipSetup, 0, sizeof(imesa->ClipSetup)); - imesa->ClipSetup[I810_CLIPREG_SCI0] = GFX_OP_SCISSOR_INFO; - imesa->ClipSetup[I810_CLIPREG_SCI1] = 0; - imesa->ClipSetup[I810_CLIPREG_SCI2] = 0; - imesa->ClipSetup[I810_CLIPREG_SC] = ( GFX_OP_SCISSOR | - SC_UPDATE_SCISSOR | - 0 ); - - /* This stuff is all invarient as long as we are using - * shared back and depth buffers. - */ memset(imesa->BufferSetup, 0, sizeof(imesa->BufferSetup)); - imesa->drawOffset = i810Screen->backOffset; imesa->BufferSetup[I810_DESTREG_DI0] = CMD_OP_DESTBUFFER_INFO; - if (imesa->glCtx->Color.DriverDrawBuffer == GL_BACK_LEFT) + if (imesa->glCtx->Color.DriverDrawBuffer == GL_BACK_LEFT) { + imesa->drawMap = i810Screen->back.map; imesa->BufferSetup[I810_DESTREG_DI1] = (i810Screen->backOffset | - i810Screen->auxPitchBits); - else + i810Screen->backPitchBits); + } else { + imesa->drawMap = imesa->driScreen->pFB; imesa->BufferSetup[I810_DESTREG_DI1] = (i810Screen->fbOffset | - i810Screen->auxPitchBits); + i810Screen->backPitchBits); + } + if (imesa->glCtx->Color.DriverDrawBuffer == GL_BACK_LEFT) { + imesa->readMap = i810Screen->back.map; + } else { + imesa->readMap = imesa->driScreen->pFB; + } imesa->BufferSetup[I810_DESTREG_DV0] = GFX_OP_DESTBUFFER_VARS; imesa->BufferSetup[I810_DESTREG_DV1] = (DV_HORG_BIAS_OGL | DV_VORG_BIAS_OGL | i810Screen->fbFormat); - imesa->BufferSetup[I810_DESTREG_ZB0] = CMD_OP_Z_BUFFER_INFO; - imesa->BufferSetup[I810_DESTREG_ZB1] = (i810Screen->depthOffset | - i810Screen->auxPitchBits); imesa->BufferSetup[I810_DESTREG_DR0] = GFX_OP_DRAWRECT_INFO; imesa->BufferSetup[I810_DESTREG_DR1] = DR1_RECT_CLIP_ENABLE; @@ -886,17 +941,31 @@ void i810DDUpdateState( GLcontext *ctx ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); + /* Have to do this here to detect texture fallbacks in time: + */ + if (I810_CONTEXT(ctx)->new_state & I810_NEW_TEXTURE) + i810DDUpdateHwState( ctx ); + + if (ctx->NewState & INTERESTED) { i810DDChooseRenderState(ctx); i810ChooseRasterSetupFunc(ctx); } + + if (0) + fprintf(stderr, "IndirectTriangles %x Fallback %x\n", + imesa->IndirectTriangles, imesa->Fallback); - /* TODO: stop mesa from clobbering these. - */ - ctx->Driver.PointsFunc=imesa->PointsFunc; - ctx->Driver.LineFunc=imesa->LineFunc; - ctx->Driver.TriangleFunc=imesa->TriangleFunc; - ctx->Driver.QuadFunc=imesa->QuadFunc; + if (!imesa->Fallback) + { + ctx->IndirectTriangles &= ~DD_SW_RASTERIZE; + ctx->IndirectTriangles |= imesa->IndirectTriangles; + + ctx->Driver.PointsFunc=imesa->PointsFunc; + ctx->Driver.LineFunc=imesa->LineFunc; + ctx->Driver.TriangleFunc=imesa->TriangleFunc; + ctx->Driver.QuadFunc=imesa->QuadFunc; + } } @@ -919,8 +988,13 @@ void i810DDInitStateFuncs(GLcontext *ctx) ctx->Driver.ReducedPrimitiveChange = i810DDReducedPrimitiveChange; ctx->Driver.RenderStart = i810DDUpdateHwState; ctx->Driver.RenderFinish = 0; + + ctx->Driver.PolygonStipple = i810DDPolygonStipple; + ctx->Driver.LineStipple = 0; + + ctx->Driver.SetReadBuffer = i810DDSetReadBuffer; + ctx->Driver.SetDrawBuffer = i810DDSetDrawBuffer; - ctx->Driver.SetBuffer = i810DDSetBuffer; ctx->Driver.Color = i810DDSetColor; ctx->Driver.ClearColor = i810DDClearColor; ctx->Driver.Dither = i810DDDither; @@ -928,6 +1002,5 @@ void i810DDInitStateFuncs(GLcontext *ctx) ctx->Driver.Index = 0; ctx->Driver.ClearIndex = 0; ctx->Driver.IndexMask = 0; - } diff --git a/xc/lib/GL/mesa/src/drv/i810/i810state.h b/xc/lib/GL/mesa/src/drv/i810/i810state.h index d0551631e..b43a1a4ff 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810state.h +++ b/xc/lib/GL/mesa/src/drv/i810/i810state.h @@ -1,13 +1,12 @@ #ifndef _I810_STATE_H #define _I810_STATE_H +#include "i810context.h" extern void i810DDUpdateHwState( GLcontext *ctx ); extern void i810DDUpdateState( GLcontext *ctx ); extern void i810DDInitState( i810ContextPtr imesa ); extern void i810DDInitStateFuncs( GLcontext *ctx ); -extern void i810DDPrintState( const char *msg, GLuint state ); - #endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810swap.c b/xc/lib/GL/mesa/src/drv/i810/i810swap.c deleted file mode 100644 index 9220ef9f4..000000000 --- a/xc/lib/GL/mesa/src/drv/i810/i810swap.c +++ /dev/null @@ -1,259 +0,0 @@ - - -#include "types.h" -#include "vbrender.h" -#include "i810log.h" - -#include <stdio.h> -#include <stdlib.h> - -#include "mm.h" -#include "i810lib.h" -#include "i810dd.h" -#include "i810dma.h" -#include "i810state.h" -#include "i810swap.h" -#include "i810dma.h" - -/* - * i810BackToFront - * - * Blit the visible rectangles from the back buffer to the screen. - * Respects the frontbuffer cliprects, and applies the offset - * necessary if the backbuffer is positioned elsewhere in the screen. - */ -static int i810BackToFront( i810ContextPtr imesa ) -{ - __DRIdrawablePrivate *dPriv = imesa->driDrawable; - i810ScreenPrivate *i810Screen = imesa->i810Screen; - - - /* Use the frontbuffer cliprects: - */ - XF86DRIClipRectPtr pbox = dPriv->pClipRects; - int nbox = dPriv->numClipRects; - - if( nbox ) - { - int i; - int pitch = i810Screen->auxPitch; - - int dx = dPriv->auxX - dPriv->x; - int dy = dPriv->auxY - dPriv->y; - int ofs = ( i810Screen->backOffset + - dy * i810Screen->auxPitch + - dx * i810Screen->cpp); - - unsigned int BR13 = ((i810Screen->fbStride) | - (0xCC << 16)); - - - for (i=0; i < nbox; i++, pbox++) { - int w = pbox->x2 - pbox->x1; - int h = pbox->y2 - pbox->y1; - - int start = ofs + pbox->x1*i810Screen->cpp + pbox->y1*pitch; - int dst = pbox->x1*i810Screen->cpp + pbox->y1*i810Screen->fbStride; - - if (I810_DEBUG&DEBUG_VERBOSE_2D) - fprintf(stderr, "i810BackToFront %d,%d-%dx%d\n", - pbox->x1,pbox->y1,w,h); - - { - BEGIN_BATCH( imesa, 6 ); - OUT_BATCH( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 ); - OUT_BATCH( BR13 ); /* dest pitch, rop */ - - OUT_BATCH( (h << 16) | (w * i810Screen->cpp)); - OUT_BATCH( dst ); - - OUT_BATCH( pitch ); /* src pitch */ - OUT_BATCH( start ); - ADVANCE_BATCH(); - } - } - } - - return Success; -} - - -/* - * ClearBox - * - * Add hardware commands to draw a filled box for the debugging - * display. These are drawn into the current drawbuffer, so should - * work with both front and backbuffer rendering. (However, it - * is only ever called on swapbuffer - ie backbuffer rendering). - */ -static void ClearBox( i810ContextPtr imesa, - int cx, int cy, int cw, int ch, - int r, int g, int b ) -{ - __DRIdrawablePrivate *dPriv = imesa->driDrawable; - i810ScreenPrivate *i810Screen = imesa->i810Screen; - - int _nc = imesa->numClipRects; - - while (_nc--) { - int x1 = cx + dPriv->x; - int y1 = cy + dPriv->y; - int x2 = x1 + cw; - int y2 = y1 + ch; - - if (imesa->needClip) { - int rx1 = imesa->pClipRects[_nc].x1; - int ry1 = imesa->pClipRects[_nc].y1; - int rx2 = imesa->pClipRects[_nc].x2; - int ry2 = imesa->pClipRects[_nc].y2; - - - if (x2 < rx1) continue; - if (y2 < ry1) continue; - if (x1 > rx2) continue; - if (y1 > ry2) continue; - if (x1 < rx1) x1 = rx1; - if (y1 < ry1) y1 = ry1; - if (x2 > rx2) x2 = rx2; - if (y2 > ry2) y2 = ry2; - } - - - { - int start = (imesa->drawOffset + - y1 * i810Screen->auxPitch + - x1 * i810Screen->cpp); - - BEGIN_BATCH( imesa, 6 ); - - OUT_BATCH( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); - OUT_BATCH( BR13_SOLID_PATTERN | - (0xF0 << 16) | - i810Screen->auxPitch ); - OUT_BATCH( ((y2-y1) << 16) | ((x2-x1) * i810Screen->cpp)); - OUT_BATCH( start ); - OUT_BATCH( i810PackColor( i810Screen->fbFormat, r, g, b, 0 ) ); - OUT_BATCH( 0 ); - - if (I810_DEBUG&DEBUG_VERBOSE_2D) - fprintf(stderr, "box %d,%x %d,%d col %x (%d,%d,%d)\n", - (int)x1,(int)y1, (int)x2,(int)y2, - (int)i810PackColor( i810Screen->fbFormat, r, g, b, 0 ), - (int)r, (int)g, (int)b); - - ADVANCE_BATCH(); - } - } -} - - -/* - * performanceBoxes - * Draw some small boxesin the corner of the buffer - * based on some performance information - */ -static void i810PerformanceBoxes( i810ContextPtr imesa ) { - - - /* draw a box to show we are active, so if it is't seen it means - that it is completely software based. Purple is traditional for - direct rendering */ - ClearBox( imesa, 4, 4, 8, 8, 255, 0, 255 ); - - /* draw a red box if we had to wait for drawing to complete - (software render or texture swap) */ - if ( i810glx.c_drawWaits ) { - ClearBox( imesa, 16, 4, 8, 8, 255, 0, 0 ); - i810glx.c_drawWaits = 0; - } - - /* draw a blue box if the 3d context was lost - */ - if ( i810glx.c_ctxlost ) { - ClearBox( imesa, 28, 4, 8, 8, 0, 0, 255 ); - i810glx.c_ctxlost = 0; - } - - /* draw an orange box if texture state was stomped */ - if ( i810glx.c_texlost ) { - ClearBox( imesa, 40, 4, 8, 8, 255, 128, 0 ); - i810glx.c_texlost = 0; - } - - /* draw a yellow box if textures were swapped */ - if ( i810glx.c_textureSwaps ) { - ClearBox( imesa, 56, 4, 8, 8, 255, 255, 0 ); - i810glx.c_textureSwaps = 0; - } - - /* draw a green box if we had to wait for dma to complete (full utilization) - on the previous frame */ - if ( !i810glx.hardwareWentIdle ) { - ClearBox( imesa, 72, 4, 8, 8, 0, 255, 0 ); - } - i810glx.hardwareWentIdle = 0; - -#if 0 - /* show buffer utilization */ - if ( i810glx.c_dmaFlush > 1 ) { - /* draw a solid bar if we flushed more than one buffer */ - ClearBox( imesa, 4, 16, 252, 4, 255, 32, 32 ); - } else { - /* draw bars to represent the utilization of primary and - secondary buffers */ - ClearBox( imesa, 4, 16, 252, 4, 32, 32, 32 ); - t = i810glx.dma_buffer->mem.Size; - w = 252 * i810glx.dma_buffer->head / t; - if ( w < 1 ) { - w = 1; - } - ClearBox( imesa, 4, 16, w, 4, 196, 128, 128 ); - } -#endif - - i810glx.c_dmaFlush = 0; -} - - -static void i810SendDmaFlush( i810ContextPtr imesa ) -{ - BEGIN_BATCH( imesa, 2 ); - OUT_BATCH( INST_PARSER_CLIENT | INST_OP_FLUSH ); - OUT_BATCH( 0 ); - ADVANCE_BATCH(); -} - -void i810SwapBuffers( i810ContextPtr imesa ) -{ - if (I810_DEBUG & DEBUG_VERBOSE_API) - fprintf(stderr, "i810SwapBuffers()\n"); - - LOCK_HARDWARE( imesa ); - i810SendDmaFlush( imesa ); - if ( i810glx.boxes ) - i810PerformanceBoxes( imesa ); - i810BackToFront( imesa ); - - /* Check if we are emitting thousands of tiny frames, and if so - * throttle them. Would be better to simply go to sleep until - * our stuff had cleared, rather than polling. A dma solution - * should provide for this. - */ - if (imesa->lastSwap >= imesa->sarea->lastWrap && - imesa->lastSwap >= imesa->sarea->lastSync) { - - if (I810_DEBUG & DEBUG_VERBOSE_API) - fprintf(stderr, "."); - - _I810Sync( imesa ); - } - - imesa->lastSwap = imesa->sarea->lastSync; - if (imesa->sarea->lastWrap > imesa->lastSwap) - imesa->lastSwap = imesa->sarea->lastWrap; - - - UNLOCK_HARDWARE( imesa ); - -/* XSync(imesa->display, 0); */ -} diff --git a/xc/lib/GL/mesa/src/drv/i810/i810swap.h b/xc/lib/GL/mesa/src/drv/i810/i810swap.h deleted file mode 100644 index 1657a717d..000000000 --- a/xc/lib/GL/mesa/src/drv/i810/i810swap.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef I810_SWAP_H -#define I810_SWAP_H - -extern void i810SwapBuffers( i810ContextPtr imesa ); - -#endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810tex.c b/xc/lib/GL/mesa/src/drv/i810/i810tex.c index 039c0af59..8c88f2b2b 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810tex.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810tex.c @@ -28,9 +28,10 @@ #include <GL/gl.h> #include "mm.h" -#include "i810lib.h" +#include "i810context.h" #include "i810tex.h" #include "i810log.h" +#include "i810ioctl.h" #include "simple_list.h" #include "enums.h" @@ -204,6 +205,7 @@ static i810TextureObjectPtr i810CreateTexObj(i810ContextPtr imesa, log_pitch++; t->dirty_images = 0; + t->bound = 0; for ( height = i = 0 ; i < I810_TEX_MAXLEVELS && tObj->Image[i] ; i++ ) { t->image[i].image = tObj->Image[i]; @@ -278,24 +280,24 @@ static i810TextureObjectPtr i810CreateTexObj(i810ContextPtr imesa, void i810DestroyTexObj(i810ContextPtr imesa, i810TextureObjectPtr t) { - int i; if (!t) return; /* This is sad - need to sync *in case* we upload a texture * to this newly free memory... */ if (t->MemBlock) { - imesa->dirty |= I810_REQUIRE_QUIESCENT; mmFreeMem(t->MemBlock); - t->MemBlock = 0; + t->MemBlock = 0; + + if (t->age > imesa->dirtyAge) + imesa->dirtyAge = t->age; } if (t->globj) t->globj->DriverData = 0; - for ( i = 0 ; i < 2 ; i++ ) - if ( imesa->CurrentTexObj[i] == t ) - imesa->CurrentTexObj[i] = 0; + if (t->bound) + imesa->CurrentTexObj[t->bound - 1] = 0; remove_from_list(t); free(t); @@ -305,9 +307,11 @@ void i810DestroyTexObj(i810ContextPtr imesa, i810TextureObjectPtr t) static void i810SwapOutTexObj(i810ContextPtr imesa, i810TextureObjectPtr t) { if (t->MemBlock) { - imesa->dirty |= I810_REQUIRE_QUIESCENT; mmFreeMem(t->MemBlock); t->MemBlock = 0; + + if (t->age > imesa->dirtyAge) + imesa->dirtyAge = t->age; } t->dirty_images = ~0; @@ -413,13 +417,28 @@ static void i810UploadTexLevel( i810TextureObjectPtr t, int level ) } break; + case GL_ALPHA: + { + GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset); + GLubyte *src = (GLubyte *)image->Data; + i810Msg(10," CopyA: %p %p\n", dst, src); + + for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) { + for (i = 0 ; i < image->Width ; i++) { + dst[i] = I810PACKCOLOR4444(255,255,255,src[0]); + src += 1; + } + } + } + break; + /* TODO: Translate color indices *now*: */ case GL_COLOR_INDEX: { GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[level].offset); GLubyte *src = (GLubyte *)image->Data; - i810Msg(10," CopyIndex %p %p\n", dst, src); + i810Msg(10," CopyIndex: %p %p\n", dst, src); for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) { for (i = 0 ; i < image->Width ; i++) { @@ -431,8 +450,8 @@ static void i810UploadTexLevel( i810TextureObjectPtr t, int level ) break; default: - i810Error("Not supported texture format %d\n",(int)image->Format); - exit(1); + i810Error("Not supported texture format %s\n", + gl_lookup_enum_by_nr(image->Format)); } } @@ -449,13 +468,19 @@ void i810PrintLocalLRU( i810ContextPtr imesa ) t->MemBlock->ofs / sz, t->MemBlock->ofs, t->MemBlock->size); + else + fprintf(stderr, "Texture (bound %d) at %x sz %x\n", + t->bound, + t->MemBlock->ofs, + t->MemBlock->size); + } } void i810PrintGlobalLRU( i810ContextPtr imesa ) { int i, j; - i810TexRegion *list = imesa->sarea->texList; + drm_i810_tex_region_t *list = imesa->sarea->texList; for (i = 0, j = I810_NR_TEX_REGIONS ; i < I810_NR_TEX_REGIONS ; i++) { fprintf(stderr, "list[%d] age %d next %d prev %d\n", @@ -471,7 +496,7 @@ void i810PrintGlobalLRU( i810ContextPtr imesa ) void i810ResetGlobalLRU( i810ContextPtr imesa ) { - i810TexRegion *list = imesa->sarea->texList; + drm_i810_tex_region_t *list = imesa->sarea->texList; int sz = 1 << imesa->i810Screen->logTextureGranularity; int i; @@ -481,7 +506,7 @@ void i810ResetGlobalLRU( i810ContextPtr imesa ) * when looking up objects at a particular location in texture * memory. */ - for (i = 0 ; (i+1) * sz < imesa->i810Screen->textureSize ; i++) { + for (i = 0 ; (i+1) * sz <= imesa->i810Screen->textureSize ; i++) { list[i].prev = i-1; list[i].next = i+1; list[i].age = 0; @@ -503,7 +528,7 @@ static void i810UpdateTexLRU( i810ContextPtr imesa, i810TextureObjectPtr t ) int logsz = imesa->i810Screen->logTextureGranularity; int start = t->MemBlock->ofs >> logsz; int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz; - i810TexRegion *list = imesa->sarea->texList; + drm_i810_tex_region_t *list = imesa->sarea->texList; imesa->texAge = ++imesa->sarea->texAge; @@ -556,7 +581,7 @@ void i810TexturesGone( i810ContextPtr imesa, /* It overlaps - kick it off. Need to hold onto the currently bound * objects, however. */ - if (t == imesa->CurrentTexObj[0] || t == imesa->CurrentTexObj[1]) + if (t->bound) i810SwapOutTexObj( imesa, t ); else i810DestroyTexObj( imesa, t ); @@ -583,7 +608,6 @@ int i810UploadTexImages( i810ContextPtr imesa, i810TextureObjectPtr t ) { int i; int ofs; - i810glx.c_textureSwaps++; /* Do we need to eject LRU texture objects? */ @@ -594,18 +618,24 @@ int i810UploadTexImages( i810ContextPtr imesa, i810TextureObjectPtr t ) if (t->MemBlock) break; + if (imesa->TexObjList.prev->bound) { + fprintf(stderr, "Hit bound texture in upload\n"); + i810PrintLocalLRU( imesa ); + return -1; + } + if (imesa->TexObjList.prev == &(imesa->TexObjList)) { - fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize); + fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize); mmDumpMemInfo( imesa->texHeap ); return -1; } - + i810DestroyTexObj( imesa, imesa->TexObjList.prev ); } ofs = t->MemBlock->ofs; t->Setup[I810_TEXREG_MI3] = imesa->i810Screen->textureOffset + ofs; - t->BufAddr = i810glx.texVirtual + ofs; + t->BufAddr = imesa->i810Screen->tex.map + ofs; imesa->dirty |= I810_UPLOAD_CTX; } @@ -613,6 +643,14 @@ int i810UploadTexImages( i810ContextPtr imesa, i810TextureObjectPtr t ) */ i810UpdateTexLRU( imesa, t ); + if (I810_DEBUG & DEBUG_VERBOSE_LRU) + fprintf(stderr, "dispatch age: %d age freed memory: %d\n", + GET_DISPATCH_AGE(imesa), imesa->dirtyAge); + + if (imesa->dirtyAge >= GET_DISPATCH_AGE(imesa)) + i810WaitAgeLocked( imesa, imesa->dirtyAge ); + + if (t->dirty_images) { if (I810_DEBUG & DEBUG_VERBOSE_LRU) fprintf(stderr, "*"); @@ -694,21 +732,37 @@ static void i810UpdateTex0State( GLcontext *ctx ) if (t->dirty_images) imesa->dirty |= I810_UPLOAD_TEX0IMAGE; - + imesa->CurrentTexObj[0] = t; + t->bound = 1; + + if (t->MemBlock) + i810UpdateTexLRU( imesa, t ); switch (ctx->Texture.Unit[0].EnvMode) { - case GL_REPLACE: - imesa->Setup[I810_CTXREG_MC0] = ( GFX_OP_MAP_COLOR_STAGES | - MC_STAGE_0 | - MC_UPDATE_DEST | - MC_DEST_CURRENT | - MC_UPDATE_ARG1 | - MC_ARG1_TEX0_COLOR | - MC_UPDATE_ARG2 | - MC_ARG2_ONE | - MC_UPDATE_OP | - MC_OP_ARG1 ); + case GL_REPLACE: + if (t->image[0].internalFormat == GL_ALPHA) + imesa->Setup[I810_CTXREG_MC0] = ( GFX_OP_MAP_COLOR_STAGES | + MC_STAGE_0 | + MC_UPDATE_DEST | + MC_DEST_CURRENT | + MC_UPDATE_ARG1 | + MC_ARG1_TEX0_COLOR | + MC_UPDATE_ARG2 | + MC_ARG2_ITERATED_COLOR | + MC_UPDATE_OP | + MC_OP_ARG2 ); + else + imesa->Setup[I810_CTXREG_MC0] = ( GFX_OP_MAP_COLOR_STAGES | + MC_STAGE_0 | + MC_UPDATE_DEST | + MC_DEST_CURRENT | + MC_UPDATE_ARG1 | + MC_ARG1_TEX0_COLOR | + MC_UPDATE_ARG2 | + MC_ARG2_ONE | + MC_UPDATE_OP | + MC_OP_ARG1 ); if (t->image[0].internalFormat == GL_RGB) { ma_modulate_op = MA_OP_ARG1; @@ -812,16 +866,28 @@ static void i810UpdateTex0State( GLcontext *ctx ) MA_OP_ARG1 ); break; case GL_BLEND: - imesa->Setup[I810_CTXREG_MC0] = ( GFX_OP_MAP_COLOR_STAGES | - MC_STAGE_0 | - MC_UPDATE_DEST | - MC_DEST_CURRENT | - MC_UPDATE_ARG1 | - MC_ARG1_COLOR_FACTOR | - MC_UPDATE_ARG2 | - MC_ARG2_ITERATED_COLOR | - MC_UPDATE_OP | - MC_OP_LIN_BLEND_TEX0_COLOR ); + if (t->image[0].internalFormat == GL_ALPHA) + imesa->Setup[I810_CTXREG_MC0] = ( GFX_OP_MAP_COLOR_STAGES | + MC_STAGE_0 | + MC_UPDATE_DEST | + MC_DEST_CURRENT | + MC_UPDATE_ARG1 | + MC_ARG1_TEX0_COLOR | + MC_UPDATE_ARG2 | + MC_ARG2_ITERATED_COLOR | + MC_UPDATE_OP | + MC_OP_ARG2 ); + else + imesa->Setup[I810_CTXREG_MC0] = ( GFX_OP_MAP_COLOR_STAGES | + MC_STAGE_0 | + MC_UPDATE_DEST | + MC_DEST_CURRENT | + MC_UPDATE_ARG1 | + MC_ARG1_COLOR_FACTOR | + MC_UPDATE_ARG2 | + MC_ARG2_ITERATED_COLOR | + MC_UPDATE_OP | + MC_OP_LIN_BLEND_TEX0_COLOR ); if (t->image[0].internalFormat == GL_RGB) { imesa->Setup[I810_CTXREG_MA0] = ( GFX_OP_MAP_ALPHA_STAGES | @@ -911,7 +977,10 @@ static void i810UpdateTex1State( GLcontext *ctx ) imesa->dirty |= I810_UPLOAD_TEX1IMAGE; imesa->CurrentTexObj[1] = t; + t->bound = 2; + if (t->MemBlock) + i810UpdateTexLRU( imesa, t ); switch (ctx->Texture.Unit[1].EnvMode) { case GL_REPLACE: @@ -1078,11 +1147,15 @@ static void i810UpdateTex1State( GLcontext *ctx ) void i810UpdateTextureState( GLcontext *ctx ) { i810ContextPtr imesa = I810_CONTEXT(ctx); + if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound = 0; + if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->bound = 0; imesa->CurrentTexObj[0] = 0; - imesa->CurrentTexObj[1] = 0; + imesa->CurrentTexObj[1] = 0; i810UpdateTex0State( ctx ); i810UpdateTex1State( ctx ); - I810_CONTEXT( ctx )->dirty |= I810_UPLOAD_CTX; + I810_CONTEXT( ctx )->dirty |= (I810_UPLOAD_CTX | + I810_UPLOAD_TEX0 | + I810_UPLOAD_TEX1); } @@ -1091,25 +1164,30 @@ void i810UpdateTextureState( GLcontext *ctx ) * DRIVER functions *****************************************/ -static void i810TexEnv( GLcontext *ctx, GLenum pname, const GLfloat *param ) +static void i810TexEnv( GLcontext *ctx, GLenum target, + GLenum pname, const GLfloat *param ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); if (pname == GL_TEXTURE_ENV_MODE) { + FLUSH_BATCH(imesa); imesa->new_state |= I810_NEW_TEXTURE; } else if (pname == GL_TEXTURE_ENV_COLOR) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - GLubyte c[4]; + GLfloat *fc = texUnit->EnvColor; GLuint col; - FLOAT_RGBA_TO_UBYTE_RGBA(texUnit->EnvColor, c); - col = (c[3]<<24) | (c[0]<<16) | (c[1]<<8) | (c[2]); + col = ((((GLubyte)fc[3])<<24) | + (((GLubyte)fc[0])<<16) | + (((GLubyte)fc[1])<<8) | + (((GLubyte)fc[2])<<0)); if (imesa->Setup[I810_CTXREG_CF1] != col) { + FLUSH_BATCH(imesa); imesa->Setup[I810_CTXREG_CF1] = col; imesa->dirty |= I810_UPLOAD_CTX; } @@ -1137,6 +1215,7 @@ static void i810TexImage( GLcontext *ctx, t = (i810TextureObjectPtr) tObj->DriverData; if (t) { + if (t->bound) FLUSH_BATCH(imesa); /* if this is the current object, it will force an update */ i810DestroyTexObj( imesa, t ); tObj->DriverData = 0; @@ -1163,10 +1242,10 @@ static void i810TexSubImage( GLcontext *ctx, GLenum target, t = (i810TextureObjectPtr) tObj->DriverData; if (t) { + if (t->bound) FLUSH_BATCH( imesa ); i810DestroyTexObj( imesa, t ); tObj->DriverData = 0; imesa->new_state |= I810_NEW_TEXTURE; - i810glx.c_textureSwaps++; } } @@ -1183,15 +1262,18 @@ static void i810TexParameter( GLcontext *ctx, GLenum target, switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: + if (t->bound) FLUSH_BATCH( imesa ); i810SetTexFilter(t,tObj->MinFilter,tObj->MagFilter); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: + if (t->bound) FLUSH_BATCH( imesa ); i810SetTexWrapping(t,tObj->WrapS,tObj->WrapT); break; case GL_TEXTURE_BORDER_COLOR: + if (t->bound) FLUSH_BATCH( imesa ); i810SetTexBorderColor(t,tObj->BorderColor); break; @@ -1206,7 +1288,14 @@ static void i810BindTexture( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); - imesa->CurrentTexObj[ctx->Texture.CurrentUnit] = 0; + + FLUSH_BATCH(imesa); + + if (imesa->CurrentTexObj[ctx->Texture.CurrentUnit]) { + imesa->CurrentTexObj[ctx->Texture.CurrentUnit]->bound = 0; + imesa->CurrentTexObj[ctx->Texture.CurrentUnit] = 0; + } + imesa->new_state |= I810_NEW_TEXTURE; } @@ -1216,6 +1305,13 @@ static void i810DeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) i810ContextPtr imesa = I810_CONTEXT( ctx ); if (t) { + + if (t->bound) { + FLUSH_BATCH(imesa); + imesa->CurrentTexObj[t->bound-1] = 0; + imesa->new_state |= I810_NEW_TEXTURE; + } + i810DestroyTexObj(imesa,t); tObj->DriverData=0; } diff --git a/xc/lib/GL/mesa/src/drv/i810/i810tex.h b/xc/lib/GL/mesa/src/drv/i810/i810tex.h index d2b153ad8..a16733ec1 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810tex.h +++ b/xc/lib/GL/mesa/src/drv/i810/i810tex.h @@ -61,10 +61,11 @@ struct i810_texture_object_t { int Height; int texelBytes; int totalSize; + int bound; PMemBlock MemBlock; char *BufAddr; - + GLuint min_level; GLuint max_level; GLuint dirty_images; @@ -87,8 +88,6 @@ struct i810_texture_object_t { #define I810_UPDATE_PALETTE 0x2 #define I810_FALLBACK_PALETTE 0x4 -typedef struct i810_texture_object_t *i810TextureObjectPtr; - void i810UpdateTextureState( GLcontext *ctx ); void i810DDInitTextureFuncs( GLcontext *ctx ); diff --git a/xc/lib/GL/mesa/src/drv/i810/i810tris.c b/xc/lib/GL/mesa/src/drv/i810/i810tris.c index 7e24da002..c601ca492 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810tris.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810tris.c @@ -31,7 +31,6 @@ #include "pipeline.h" #include "mm.h" -#include "i810lib.h" #include "i810tris.h" #include "i810vb.h" #include "i810log.h" diff --git a/xc/lib/GL/mesa/src/drv/i810/i810tris.h b/xc/lib/GL/mesa/src/drv/i810/i810tris.h index 81cdb5159..3b3843683 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810tris.h +++ b/xc/lib/GL/mesa/src/drv/i810/i810tris.h @@ -27,37 +27,48 @@ #define I810TRIS_INC #include "types.h" -#include "i810dma.h" +#include "i810ioctl.h" extern void i810PrintRenderState( const char *msg, GLuint state ); extern void i810DDChooseRenderState(GLcontext *ctx); extern void i810DDTrifuncInit( void ); -extern GLuint *i810AllocPrimitiveVerts( i810ContextPtr imesa, int dwords ); - - -/* Todo: - * - multidraw, ... - * - Antialiasing (?) - * - line and polygon stipple - * - select and feedback - * - stencil - * - point parameters - * - - */ -#define I810_ANTIALIAS_BIT 0 /* ignored for now, no fallback */ +/* shared */ #define I810_FLAT_BIT 0x1 + +/* triangle */ #define I810_OFFSET_BIT 0x2 #define I810_TWOSIDE_BIT 0x4 -#define I810_NODRAW_BIT 0x8 -#define I810_FALLBACK_BIT 0x10 -/* Not in use: - */ -#define I810_FEEDBACK_BIT 0x20 -#define I810_SELECT_BIT 0x40 -#define I810_POINT_PARAM_BIT 0x80 /* not needed? */ +/* line */ +#define I810_WIDE_LINE_BIT 0x2 +#define I810_STIPPLE_LINE_BIT 0x4 + +/* shared */ +#define I810_FALLBACK_BIT 0x8 + + + + + +static i810_vertex __inline__ *i810AllocTriangles( i810ContextPtr imesa, int nr) +{ + GLuint *start = i810AllocDwords( imesa, 30*nr, PR_TRIANGLES ); + return (i810_vertex *)start; +} + +static i810_vertex __inline__ *i810AllocLine( i810ContextPtr imesa ) +{ + GLuint *start = i810AllocDwords( imesa, 20, PR_LINES ); + return (i810_vertex *)start; +} + +static i810_vertex __inline__ *i810AllocRect( i810ContextPtr imesa ) +{ + GLuint *start = i810AllocDwords( imesa, 30, PR_RECTS ); + return (i810_vertex *)start; +} @@ -66,23 +77,17 @@ static void __inline__ i810_draw_triangle( i810ContextPtr imesa, i810_vertex *v1, i810_vertex *v2 ) { - i810_vertex *wv = (i810_vertex *)i810AllocPrimitiveVerts( imesa, 30 ); + i810_vertex *wv = i810AllocTriangles( imesa, 1 ); wv[0] = *v0; wv[1] = *v1; wv[2] = *v2; - FINISH_PRIM(); } - - -/* These can go soon, but for the meantime we're using triangles for - * everything. - */ static __inline__ void i810_draw_point( i810ContextPtr imesa, i810_vertex *tmp, float sz ) { - i810_vertex *wv = (i810_vertex *)i810AllocPrimitiveVerts( imesa, 6*10 ); + i810_vertex *wv = i810AllocTriangles( imesa, 2 ); wv[0] = *tmp; wv[0].x = tmp->x - sz; @@ -108,16 +113,25 @@ static __inline__ void i810_draw_point( i810ContextPtr imesa, wv[5].x = tmp->x - sz; wv[5].y = tmp->y - sz; - FINISH_PRIM(); } -static __inline__ void i810_draw_line( i810ContextPtr imesa, - i810_vertex *tmp0, - i810_vertex *tmp1, - float width ) +static __inline__ void i810_draw_line_line( i810ContextPtr imesa, + i810_vertex *tmp0, + i810_vertex *tmp1 ) { - i810_vertex *wv = (i810_vertex *)i810AllocPrimitiveVerts( imesa, 6 * 10 ); + i810_vertex *wv = i810AllocLine( imesa ); + wv[0] = *tmp0; + wv[1] = *tmp1; +} + +static __inline__ void i810_draw_tri_line( i810ContextPtr imesa, + i810_vertex *tmp0, + i810_vertex *tmp1, + float width ) +{ + i810_vertex *wv = i810AllocTriangles( imesa, 2 ); + float dx, dy, ix, iy; dx = tmp0->x - tmp1->x; @@ -151,8 +165,15 @@ static __inline__ void i810_draw_line( i810ContextPtr imesa, wv[5] = *tmp1; wv[5].x = tmp1->x + ix; wv[5].y = tmp1->y + iy; +} - FINISH_PRIM(); + +static __inline__ void i810_draw_line( i810ContextPtr imesa, + i810_vertex *tmp0, + i810_vertex *tmp1, + float width ) +{ + i810_draw_line_line( imesa, tmp0, tmp1 ); } #endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810tritmp.h b/xc/lib/GL/mesa/src/drv/i810/i810tritmp.h index 97c101c17..9d6b43d93 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810tritmp.h +++ b/xc/lib/GL/mesa/src/drv/i810/i810tritmp.h @@ -63,44 +63,37 @@ static __inline__ void TAG(triangle)( GLcontext *ctx, GLuint e0, } #endif - i810glx.c_triangles++; - - BEGIN_CLIP_LOOP(imesa) - { - i810_vertex *wv = (i810_vertex *)i810AllocPrimitiveVerts( imesa, 30 ); - wv[0] = *v0; + { + i810_vertex *wv = i810AllocTriangles( imesa, 1 ); + wv[0] = *v0; #if (IND & (I810_FLAT_BIT|I810_TWOSIDE_BIT)) - *((int *)(&wv[0].color)) = c0; + *((int *)(&wv[0].color)) = c0; #endif #if (IND & I810_OFFSET_BIT) - wv[0].z = v0->z + offset; + wv[0].z = v0->z + offset; #endif - wv[1] = *v1; + wv[1] = *v1; #if (IND & (I810_FLAT_BIT|I810_TWOSIDE_BIT)) - *((int *)(&wv[1].color)) = c1; + *((int *)(&wv[1].color)) = c1; #endif #if (IND & I810_OFFSET_BIT) - wv[1].z = v1->z + offset; + wv[1].z = v1->z + offset; #endif - wv[2] = *v2; + wv[2] = *v2; #if (IND & (I810_FLAT_BIT|I810_TWOSIDE_BIT)) - *((int *)(&wv[2].color)) = c2; + *((int *)(&wv[2].color)) = c2; #endif #if (IND & I810_OFFSET_BIT) - wv[2].z = v2->z + offset; + wv[2].z = v2->z + offset; #endif - - FINISH_PRIM(); - } - END_CLIP_LOOP(imesa); + } } - static void TAG(quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3, GLuint pv ) @@ -109,25 +102,35 @@ static void TAG(quad)( GLcontext *ctx, GLuint v0, TAG(triangle)( ctx, v1, v2, v3, pv ); } - -#if ((IND & ~I810_FLAT_BIT) == 0) - static void TAG(line)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint pv ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); i810VertexPtr i810VB = I810_DRIVER_DATA(ctx->VB)->verts; - i810_vertex tmp0 = i810VB[v0].v; - i810_vertex tmp1 = i810VB[v1].v; - float width = ctx->Line.Width; + int tmp0, tmp1; + (void) tmp0; (void) tmp1; + if (IND & I810_FLAT_BIT) { - *(int *)&tmp1.color = *(int *)&tmp0.color = - *(int *)&i810VB[pv].v.color; - } + tmp0 = *(int *)&i810VB[v0].v.color; + tmp1 = *(int *)&i810VB[v1].v.color; + i810VB[v0].v.color = i810VB[pv].v.color; + i810VB[v1].v.color = i810VB[pv].v.color; + } - BEGIN_CLIP_LOOP(imesa) - i810_draw_line( imesa, &tmp0, &tmp1, width ); - END_CLIP_LOOP(imesa); + if (IND & I810_WIDE_LINE_BIT) + { + i810_draw_tri_line( imesa, &i810VB[v0].v, &i810VB[v1].v, + ctx->Line.Width ); + } + else + { + i810_draw_line_line( imesa, &i810VB[v0].v, &i810VB[v1].v ); + } + + if (IND & I810_FLAT_BIT) { + *(int *)&i810VB[v0].v.color = tmp0; + *(int *)&i810VB[v1].v.color = tmp1; + } } @@ -143,28 +146,22 @@ static void TAG(points)( GLcontext *ctx, GLuint first, GLuint last ) * ctx->Driver.ReducedPrimitiveChange() callback. */ - BEGIN_CLIP_LOOP(imesa) - for(i=first;i<=last;i++) { - if(VB->ClipMask[i]==0) { - i810_vertex *tmp = &i810VB[i].v; - i810_draw_point( imesa, tmp, sz ); - } + for(i=first;i<=last;i++) { + if(VB->ClipMask[i]==0) { + i810_vertex *tmp = &i810VB[i].v; + i810_draw_point( imesa, tmp, sz ); } - END_CLIP_LOOP(imesa); + } } -#endif static void TAG(init)( void ) { tri_tab[IND] = TAG(triangle); quad_tab[IND] = TAG(quad); - -#if ((IND & ~I810_FLAT_BIT) == 0) line_tab[IND] = TAG(line); points_tab[IND] = TAG(points); -#endif } diff --git a/xc/lib/GL/mesa/src/drv/i810/i810vb.c b/xc/lib/GL/mesa/src/drv/i810/i810vb.c index 6ba7eb9a5..6f8d163c4 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810vb.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810vb.c @@ -23,11 +23,9 @@ * */ -#include "i810lib.h" #include "i810context.h" #include "i810vb.h" #include "i810log.h" -#include "i810dma.h" #include "stages.h" diff --git a/xc/lib/GL/mesa/src/drv/mga/Imakefile b/xc/lib/GL/mesa/src/drv/mga/Imakefile index e4e39b747..cbcd09821 100644 --- a/xc/lib/GL/mesa/src/drv/mga/Imakefile +++ b/xc/lib/GL/mesa/src/drv/mga/Imakefile @@ -1,4 +1,6 @@ +#include <Threads.tmpl> + #define DoNormalLib NormalLibGlx #define DoSharedLib SharedLibGlx #define DoExtraLib SharedLibGlx @@ -9,38 +11,285 @@ ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL #endif +#if defined(LinuxArchitecture) +OS_SUBDIR = linux +#endif +#if defined(FreeBSDArchitecture) +OS_SUBDIR = bsd +#endif + +#ifdef i386Architecture +#ifdef MesaUse3DNow + ASM_DEFS = -DUSE_MMX_ASM -DUSE_X86_ASM -DUSE_3DNOW_ASM +#else + ASM_DEFS = -DUSE_MMX_ASM -DUSE_X86_ASM +#endif +#endif + + #if BuildXF86DRI DRI_DEFINES = GlxDefines -DDRIVERTS DRI_INCLUDES = -I../../../../dri -I../../../../glx \ + -I../../../dri \ -I$(TOP)/include -I$(TOP)/include/GL \ -I$(XF86OSSRC) -I$(SERVERSRC)/GL/dri \ -I$(XF86DRIVERSRC)/mga \ -I../../../include -I../.. -I../../X -I../common \ - -I$(XF86OSSRC)/linux/drm/kernel + -I$(XF86OSSRC)/$(OS_SUBDIR)/drm/kernel #endif MESA_INCLUDES = -I. -I.. -I../../include - DEFINES = $(ALLOC_DEFINES) $(DRI_DEFINES) - INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) \ - -I/usr/include/glide - DRISRCS = mgaclear.c mgacnvtex.c mgadd.c mgadepth.c \ - mgafastpath.c \ + DEFINES = $(ALLOC_DEFINES) $(DRI_DEFINES) $(ASM_DEFS) + INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) + +#if 0 + LOSRC = ../../../../lowpc.c + LOOBJ = ../../../../lowpc.o + + HISRC = ../../../../highpc.c + HIOBJ = ../../../../highpc.o +#endif + + DRISRCS = ../../../dri/dri_mesa.c \ + ../../../../dri/dri_tmm.c + + DRIOBJS = ../../../dri/dri_mesa.o \ + ../../../../dri/dri_tmm.o + + DRMSRCS = ../../../../dri/drm/xf86drm.c \ + ../../../../dri/drm/xf86drmHash.c \ + ../../../../dri/drm/xf86drmRandom.c \ + ../../../../dri/drm/xf86drmSL.c + + DRMOBJS = ../../../../dri/drm/xf86drm.o \ + ../../../../dri/drm/xf86drmHash.o \ + ../../../../dri/drm/xf86drmRandom.o \ + ../../../../dri/drm/xf86drmSL.o + + + MGASRCS = mgaclear.c mgacnvtex.c mgadd.c \ + mgafastpath.c mgaeltpath.c \ mgapipeline.c \ mgaspan.c mgastate.c mgatex.c \ - mgatris.c mgavb.c mgaioctl.c mga_xmesa.c + mgatris.c mgavb.c mgaioctl.c mga_xmesa.c mgabuffers.c - DRIOBJS = mgaclear.o mgacnvtex.o mgadd.o mgadepth.o \ - mgafastpath.o \ + MGAOBJS = mgaclear.o mgacnvtex.o mgadd.o \ + mgafastpath.o mgaeltpath.o \ mgapipeline.o \ mgaspan.o mgastate.o mgatex.o \ - mgatris.o mgavb.o mgaioctl.o mga_xmesa.o + mgatris.o mgavb.o mgaioctl.o mga_xmesa.o mgabuffers.o + + MESASRCS = ../../aatriangle.c \ + ../../accum.c \ + ../../alpha.c \ + ../../alphabuf.c \ + ../../attrib.c \ + ../../bbox.c \ + ../../bitmap.c \ + ../../blend.c \ + ../../buffers.c \ + ../../clip.c \ + ../../colortab.c \ + ../../config.c \ + ../../context.c \ + ../../copypix.c \ + ../../cva.c \ + ../../debug_xform.c \ + ../../depth.c \ + ../../dlist.c \ + ../../drawpix.c \ + ../../enable.c \ + ../../enums.c \ + ../../eval.c \ + ../../extensions.c \ + ../../feedback.c \ + ../../fog.c \ + ../../get.c \ + ../../glapi.c \ + ../../glapinoop.c \ + ../../glthread.c \ + ../../hash.c \ + ../../image.c \ + ../../imaging.c \ + ../../light.c \ + ../../lines.c \ + ../../logic.c \ + ../../masking.c \ + ../../matrix.c \ + ../../mem.c \ + ../../mmath.c \ + ../../pb.c \ + ../../pipeline.c \ + ../../pixel.c \ + ../../pixeltex.c \ + ../../points.c \ + ../../polygon.c \ + ../../quads.c \ + ../../rastpos.c \ + ../../readpix.c \ + ../../rect.c \ + ../../scissor.c \ + ../../shade.c \ + ../../span.c \ + ../../stages.c \ + ../../state.c \ + ../../stencil.c \ + ../../teximage.c \ + ../../texobj.c \ + ../../texstate.c \ + ../../texture.c \ + ../../texutil.c \ + ../../translate.c \ + ../../triangle.c \ + ../../varray.c \ + ../../vb.c \ + ../../vbcull.c \ + ../../vbfill.c \ + ../../vbindirect.c \ + ../../vbrender.c \ + ../../vbxform.c \ + ../../vector.c \ + ../../vertices.c \ + ../../winpos.c \ + ../../xform.c \ + ../../zoom.c \ + ../../X86/common_x86.c + + MESAOBJS = ../../aatriangle.o \ + ../../accum.o \ + ../../alpha.o \ + ../../alphabuf.o \ + ../../attrib.o \ + ../../bbox.o \ + ../../bitmap.o \ + ../../blend.o \ + ../../buffers.o \ + ../../clip.o \ + ../../colortab.o \ + ../../config.o \ + ../../context.o \ + ../../copypix.o \ + ../../cva.o \ + ../../debug_xform.o \ + ../../depth.o \ + ../../dlist.o \ + ../../drawpix.o \ + ../../enable.o \ + ../../enums.o \ + ../../eval.o \ + ../../extensions.o \ + ../../feedback.o \ + ../../fog.o \ + ../../get.o \ + ../../hash.o \ + ../../hint.o \ + ../../image.o \ + ../../imaging.o \ + ../../light.o \ + ../../lines.o \ + ../../logic.o \ + ../../masking.o \ + ../../matrix.o \ + ../../mem.o \ + ../../mmath.o \ + ../../pb.o \ + ../../pipeline.o \ + ../../pixel.o \ + ../../pixeltex.o \ + ../../points.o \ + ../../polygon.o \ + ../../quads.o \ + ../../rastpos.o \ + ../../readpix.o \ + ../../rect.o \ + ../../scissor.o \ + ../../shade.o \ + ../../span.o \ + ../../stages.o \ + ../../state.o \ + ../../stencil.o \ + ../../teximage.o \ + ../../texobj.o \ + ../../texstate.o \ + ../../texture.o \ + ../../texutil.o \ + ../../translate.o \ + ../../triangle.o \ + ../../varray.o \ + ../../vb.o \ + ../../vbcull.o \ + ../../vbfill.o \ + ../../vbindirect.o \ + ../../vbrender.o \ + ../../vbxform.o \ + ../../vector.o \ + ../../vertices.o \ + ../../winpos.o \ + ../../xform.o \ + ../../zoom.o + +#ifdef i386Architecture + X86_SRCS = ../../X86/x86.c \ + ../../X86/x86a.S \ + ../../X86/common_x86.c \ + ../../X86/common_x86asm.S \ + ../../X86/vertex.S + + X86_OBJS = ../../X86/x86.o \ + ../../X86/x86a.o \ + ../../X86/common_x86.o \ + ../../X86/common_x86asm.o \ + ../../X86/vertex.o + + MMX_SRCS = ../../X86/mmx_blend.S + + MMX_OBJS = ../../X86/mmx_blend.o + +#ifdef MesaUse3DNow + 3DNOW_SRCS = ../../X86/3dnow.c \ + ../../X86/3dnow_norm_raw.S \ + ../../X86/3dnow_xform_masked1.S \ + ../../X86/3dnow_xform_masked2.S \ + ../../X86/3dnow_xform_masked3.S \ + ../../X86/3dnow_xform_masked4.S \ + ../../X86/3dnow_xform_raw1.S \ + ../../X86/3dnow_xform_raw2.S \ + ../../X86/3dnow_xform_raw3.S \ + ../../X86/3dnow_xform_raw4.S \ + ../../X86/vertex_3dnow.S + 3DNOW_OBJS = ../../X86/3dnow.o \ + ../../X86/3dnow_norm_raw.o \ + ../../X86/3dnow_xform_masked1.o \ + ../../X86/3dnow_xform_masked2.o \ + ../../X86/3dnow_xform_masked3.o \ + ../../X86/3dnow_xform_masked4.o \ + ../../X86/3dnow_xform_raw1.o \ + ../../X86/3dnow_xform_raw2.o \ + ../../X86/3dnow_xform_raw3.o \ + ../../X86/3dnow_xform_raw4.o \ + ../../X86/vertex_3dnow.o + +#endif +#endif + + ASMSRCS = $(X86_SRCS) $(MMX_SRCS) $(3DNOW_SRCS) + ASMOBJS = $(X86_OBJS) $(MMX_OBJS) $(3DNOW_OBJS) + + COMMONSRCS = ../common/mm.c ../common/hwlog.c + COMMONOBJS = ../common/mm.o ../common/hwlog.o + + SRCS = $(LOWSRC) $(DRISRCS) $(DRMSRCS) $(MESASRCS) $(ASMSRCS) $(COMMONSRCS) $(MGASRCS) $(HISRC) + OBJS = $(LOWOBJ) $(DRIOBJS) $(DRMOBJS) $(MESAOBJS) $(ASMOBJS) $(COMMONOBJS) $(MGAOBJS) $(HIOBJ) + +REQUIREDLIBS += -lm +#if !GlxBuiltInMga +REQUIREDLIBS += -L../../../.. -lGL +#endif - SRCS = $(DRISRCS) - OBJS = $(DRIOBJS) #if !GlxUseBuiltInDRIDriver #undef DoNormalLib NormalLibGlx @@ -61,7 +310,7 @@ LIBNAME = mga_dri.so ALL_OBJS = $(OBJS) ALL_DEPS = DONE SharedDepModuleTarget($(LIBNAME),$(ALL_DEPS),$(ALL_OBJS)) -InstallDynamicModule($(LIBNAME),$(MODULEDIR),.) +InstallDynamicModule($(LIBNAME),$(MODULEDIR)/dri,.) #endif DependTarget() diff --git a/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c b/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c index b7fc70b79..a0d9cdf73 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c +++ b/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c @@ -78,6 +78,21 @@ static mgaContextPtr mgaCtx = 0; mgaGlx_t mgaglx; +/* These functions are accessed externally to the driver: + * + * XMesaInitDriver + * XMesaResetDriver + * XMesaCreateVisual + * XMesaDestroyVisual + * XMesaCreateContext + * XMesaDestroyContext + * XMesaCreateWindowBuffer + * XMesaCreatePixmapBuffer + * XMesaDestroyBuffer + * XMesaSwapBuffers + * XMesaMakeCurrent + * + */ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) { @@ -150,23 +165,21 @@ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) mgaScreen->depthPitch = serverInfo->depthPitch; - mgaScreen->agp_tex.handle = serverInfo->agp; - mgaScreen->agp_tex.size = serverInfo->agpSize; + mgaScreen->agp.handle = serverInfo->agp; + mgaScreen->agp.size = serverInfo->agpSize; if (drmMap(sPriv->fd, - mgaScreen->agp_tex.handle, - mgaScreen->agp_tex.size, - (drmAddress *)&mgaScreen->agp_tex.map) != 0) + mgaScreen->agp.handle, + mgaScreen->agp.size, + (drmAddress *)&mgaScreen->agp.map) != 0) { Xfree(mgaScreen); sPriv->private = NULL; return GL_FALSE; } - - mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset; - mgaScreen->textureOffset[MGA_AGP_HEAP] = (mgaScreen->agp_tex.handle | + mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset | PDEA_pagpxfer_enable | 1); /* @@ -184,12 +197,17 @@ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) serverInfo->logAgpTextureGranularity; mgaScreen->texVirtual[MGA_CARD_HEAP] = (mgaScreen->sPriv->pFB + - mgaScreen->textureOffset[0]); - mgaScreen->texVirtual[MGA_AGP_HEAP] = mgaScreen->agp_tex.map; + serverInfo->textureOffset); + mgaScreen->texVirtual[MGA_AGP_HEAP] = (mgaScreen->agp.map + + serverInfo->agpTextureOffset); mgaScreen->mAccess = serverInfo->mAccess; + /* For calculating setupdma addresses. + */ + mgaScreen->dmaOffset = serverInfo->agpBufferOffset; + /* fprintf(stderr, "\n\n\nbackOffset: %x pitch %x\n", mgaScreen->backOffset, @@ -199,7 +217,7 @@ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) mgaScreen->Attrib = MGA_PF_565; mgaScreen->bufs = drmMapBufs(sPriv->fd); if (!mgaScreen->bufs) { - drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size); + /*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/ XFree(mgaScreen); sPriv->private = NULL; return GL_FALSE; @@ -210,6 +228,7 @@ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) memset(&mgaglx, 0, sizeof(mgaglx)); mgaDDFastPathInit(); + mgaDDEltPathInit(); mgaDDTrifuncInit(); mgaDDSetupInit(); @@ -222,7 +241,7 @@ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) void XMesaResetDriver(__DRIscreenPrivate *sPriv) { mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private; - drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size); + /*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/ Xfree(mgaScreen); sPriv->private = NULL; } @@ -481,4 +500,5 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags ) } + #endif diff --git a/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.h b/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.h index d563bd429..489b71836 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.h +++ b/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.h @@ -28,7 +28,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* * Authors: * Keith Whitwell <keithw@precisioninsight.com> - * Daryll Strauss <daryll@precisioninsight.com> (Origninal tdfx driver). * */ @@ -42,7 +41,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dri_mesaint.h" #include "dri_mesa.h" #include "types.h" -#include "xmesaP.h" +#include "mgaregs.h" + +typedef struct { + drmHandle handle; + drmSize size; + char *map; +} mgaRegion, *mgaRegionPtr; typedef struct { @@ -54,53 +59,69 @@ typedef struct { int cpp; /* for front and back buffers */ int Attrib; + unsigned int mAccess; - int frontOffset; - int frontPitch; - int backOffset; - int backPitch; + unsigned int frontOffset; + unsigned int frontPitch; + unsigned int backOffset; + unsigned int backPitch; - int depthOffset; - int depthPitch; + unsigned int depthOffset; + unsigned int depthPitch; int depthCpp; - int textureOffset; - int textureSize; - int logTextureGranularity; + unsigned int dmaOffset; + + unsigned int textureOffset[MGA_NR_TEX_HEAPS]; + unsigned int textureSize[MGA_NR_TEX_HEAPS]; + int logTextureGranularity[MGA_NR_TEX_HEAPS]; + char *texVirtual[MGA_NR_TEX_HEAPS]; + __DRIscreenPrivate *sPriv; drmBufMapPtr bufs; + /* Maps the dma buffers as well as textures ? + */ + mgaRegion agp; + } mgaScreenPrivate; #include "mgalib.h" -extern void mgaXMesaUpdateState( mgaContextPtr mmesa ); +extern void mgaGetLock( mgaContextPtr mmesa, GLuint flags ); extern void mgaEmitHwStateLocked( mgaContextPtr mmesa ); extern void mgaEmitScissorValues( mgaContextPtr mmesa, int box_nr, int emit ); -extern void mgaXMesaSetBackClipRects( mgaContextPtr mmesa ); -extern void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa ); + +#define GET_DISPATCH_AGE( mmesa ) mmesa->sarea->last_dispatch +#define GET_ENQUEUE_AGE( mmesa ) mmesa->sarea->last_enqueue /* Lock the hardware and validate our state. */ -#define LOCK_HARDWARE( mmesa ) \ - do { \ - char __ret=0; \ - DRM_CAS(mmesa->driHwLock, mmesa->hHWContext, \ - (DRM_LOCK_HELD|mmesa->hHWContext), __ret); \ - if (__ret) { \ - drmGetLock(mmesa->driFd, mmesa->hHWContext, 0); \ - mgaXMesaUpdateState( mmesa ); \ - } \ +#define LOCK_HARDWARE( mmesa ) \ + do { \ + char __ret=0; \ + DRM_CAS(mmesa->driHwLock, mmesa->hHWContext, \ + (DRM_LOCK_HELD|mmesa->hHWContext), __ret); \ + if (__ret) \ + mgaGetLock( mmesa, 0 ); \ } while (0) +/* + */ +#define LOCK_HARDWARE_QUIESCENT( mmesa ) do { \ + LOCK_HARDWARE( mmesa ); \ + mgaUpdateLock( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH ); \ +} while (0) + + /* Unlock the hardware using the global current context */ -#define UNLOCK_HARDWARE(mmesa) \ +#define UNLOCK_HARDWARE(mmesa) \ DRM_UNLOCK(mmesa->driFd, mmesa->driHwLock, mmesa->hHWContext); @@ -109,6 +130,8 @@ extern void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa ); #define REFRESH_DRAWABLE_INFO( mmesa ) \ do { \ LOCK_HARDWARE( mmesa ); \ + mmesa->lastX = mmesa->drawX; \ + mmesa->lastY = mmesa->drawY; \ UNLOCK_HARDWARE( mmesa ); \ } while (0) diff --git a/xc/lib/GL/mesa/src/drv/mga/mgaeltpath.c b/xc/lib/GL/mesa/src/drv/mga/mgaeltpath.c new file mode 100644 index 000000000..4751eb091 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/mga/mgaeltpath.c @@ -0,0 +1,457 @@ +/* + * GLX Hardware Device Driver for Matrox G400 + * Copyright (C) 1999 Keith Whitwell + * + * 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 + * KEITH WHITWELL, 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. + * + */ + +#include <stdio.h> + +#include "types.h" +#include "enums.h" +#include "cva.h" +#include "vertices.h" +#include "mmath.h" +#include "xform.h" + +#include "mgalib.h" +#include "mgapipeline.h" +#include "mgatris.h" +#include "mgastate.h" +#include "mgavb.h" + + +/* Always use a full-sized stride for vertices. [FIXME] + * Stride in the buffers must be a quadword multiple. + */ +#define BUFFER_STRIDE 12 +#define CLIP_STRIDE 10 + + +static void fire_elts( mgaContextPtr mmesa ) +{ + LOCK_HARDWARE( mmesa ); + + /* Fire queued elements and discard that buffer if its contents + * won't be referenced by future elements. + */ + if (mmesa->elt_buf) { + GLuint retain = (mmesa->elt_buf == mmesa->retained_buf); + + if (mmesa->first_elt != mmesa->next_elt) { + mgaFireEltsLocked( mmesa, + ((GLuint)mmesa->first_elt - + (GLuint)mmesa->elt_buf->address), + ((GLuint)mmesa->next_elt - + (GLuint)mmesa->elt_buf->address), + !retain ); + } else if (!retain) + mgaReleaseBufLocked( mmesa, mmesa->elt_buf ); + + mmesa->elt_buf = 0; + } + else if (mmesa->vertex_dma_buffer) + { + mgaFlushVerticesLocked( mmesa ); + } + + mgaGetEltBufLocked( mmesa ); + + UNLOCK_HARDWARE( mmesa ); + + mmesa->next_vert = (GLfloat *)((GLuint)mmesa->elt_buf->address + + mmesa->elt_buf->total - + BUFFER_STRIDE * sizeof(GLfloat)); + + mmesa->next_vert_phys = (mmesa->mgaScreen->dmaOffset + + mmesa->elt_buf->idx * MGA_DMA_BUF_SZ + + mmesa->elt_buf->total - + BUFFER_STRIDE * sizeof(GLfloat)); + + mmesa->first_elt = (GLuint *)mmesa->elt_buf->address; + mmesa->next_elt = (GLuint *)mmesa->elt_buf->address; + +} + + +static void release_bufs( mgaContextPtr mmesa ) +{ + if (mmesa->retained_buf && mmesa->retained_buf != mmesa->elt_buf) + { + LOCK_HARDWARE( mmesa ); + if (mmesa->first_elt != mmesa->next_elt) { + mgaFireEltsLocked( mmesa, + ((GLuint)mmesa->first_elt - + (GLuint)mmesa->elt_buf->address), + ((GLuint)mmesa->next_elt - + (GLuint)mmesa->elt_buf->address), + 0 ); + + mmesa->first_elt = mmesa->next_elt; + } + + mgaReleaseBufLocked( mmesa, mmesa->retained_buf ); + UNLOCK_HARDWARE( mmesa ); + } + + mmesa->retained_buf = 0; +} + + + + +#define NEGATIVE(f) (f < 0) +#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) +#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) ) + + +#define INTERP_RGBA(t, out, a, b) { \ + int i; \ + for (i = 0; i < 4; i++) { \ + GLfloat fa = UBYTE_COLOR_TO_FLOAT_COLOR(a[i]); \ + GLfloat fb = UBYTE_COLOR_TO_FLOAT_COLOR(b[i]); \ + GLfloat fo = LINTERP(t, fa, fb); \ + FLOAT_COLOR_TO_UBYTE_COLOR(out[i], fo); \ + } \ +} + + +#define CLIP(SGN,V,PLANE) \ +if (mask & PLANE) { \ + GLuint *indata = inlist[in]; \ + GLuint *outdata = inlist[in ^= 1]; \ + GLuint nr = n; \ + GLfloat *J = verts[indata[nr-1]]; \ + GLfloat dpJ = (SGN J[V]) + J[3]; \ + \ + for (i = n = 0 ; i < nr ; i++) { \ + GLuint elt_i = indata[i]; \ + GLfloat *I = verts[elt_i]; \ + GLfloat dpI = (SGN I[V]) + I[3]; \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLfloat *O = verts[next_vert]; \ + outdata[n++] = next_vert++; \ + \ + if (NEGATIVE(dpI)) { \ + GLfloat t = dpI / (dpI - dpJ); \ + interp(t, O, I, J); \ + } \ + else \ + { \ + GLfloat t = dpJ / (dpJ - dpI); \ + interp(t, O, J, I); \ + } \ + } \ + \ + if (!NEGATIVE(dpI)) \ + outdata[n++] = elt_i; \ + \ + J = I; \ + dpJ = dpI; \ + } \ + \ + if (n < 3) return; \ +} + + +static void mga_tri_clip( mgaContextPtr mmesa, + struct vertex_buffer *VB, + GLuint *elt, + GLubyte mask ) +{ + struct mga_elt_tab *tab = mmesa->elt_tab; + mga_interp_func interp = tab->interp; + GLuint inlist[2][VB_MAX_CLIPPED_VERTS]; + GLuint in = 0; + GLuint n = 3, next_vert = 3; + GLuint i; + GLfloat verts[VB_MAX_CLIPPED_VERTS][CLIP_STRIDE]; + + /* Build temporary vertices in clipspace. This is the potential + * downside to this path. + */ + tab->build_tri_verts( mmesa, VB, (GLfloat *)verts, elt ); + + inlist[0][0] = 0; + inlist[0][1] = 1; + inlist[0][2] = 2; + + CLIP(-,0,CLIP_RIGHT_BIT); + CLIP(+,0,CLIP_LEFT_BIT); + CLIP(-,1,CLIP_TOP_BIT); + CLIP(+,1,CLIP_BOTTOM_BIT); + CLIP(-,2,CLIP_FAR_BIT); + CLIP(+,2,CLIP_NEAR_BIT); + + + { + GLuint *out = inlist[in]; + GLuint space = (GLuint)mmesa->next_vert - (GLuint)mmesa->next_elt; + + if (space < n * (BUFFER_STRIDE + 3) * sizeof(GLuint)) + fire_elts(mmesa); + + /* Project the new vertices and emit to dma buffers. Translate + * out values to physical addresses for setup dma. + */ + tab->project_and_emit_verts( mmesa, (GLfloat *)verts, out, n ); + + /* Convert the planar polygon to a list of triangles and emit to + * elt buffers. + */ + for (i = 2 ; i < n ; i++) { + mmesa->next_elt[0] = out[0]; + mmesa->next_elt[1] = out[i-1]; + mmesa->next_elt[2] = out[i]; + mmesa->next_elt += 3; + } + } +} + + + + +/* Build a table of functions to clip each primitive type. These + * produce a list of elements in the appropriate 'reduced' primitive, + * ie (points, lines, triangles) containing all the clipped and + * unclipped primitives from the original list. + */ + +#define INIT(x) + +#define TRI_THRESHOLD (3 * sizeof(GLuint)) + +#define UNCLIPPED_VERT(x) (mmesa->first_vert_phys - x * BUFFER_STRIDE * 4) + +#define TRIANGLE( e2, e1, e0 ) \ +do { \ + if ((GLuint)mmesa->next_vert - \ + (GLuint)mmesa->next_elt < TRI_THRESHOLD) \ + fire_elts(mmesa); \ + mmesa->next_elt[0] = UNCLIPPED_VERT(e2); \ + mmesa->next_elt[1] = UNCLIPPED_VERT(e1); \ + mmesa->next_elt[2] = UNCLIPPED_VERT(e0); \ + mmesa->next_elt+=3; \ +} while (0) + +#define CLIP_TRIANGLE( e2, e1, e0 ) \ +do { \ + GLubyte ormask = mask[e2] | mask[e1] | mask[e0]; \ + if (ormask == 0) { \ + TRIANGLE( e2, e1, e0 ); \ + } else if ((mask[e2] & mask[e1] & mask[e0]) == 0) { \ + out[0] = e2; \ + out[1] = e1; \ + out[2] = e0; \ + mga_tri_clip( mmesa, VB, out, ormask ); \ + } \ +} while (0) + +#define LOCAL_VARS \ + mgaContextPtr mmesa = MGA_CONTEXT( VB->ctx ); \ + GLuint *elt = VB->EltPtr->data; \ + GLuint out[VB_MAX_CLIPPED_VERTS]; \ + GLubyte *mask = VB->ClipMask; \ + (void) mask; (void) out; (void) elt; (void) mmesa; + + + +#define RENDER_POINTS(start, count) +#define RENDER_LINE(i1, i0) +#define RENDER_TRI(i2, i1, i0, pv, parity) \ +do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e0 = elt[i0]; \ + if (parity) e2 = elt[i1], e1 = elt[i2]; \ + CLIP_TRIANGLE( e2, e1, e0 ); \ +} while (0) + +#define RENDER_QUAD(i3, i2, i1, i0, pv ) \ + CLIP_TRIANGLE(elt[i3], elt[i2], elt[i0]); \ + CLIP_TRIANGLE(elt[i2], elt[i1], elt[i0]) + +#define TAG(x) mga_##x##_elt +#include "render_tmp.h" + + + +#define LOCAL_VARS \ + mgaContextPtr mmesa = MGA_CONTEXT( VB->ctx ); \ + GLuint *elt = VB->EltPtr->data; \ + (void) elt; (void) mmesa; + +#define RENDER_POINTS(start, count) +#define RENDER_LINE(i1, i0) +#define RENDER_TRI(i2, i1, i0, pv, parity) \ +do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e0 = elt[i0]; \ + if (parity) e2 = elt[i1], e1 = elt[i2]; \ + TRIANGLE( e2, e1, e0 ); \ +} while (0) + +#define RENDER_QUAD(i3, i2, i1, i0, pv ) \ + TRIANGLE(elt[i3], elt[i2], elt[i0]); \ + TRIANGLE(elt[i2], elt[i1], elt[i0]) + +#define TAG(x) mga_##x##_elt_unclipped +#include "render_tmp.h" + + + + +static void refresh_projection_matrix( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLfloat *m = mmesa->device_matrix; + GLmatrix *mat = &ctx->Viewport.WindowMap; + + REFRESH_DRAWABLE_INFO(mmesa); + + m[MAT_SX] = mat->m[MAT_SX]; + m[MAT_TX] = mat->m[MAT_TX] + mmesa->drawX + .5; + m[MAT_SY] = (- mat->m[MAT_SY]); + m[MAT_TY] = (- mat->m[MAT_TY]) + mmesa->driDrawable->h + mmesa->drawY - .5; + m[MAT_SZ] = mat->m[MAT_SZ] * (1.0 / 0x10000); + m[MAT_TZ] = mat->m[MAT_TZ] * (1.0 / 0x10000); +} + +#define CLIP_UBYTE_B 0 +#define CLIP_UBYTE_G 1 +#define CLIP_UBYTE_R 2 +#define CLIP_UBYTE_A 3 + + +#define TYPE (0) +#define TAG(x) x +#include "mgaelttmp.h" + +#define TYPE (MGA_RGBA_BIT) +#define TAG(x) x##_RGBA +#include "mgaelttmp.h" + +#define TYPE (MGA_TEX0_BIT) +#define TAG(x) x##_TEX0 +#include "mgaelttmp.h" + +#define TYPE (MGA_RGBA_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_RGBA_TEX0 +#include "mgaelttmp.h" + +#define TYPE (MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_RGBA_TEX0_TEX1 +#include "mgaelttmp.h" + +#define TYPE (MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_TEX0_TEX1 +#include "mgaelttmp.h" + + +/* Very sparsely popluated array - fix the indices. + */ +static struct mga_elt_tab mgaEltTab[0x80]; + +void mgaDDEltPathInit( void ) +{ + mga_render_init_elt(); + mga_render_init_elt_unclipped(); + + mga_init_eltpath( &mgaEltTab[0] ); + mga_init_eltpath_RGBA( &mgaEltTab[MGA_RGBA_BIT] ); + mga_init_eltpath_TEX0( &mgaEltTab[MGA_TEX0_BIT] ); + mga_init_eltpath_RGBA_TEX0( &mgaEltTab[MGA_RGBA_BIT|MGA_TEX0_BIT] ); + mga_init_eltpath_TEX0_TEX1( &mgaEltTab[MGA_TEX0_BIT|MGA_TEX1_BIT] ); + mga_init_eltpath_RGBA_TEX0_TEX1( &mgaEltTab[MGA_RGBA_BIT|MGA_TEX0_BIT| + MGA_TEX1_BIT] ); +} + +#define VALID_SETUP (MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) + + + +/* Use a temporary array for device coordinates, so that we can easily + * tap into existing mesa assembly. Otherwise consider emitting + * device coordinates to dma buffers directly from the project/cliptest + * routine. (requires output stride, potential loss of writecombining + * efficiency?) + * + * This path is a lot closer to the standard vertex path in the + * initial stages than the original fastpath. A slightly more optimal + * path could be constructed, but would require us to write new + * assembly. + */ +void mgaDDEltPath( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + GLenum prim = ctx->CVA.elt_mode; + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + struct mga_elt_tab *tab = &mgaEltTab[mmesa->setupindex & VALID_SETUP]; + + VB->ClipPtr = TransformRaw(&VB->Clip, &ctx->ModelProjectMatrix, VB->ObjPtr ); + + refresh_projection_matrix( ctx ); + + VB->ClipAndMask = ~0; + VB->ClipOrMask = 0; + VB->Projected = gl_clip_tab[VB->ClipPtr->size]( VB->ClipPtr, + &VB->Win, + VB->ClipMask, + &VB->ClipOrMask, + &VB->ClipAndMask ); + + if (VB->ClipAndMask) + return; + + if (mmesa->vertex_dma_buffer) + mgaFlushVertices( mmesa ); + + if (mmesa->new_state) + mgaDDUpdateHwState( ctx ); + + /* Allocate a single buffer to hold unclipped vertices. All + * unclipped vertices must be contiguous. + */ + if ((GLuint)mmesa->next_vert - (GLuint)mmesa->next_elt < + VB->Count * BUFFER_STRIDE * sizeof(GLuint)) + fire_elts( mmesa ); + + mmesa->retained_buf = mmesa->elt_buf; + + /* Emit unclipped vertices to the buffer. + */ + tab->emit_unclipped_verts( VB ); + + /* Emit indices and clipped vertices to one or more buffers. + */ + if (VB->ClipOrMask) { + mmesa->elt_tab = tab; + mga_render_tab_elt[prim]( VB, 0, VB->EltPtr->count, 0 ); + } else + mga_render_tab_elt_unclipped[prim]( VB, 0, VB->EltPtr->count, 0 ); + + /* Send to hardware and release any retained buffers. + */ + release_bufs( mmesa ); + + /* This indicates that there is no cached data to reuse. + */ + VB->pipeline->data_valid = 0; + VB->pipeline->new_state = 0; +} + diff --git a/xc/lib/GL/mesa/src/drv/mga/mgaelttmp.h b/xc/lib/GL/mesa/src/drv/mga/mgaelttmp.h new file mode 100644 index 000000000..ce758a532 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/mga/mgaelttmp.h @@ -0,0 +1,269 @@ +/* + * DRI Hardware Device Driver for G200/G400 + * Copyright (C) 1999 Keith Whitwell + * + * 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 + * KEITH WHITWELL, 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. + * + */ + +/* Buffers fill from high addresses down with vertices and from low + * addresses up with elements. + */ + + +/* Emit the bulk of the vertices to the first dma buffer. Leave + * empty slots for clipped vertices so that we can still address + * vertices by index. + */ +static void TAG(emit_unclipped_verts)( struct vertex_buffer *VB ) +{ + GLuint i; + mgaContextPtr mmesa = MGA_CONTEXT(VB->ctx); + GLfloat *dev = VB->Projected->start; + GLubyte *color = VB->ColorPtr->start; + GLfloat *tex0_data = VB->TexCoordPtr[0]->start; + GLfloat *tex1_data = VB->TexCoordPtr[1]->start; + GLuint color_stride = VB->ColorPtr->stride; + GLuint tex0_stride = VB->TexCoordPtr[0]->stride; + GLuint tex1_stride = VB->TexCoordPtr[1]->stride; + + GLfloat *f = mmesa->next_vert; + GLuint count = VB->Count; + GLubyte *clipmask = VB->ClipMask; + + const GLfloat *m = mmesa->device_matrix; + const GLfloat sx = m[0], sy = m[5], sz = m[10]; + const GLfloat tx = m[12], ty = m[13], tz = m[14]; + + mmesa->retained_buf = mmesa->elt_buf; + mmesa->first_vert_phys = mmesa->next_vert_phys; + + for (i = 0 ; i < count ; f -= BUFFER_STRIDE, i++) + { + if (!clipmask[i]) + { + f[0] = sx * dev[0] + tx; + f[1] = sy * dev[1] + ty; + f[2] = sz * dev[2] + tz; + f[3] = dev[3]; + + if (TYPE & MGA_RGBA_BIT) { +#if defined(USE_X86_ASM) + __asm__ ( + "movl (%%edx),%%eax \n" + "bswap %%eax \n" + "rorl $8,%%eax \n" + "movl %%eax,16(%%edi) \n" + : + : "d" (color), "D" (f) + : "%eax" ); +#else + GLubyte *b = (GLubyte *)&f[4]; + b[CLIP_UBYTE_B] = color[2]; + b[CLIP_UBYTE_G] = color[1]; + b[CLIP_UBYTE_R] = color[0]; + b[CLIP_UBYTE_A] = color[3]; +#endif + } + + if (TYPE & MGA_TEX0_BIT) { +/* fprintf(stderr, "i %d tex0 %f, %f\n", i, */ +/* tex0_data[0], tex0_data[1]); */ + *(int*)&f[6] = *(int*)&tex0_data[0]; + *(int*)&f[7] = *(int*)&tex0_data[1]; + } + + if (TYPE & MGA_TEX1_BIT) { + *(int*)&f[8] = *(int*)&tex1_data[0]; + *(int*)&f[9] = *(int*)&tex1_data[1]; + } + } + + STRIDE_F(dev, 16); + if (TYPE & MGA_RGBA_BIT) color += color_stride; + if (TYPE & MGA_TEX0_BIT) STRIDE_F(tex0_data, tex0_stride); + if (TYPE & MGA_TEX1_BIT) STRIDE_F(tex1_data, tex1_stride); + } + + mmesa->next_vert = f; + mmesa->next_vert_phys -= count * BUFFER_STRIDE * sizeof(GLuint); +} + + +/* Build three temporary clipspace vertex for clipping a triangle. + * Recreate from the VB data rather than trying to read back from + * uncached memory. + */ +static void TAG(build_tri_verts)( mgaContextPtr mmesa, + struct vertex_buffer *VB, + GLfloat *O, + GLuint *elt ) +{ + int i; + + for (i = 0 ; i < 3 ; i++, O += CLIP_STRIDE) { + GLfloat *clip = VB->Clip.start + elt[i]*4; + + O[0] = clip[0]; + O[1] = clip[1]; + O[2] = clip[2]; + O[3] = clip[3]; + + if (TYPE & MGA_RGBA_BIT) { + GLubyte *col = VEC_ELT(VB->ColorPtr, GLubyte, elt[i]); + GLubyte *b = (GLubyte *)&O[4]; + b[CLIP_UBYTE_R] = col[0]; + b[CLIP_UBYTE_G] = col[1]; + b[CLIP_UBYTE_B] = col[2]; + b[CLIP_UBYTE_A] = col[3]; + } + + if (0) + fprintf(stderr, + "build_tri_vert elt[%d]: %d phys: %x (first_phys %x elt_buf %x\n", + i, elt[i], UNCLIPPED_VERT(elt[i]), + mmesa->first_vert_phys, (GLuint)mmesa->elt_buf); + + *(GLuint *)&O[5] = UNCLIPPED_VERT(elt[i]); + + if (TYPE & MGA_TEX0_BIT) { + GLfloat *tex0_data = VEC_ELT(VB->TexCoordPtr[0], GLfloat, elt[i]); + *(int*)&O[6] = *(int*)&tex0_data[0]; + *(int*)&O[7] = *(int*)&tex0_data[1]; + } + + if (TYPE & MGA_TEX1_BIT) { + GLfloat *tex1_data = VEC_ELT(VB->TexCoordPtr[1], GLfloat, elt[i]); + *(int*)&O[8] = *(int*)&tex1_data[0]; + *(int*)&O[9] = *(int*)&tex1_data[1]; + } + } +} + + +/* Interpolate between two of the vertices constructed above. + */ +static void TAG(interp)( GLfloat t, + GLfloat *O, + const GLfloat *I, + const GLfloat *J ) +{ + O[0] = LINTERP(t, I[0], J[0]); + O[1] = LINTERP(t, I[1], J[1]); + O[2] = LINTERP(t, I[2], J[2]); + O[3] = LINTERP(t, I[3], J[3]); + + if (TYPE & MGA_RGBA_BIT) { + INTERP_RGBA(t, + ((GLubyte *)&(O[4])), + ((GLubyte *)&(I[4])), + ((GLubyte *)&(J[4]))); + } + + if (0) fprintf(stderr, "setting 0x%x to ~0\n", (GLuint)&O[5]); + + *(GLuint *)&O[5] = ~0; /* note that this is a new vertex */ + + if (TYPE & MGA_TEX0_BIT) { + O[6] = LINTERP(t, I[6], J[6]); + O[7] = LINTERP(t, I[7], J[7]); + } + + if (TYPE & MGA_TEX1_BIT) { + O[8] = LINTERP(t, I[8], J[8]); + O[9] = LINTERP(t, I[9], J[9]); + } +} + + + +/* When clipping is complete, scan the final vertex list and emit any + * new ones to dma buffers. Update the element list to a format + * suitable for sending to hardware. + */ +static void TAG(project_and_emit_verts)( mgaContextPtr mmesa, + const GLfloat *verts, + GLuint *elt, + int nr) +{ + + GLfloat *O = mmesa->next_vert; + GLuint phys = mmesa->next_vert_phys; + + const GLfloat *m = mmesa->device_matrix; + const GLfloat sx = m[0], sy = m[5], sz = m[10]; + const GLfloat tx = m[12], ty = m[13], tz = m[14]; + GLuint i; + + for (i = 0 ; i < nr ; i++) { + const GLfloat *I = &verts[elt[i] * CLIP_STRIDE]; + GLuint tmp = *(GLuint *)&I[5]; + + if (0) fprintf(stderr, "elt[%d] (tmp 0x%x %d) %d --> ", i, (GLuint)&I[5], + tmp, elt[i]); + + + if ((elt[i] = tmp) == ~0) + { + GLfloat oow = 1.0/I[3]; + + elt[i] = phys; + phys -= BUFFER_STRIDE * sizeof(GLuint); + + O[0] = sx * I[0] * oow + tx; + O[1] = sy * I[1] * oow + ty; + O[2] = sz * I[2] * oow + tz; + O[3] = oow; + + if (TYPE & MGA_RGBA_BIT) { + *(int*)&O[4] = *(int*)&I[4]; + } + + if (TYPE & MGA_TEX0_BIT) { + *(int*)&O[6] = *(int*)&I[6]; + *(int*)&O[7] = *(int*)&I[7]; + } + + if (TYPE & MGA_TEX1_BIT) { + *(int*)&O[8] = *(int*)&I[8]; + *(int*)&O[9] = *(int*)&I[9]; + } + + O -= BUFFER_STRIDE; + } + if (0) fprintf(stderr, "0x%x\n", elt[i]); + } + + mmesa->next_vert = O; + mmesa->next_vert_phys = phys; +} + + + +static void TAG(mga_init_eltpath)( struct mga_elt_tab *tab ) +{ + tab->emit_unclipped_verts = TAG(emit_unclipped_verts); + tab->build_tri_verts = TAG(build_tri_verts); + tab->interp = TAG(interp); + tab->project_and_emit_verts = TAG(project_and_emit_verts); +} + +#undef TYPE +#undef TAG +#undef STRIDE diff --git a/xc/lib/GL/mesa/src/drv/mga/mgafastpath.c b/xc/lib/GL/mesa/src/drv/mga/mgafastpath.c index cd316e162..73a939b74 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgafastpath.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgafastpath.c @@ -488,6 +488,16 @@ void mgaDDFastPath( struct vertex_buffer *VB ) gl_prepare_arrays_cva( VB ); /* still need this */ + if (gl_reduce_prim[prim] == GL_TRIANGLES && + VB->Count < (MGA_DMA_BUF_SZ / 48) && + (ctx->ModelProjectMatrix.flags & (MAT_FLAG_GENERAL| + MAT_FLAG_PERSPECTIVE)) && + mmesa->mgaScreen->chipset == MGA_CARD_TYPE_G400) + { + mgaDDEltPath( VB ); + return; + } + /* Reserve enough space for the pathological case. */ if (VB->EltPtr->count * 12 > MGA_DRIVER_DATA(VB)->size) { diff --git a/xc/lib/GL/mesa/src/drv/mga/mgafasttmp.h b/xc/lib/GL/mesa/src/drv/mga/mgafasttmp.h index 43caddcac..683640409 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgafasttmp.h +++ b/xc/lib/GL/mesa/src/drv/mga/mgafasttmp.h @@ -39,7 +39,6 @@ static void TAG(mga_setup_full)( struct vertex_buffer *VB, GLuint do_cliptest ) const GLfloat * const m = ctx->ModelProjectMatrix.m; GLuint start = VB->CopyStart; GLuint count = VB->Count; - GLuint i; gl_xform_points3_v16_general(MGA_DRIVER_DATA(VB)->verts[start].f, m, @@ -71,26 +70,63 @@ static void TAG(mga_setup_full)( struct vertex_buffer *VB, GLuint do_cliptest ) GLuint tex1_stride = VB->TexCoordPtr[1]->stride; GLfloat *f = MGA_DRIVER_DATA(VB)->verts[start].f; - - for (i = start ; i < count ; i++, f += 16) { + GLfloat *end = f+(16*(count-start)); + while (f != end) { if (TYPE & MGA_RGBA_BIT) { +#if defined(USE_X86_ASM) + __asm__ ( + "movl (%%edx),%%eax \n" + "bswap %%eax \n" + "rorl $8,%%eax \n" + "movl %%eax,16(%%edi) \n" + : + : "d" (color), "D" (f) + : "%eax" ); +#else + GLubyte *col = color; GLubyte *b = (GLubyte *)&f[CLIP_UBYTE_COLOR]; - GLubyte *col = color; color += color_stride; - b[CLIP_UBYTE_R] = col[0]; - b[CLIP_UBYTE_G] = col[1]; b[CLIP_UBYTE_B] = col[2]; + b[CLIP_UBYTE_G] = col[1]; + b[CLIP_UBYTE_R] = col[0]; b[CLIP_UBYTE_A] = col[3]; +#endif } if (TYPE & MGA_TEX0_BIT) { - f[CLIP_S0] = tex0_data[0]; - f[CLIP_T0] = tex0_data[1]; - STRIDE_F(tex0_data, tex0_stride); +#if defined (USE_X86_ASM) + __asm__ ( + "movl (%%ecx), %%eax \n" + "movl %%eax, 24(%%edi) \n" + "movl 4(%%ecx), %%eax \n" + "movl %%eax, 28(%%edi)" + : + : "c" (tex0_data), "D" (f) + : "%eax"); +#else + *(unsigned int *)(f+CLIP_S0) = *(unsigned int *)tex0_data; + *(unsigned int *)(f+CLIP_T0) = *(unsigned int *)(tex0_data+1); +#endif } if (TYPE & MGA_TEX1_BIT) { - f[CLIP_S1] = tex1_data[0]; - f[CLIP_T1] = tex1_data[1]; - STRIDE_F(tex1_data, tex1_stride); + /* Hits a second cache line. + */ +#if defined (USE_X86_ASM) + __asm__ ( + "movl (%%esi), %%eax \n" + "movl %%eax, 32(%%edi) \n" + "movl 4(%%esi), %%eax \n" + "movl %%eax, 36(%%edi)" + : + : "S" (tex1_data), "D" (f) + : "%eax"); +#else + *(unsigned int *)(f+CLIP_S1) = *(unsigned int *)tex1_data; + *(unsigned int *)(f+CLIP_T1) = *(unsigned int *)(tex1_data+1); +#endif } + if(TYPE & MGA_RGBA_BIT)color += color_stride; + if(TYPE & MGA_TEX0_BIT)STRIDE_F(tex0_data, tex0_stride); + if(TYPE & MGA_TEX1_BIT)STRIDE_F(tex1_data, tex1_stride); + f += 16; } } diff --git a/xc/lib/GL/mesa/src/drv/mga/mgaioctl.c b/xc/lib/GL/mesa/src/drv/mga/mgaioctl.c index c1819924d..640849e3f 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgaioctl.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgaioctl.c @@ -14,114 +14,137 @@ #include "mgalog.h" #include "mgavb.h" #include "mgatris.h" +#include "mgabuffers.h" + #include "drm.h" #include <sys/ioctl.h> +#define DEPTH_SCALE 65535.0F + static void mga_iload_dma_ioctl(mgaContextPtr mmesa, - int x1, int y1, int x2, int y2, - unsigned long dest, unsigned int maccess) + unsigned long dest, + int length) { int retcode; drm_mga_iload_t iload; - drmBufPtr buf = mmesa->dma_buffer; + drmBufPtr buf = mmesa->iload_buffer; iload.idx = buf->idx; iload.destOrg = dest; - iload.mAccess = maccess; - iload.texture.x1 = x1; - iload.texture.y1 = y1; - iload.texture.y2 = x2; - iload.texture.x2 = y2; + iload.length = length; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "DRM_IOCTL_MGA_ILOAD idx %d dst %x length %d\n", + iload.idx, iload.destOrg, iload.length); + if ((retcode = ioctl(mmesa->driFd, DRM_IOCTL_MGA_ILOAD, &iload))) { printf("send iload retcode = %d\n", retcode); exit(1); } -} + mmesa->iload_buffer = 0; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished iload dma put\n"); + +} -static void mga_vertex_dma_ioctl(mgaContextPtr mmesa) +int mgaUpdateLock( mgaContextPtr mmesa, drmLockFlags flags ) { - int retcode; - int size = MGA_DMA_BUF_SZ; - drmDMAReq dma; - drmBufPtr buf = mmesa->dma_buffer; + drm_lock_t lock; + + lock.flags = 0; - dma.context = mmesa->hHWContext; - dma.send_count = 1; - dma.send_list = &buf->idx; - dma.send_sizes = &size; - dma.flags = DRM_DMA_WAIT; - dma.request_count = 0; - dma.request_size = 0; - dma.request_list = 0; - dma.request_sizes = 0; - - if ((retcode = drmDMA(mmesa->driFd, &dma))) { - printf("send iload retcode = %d\n", retcode); - exit(1); + if (mmesa->sarea->last_quiescent != mmesa->sarea->last_enqueue && + flags & DRM_LOCK_QUIESCENT) { + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaLockQuiescent\n"); + lock.flags |= _DRM_LOCK_QUIESCENT; + } + + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + + if (!lock.flags) + return 0; + + if(ioctl(mmesa->driFd, DRM_IOCTL_MGA_FLUSH, &lock)) { + fprintf(stderr, "Lockupdate failed\n"); + return -1; } + + if(flags & DRM_LOCK_QUIESCENT) + mmesa->sarea->last_quiescent = mmesa->sarea->last_enqueue; + + return 0; } - -static void mga_get_buffer_ioctl( mgaContextPtr mmesa ) +static drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa ) { int idx = 0; int size = 0; drmDMAReq dma; int retcode; + drmBufPtr buf; - fprintf(stderr, "Getting dma buffer\n"); + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Getting dma buffer\n"); dma.context = mmesa->hHWContext; dma.send_count = 0; dma.send_list = NULL; dma.send_sizes = NULL; - dma.flags = DRM_DMA_WAIT; + dma.flags = 0; dma.request_count = 1; dma.request_size = MGA_DMA_BUF_SZ; dma.request_list = &idx; dma.request_sizes = &size; - - if ((retcode = drmDMA(mmesa->driFd, &dma))) { - fprintf(stderr, "request drmDMA retcode = %d\n", retcode); - exit(1); - } + dma.granted_count = 0; - mmesa->dma_buffer = &mmesa->mgaScreen->bufs->list[idx]; -} -static void mga_swap_ioctl( mgaContextPtr mmesa ) -{ - int retcode; - drm_mga_swap_t swap; - - if((retcode = ioctl(mmesa->driFd, DRM_IOCTL_MGA_SWAP, &swap))) { - printf("send swap retcode = %d\n", retcode); - exit(1); - } -} + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "drmDMA (get) ctx %d count %d size 0x%x\n", + dma.context, dma.request_count, + dma.request_size); + while (1) { + retcode = drmDMA(mmesa->driFd, &dma); + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "retcode %d sz %d idx %d count %d\n", + retcode, + dma.request_sizes[0], + dma.request_list[0], + dma.granted_count); -static void mga_clear_ioctl( mgaContextPtr mmesa, int flags, int col, int zval ) -{ - int retcode; - drm_mga_clear_t clear; - - clear.flags = flags; - clear.clear_color = col; - clear.clear_depth = zval; - - if((retcode = ioctl(mmesa->driFd, DRM_IOCTL_MGA_CLEAR, &clear))) { - printf("send clear retcode = %d\n", retcode); - exit(1); + if (retcode == 0 && + dma.request_sizes[0] && + dma.granted_count) + break; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "\n\nflush"); + mgaUpdateLock( mmesa, DRM_LOCK_FLUSH ); } -} + buf = &(mmesa->mgaScreen->bufs->list[idx]); + buf->used = 0; + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, + "drmDMA (get) returns size[0] 0x%x idx[0] %d\n" + "dma_buffer now: buf idx: %d size: %d used: %d\n", + dma.request_sizes[0], dma.request_list[0], + buf->idx, buf->total, + buf->used); + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished getbuffer\n"); + + return buf; +} @@ -130,52 +153,59 @@ GLbitfield mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - GLuint c = mmesa->ClearColor; - mgaUI32 zval = (mgaUI32) (ctx->Depth.Clear * DEPTH_SCALE); __DRIdrawablePrivate *dPriv = mmesa->driDrawable; - int flags = 0; + const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); + drm_mga_clear_t clear; + int retcode; int i; + static int nrclears; - mgaMsg( 10, "mgaClear( %i, %i, %i, %i, %i )\n", - mask, x, y, width, height ); - + if (0) fprintf(stderr, "clear %d: %d,%d %dx%d\n", all,cx,cy,cw,ch); - mgaFlushVertices( mmesa ); + clear.flags = 0; + clear.clear_color = mmesa->ClearColor; + clear.clear_depth = (mgaUI32) (ctx->Depth.Clear * DEPTH_SCALE); + FLUSH_BATCH( mmesa ); + + if ((mask & DD_FRONT_LEFT_BIT) && colorMask == ~0) { + clear.flags |= MGA_FRONT; + mask &= ~DD_FRONT_LEFT_BIT; + } - if (mask & GL_COLOR_BUFFER_BIT) { - if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT) { - flags |= MGA_CLEAR_FRONT; - mask &= ~GL_COLOR_BUFFER_BIT; - } else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT) { - flags |= MGA_CLEAR_BACK; - mask &= ~GL_COLOR_BUFFER_BIT; - } + if ((mask & DD_BACK_LEFT_BIT) && colorMask == ~0) { + clear.flags |= MGA_BACK; + mask &= ~DD_BACK_LEFT_BIT; } - if ((flags & GL_DEPTH_BUFFER_BIT) && ctx->Depth.Mask) { - flags |= MGA_CLEAR_DEPTH; - mask &= ~GL_DEPTH_BUFFER_BIT; + if ((mask & DD_DEPTH_BIT) && ctx->Depth.Mask) { + clear.flags |= MGA_DEPTH; + mask &= ~DD_DEPTH_BIT; } - if (!flags) + if (!clear.flags) return mask; LOCK_HARDWARE( mmesa ); - + + if (mmesa->dirty_cliprects) + mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK)); + /* flip top to bottom */ cy = dPriv->h-cy-ch; cx += mmesa->drawX; cy += mmesa->drawY; - for (i = 0 ; i < dPriv->numClipRects ; ) { + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Clear, bufs %x nbox %d\n", + (int)clear.flags, (int)mmesa->numClipRects); - /* Use the cliprects for the current draw buffer - */ + for (i = 0 ; i < mmesa->numClipRects ; ) + { int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, mmesa->numClipRects); XF86DRIClipRectRec *box = mmesa->pClipRects; - xf86drmClipRectRec *b = mmesa->sarea->boxes; - mmesa->sarea->nbox = nr - i; + drm_clip_rect_t *b = mmesa->sarea->boxes; + int n = 0; if (!all) { for ( ; i < nr ; i++) { @@ -196,16 +226,37 @@ GLbitfield mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean all, b->x2 = x + w; b->y2 = y + h; b++; + n++; } } else { - for ( ; i < nr ; i++) - *b++ = *(xf86drmClipRectRec *)&box[i]; + for ( ; i < nr ; i++) { + *b++ = *(drm_clip_rect_t *)&box[i]; + n++; + } } - mga_clear_ioctl( mmesa, mask, c, zval ); + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, + "DRM_IOCTL_MGA_CLEAR flag 0x%x color %x depth %x nbox %d\n", + clear.flags, clear.clear_color, + clear.clear_depth, mmesa->sarea->nbox); + + + mmesa->sarea->nbox = n; + + retcode = ioctl(mmesa->driFd, DRM_IOCTL_MGA_CLEAR, &clear); + if (retcode) { + printf("send clear retcode = %d\n", retcode); + exit(1); + } + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished clear %d\n", ++nrclears); } UNLOCK_HARDWARE( mmesa ); + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + return mask; } @@ -218,50 +269,61 @@ GLbitfield mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean all, void mgaSwapBuffers( mgaContextPtr mmesa ) { __DRIdrawablePrivate *dPriv = mmesa->driDrawable; + XF86DRIClipRectPtr pbox; + int nbox; + drm_mga_swap_t swap; + static int nrswaps; + int retcode; int i; + int tmp; - mgaFlushVertices( mmesa ); - LOCK_HARDWARE( mmesa ); - { - /* Use the frontbuffer cliprects - */ - XF86DRIClipRectPtr pbox = dPriv->pClipRects; - int nbox = dPriv->numClipRects; + FLUSH_BATCH( mmesa ); - for (i = 0 ; i < nbox ; ) - { - int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); - XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)mmesa->sarea->boxes; - mmesa->sarea->nbox = nr - i; + LOCK_HARDWARE( mmesa ); + + /* Use the frontbuffer cliprects + */ + if (mmesa->dirty_cliprects & MGA_FRONT) + mgaUpdateRects( mmesa, MGA_FRONT ); + - for ( ; i < nr ; i++) - *b++ = pbox[i]; - - mga_swap_ioctl( mmesa ); - } - } + pbox = dPriv->pClipRects; + nbox = dPriv->numClipRects; + if (0) fprintf(stderr, "swap, nbox %d\n", nbox); -#if 1 - UNLOCK_HARDWARE(mmesa); -#else + for (i = 0 ; i < nbox ; ) { - last_enqueue = mmesa->sarea->lastEnqueue; - last_dispatch = mmesa->sarea->lastDispatch; - UNLOCK_HARDWARE; + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)mmesa->sarea->boxes; + + mmesa->sarea->nbox = nr - i; + + for ( ; i < nr ; i++) + *b++ = pbox[i]; - /* Throttle runaway apps - there should be an easier way to sleep - * on dma without locking out the rest of the system! - */ - if (mmesa->lastSwap > last_dispatch) { - drmGetLock(mmesa->driFd, mmesa->hHWContext, DRM_LOCK_QUIESCENT); - DRM_UNLOCK(mmesa->driFd, mmesa->driHwLock, mmesa->hHWContext); + if (0) + fprintf(stderr, "DRM_IOCTL_MGA_SWAP\n"); + + if((retcode = ioctl(mmesa->driFd, DRM_IOCTL_MGA_SWAP, &swap))) { + printf("send swap retcode = %d\n", retcode); + exit(1); } - mmesa->lastSwap = last_enqueue; + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "finished swap %d\n", ++nrswaps); } -#endif + + tmp = GET_ENQUEUE_AGE(mmesa); + + UNLOCK_HARDWARE( mmesa ); + + if (GET_DISPATCH_AGE(mmesa) < mmesa->lastSwap) + mgaWaitAge(mmesa, mmesa->lastSwap); + + mmesa->lastSwap = tmp; + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; } @@ -269,13 +331,165 @@ void mgaSwapBuffers( mgaContextPtr mmesa ) */ void mgaDDFinish( GLcontext *ctx ) { - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - drmGetLock(mmesa->driFd, mmesa->hHWContext, DRM_LOCK_QUIESCENT); - DRM_UNLOCK(mmesa->driFd, mmesa->driHwLock, mmesa->hHWContext); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + FLUSH_BATCH( mmesa ); + + if (mmesa->sarea->last_quiescent != mmesa->sarea->last_enqueue) { + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaRegetLockQuiescent\n"); + + LOCK_HARDWARE( mmesa ); + mgaUpdateLock( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH); + UNLOCK_HARDWARE( mmesa ); + + mmesa->sarea->last_quiescent = mmesa->sarea->last_enqueue; + } +} + +void mgaWaitAgeLocked( mgaContextPtr mmesa, int age ) +{ + if (GET_DISPATCH_AGE(mmesa) < age) { + if (0) fprintf(stderr, "\n\n\nmgaWaitAgeLocked\n"); + mgaUpdateLock( mmesa, DRM_LOCK_FLUSH ); + } +} + + +void mgaWaitAge( mgaContextPtr mmesa, int age ) +{ + if (GET_DISPATCH_AGE(mmesa) < age) { + LOCK_HARDWARE(mmesa); + if (GET_DISPATCH_AGE(mmesa) < age) { + if (0) fprintf(stderr, "\n\n\nmgaWaitAge\n"); + mgaUpdateLock( mmesa, DRM_LOCK_FLUSH ); + } + UNLOCK_HARDWARE(mmesa); + } +} + + +static int intersect_rect( drm_clip_rect_t *out, + drm_clip_rect_t *a, + drm_clip_rect_t *b ) +{ + *out = *a; + if (b->x1 > out->x1) out->x1 = b->x1; + if (b->y1 > out->y1) out->y1 = b->y1; + if (b->x2 < out->x2) out->x2 = b->x2; + if (b->y2 < out->y2) out->y2 = b->y2; + if (out->x1 >= out->x2) return 0; + if (out->y1 >= out->y2) return 0; + return 1; +} + + + + +static void age_mmesa( mgaContextPtr mmesa, int age ) +{ + if (mmesa->CurrentTexObj[0]) mmesa->CurrentTexObj[0]->age = age; + if (mmesa->CurrentTexObj[1]) mmesa->CurrentTexObj[1]->age = age; } +void mgaFlushVerticesLocked( mgaContextPtr mmesa ) +{ + drm_clip_rect_t *pbox = (drm_clip_rect_t *)mmesa->pClipRects; + int nbox = mmesa->numClipRects; + drmBufPtr buffer = mmesa->vertex_dma_buffer; + drm_mga_vertex_t vertex; + int i; + + mmesa->vertex_dma_buffer = 0; + + if (!buffer) + return; + + if (mmesa->dirty_cliprects & mmesa->draw_buffer) + mgaUpdateRects( mmesa, mmesa->draw_buffer ); + + if (mmesa->dirty & ~MGA_UPLOAD_CLIPRECTS) + mgaEmitHwStateLocked( mmesa ); + + /* FIXME: Workaround bug in kernel module. + */ + mmesa->sarea->dirty |= MGA_UPLOAD_CTX; + + /* FIXME: dstorg bug + */ + if (0) + if (mmesa->lastX != mmesa->drawX || mmesa->lastY != mmesa->drawY) + fprintf(stderr, "****** last: %d,%d current: %d,%d\n", + mmesa->lastX, mmesa->lastY, + mmesa->drawX, mmesa->drawY); + + vertex.idx = buffer->idx; + vertex.used = buffer->used; + vertex.discard = 0; + + if (!nbox) + vertex.used = 0; + + if (nbox >= MGA_NR_SAREA_CLIPRECTS) + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + + if (!vertex.used || !(mmesa->dirty & MGA_UPLOAD_CLIPRECTS)) + { + if (nbox == 1) + mmesa->sarea->nbox = 0; + else + mmesa->sarea->nbox = nbox; + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "Firing vertex -- case a nbox %d\n", nbox); + + vertex.discard = 1; + ioctl(mmesa->driFd, DRM_IOCTL_MGA_VERTEX, &vertex); + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } + else + { + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, nbox); + drm_clip_rect_t *b = mmesa->sarea->boxes; + + if (mmesa->scissor) { + mmesa->sarea->nbox = 0; + + for ( ; i < nr ; i++) { + *b = pbox[i]; + if (intersect_rect(b, b, &mmesa->scissor_rect)) { + mmesa->sarea->nbox++; + b++; + } + } + + /* Culled? + */ + if (!mmesa->sarea->nbox) { + if (nr < nbox) continue; + vertex.used = 0; + } + } else { + mmesa->sarea->nbox = nr - i; + for ( ; i < nr ; i++) + *b++ = pbox[i]; + } + + /* Finished with the buffer? + */ + if (nr == nbox) + vertex.discard = 1; + mmesa->sarea->dirty |= MGA_UPLOAD_CLIPRECTS; + ioctl(mmesa->driFd, DRM_IOCTL_MGA_VERTEX, &vertex); + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } + } + mmesa->dirty &= ~MGA_UPLOAD_CLIPRECTS; +} void mgaFlushVertices( mgaContextPtr mmesa ) { @@ -284,38 +498,221 @@ void mgaFlushVertices( mgaContextPtr mmesa ) UNLOCK_HARDWARE( mmesa ); } +void mgaFlushEltsLocked( mgaContextPtr mmesa ) +{ + if (mmesa->first_elt != mmesa->next_elt) { + mgaFireEltsLocked( mmesa, + ((GLuint)mmesa->first_elt - + (GLuint)mmesa->elt_buf->address), + ((GLuint)mmesa->next_elt - + (GLuint)mmesa->elt_buf->address), + 0 ); + mmesa->first_elt = mmesa->next_elt; + } +} -void mgaFlushVerticesLocked( mgaContextPtr mmesa ) +void mgaFlushElts( mgaContextPtr mmesa ) +{ + LOCK_HARDWARE( mmesa ); + mgaFlushEltsLocked( mmesa ); + UNLOCK_HARDWARE( mmesa ); +} + + +mgaUI32 *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords ) +{ + int bytes = dwords * 4; + mgaUI32 *head; + + if (!mmesa->vertex_dma_buffer) { + LOCK_HARDWARE( mmesa ); + + if (mmesa->first_elt != mmesa->next_elt) + mgaFlushEltsLocked(mmesa); + + mmesa->vertex_dma_buffer = mga_get_buffer_ioctl( mmesa ); + UNLOCK_HARDWARE( mmesa ); + } else if (mmesa->vertex_dma_buffer->used + bytes > + mmesa->vertex_dma_buffer->total) { + LOCK_HARDWARE( mmesa ); + mgaFlushVerticesLocked( mmesa ); + mmesa->vertex_dma_buffer = mga_get_buffer_ioctl( mmesa ); + UNLOCK_HARDWARE( mmesa ); + } + + head = (mgaUI32 *)((char *)mmesa->vertex_dma_buffer->address + + mmesa->vertex_dma_buffer->used); + + mmesa->vertex_dma_buffer->used += bytes; + return head; +} + + +void mgaFireILoadLocked( mgaContextPtr mmesa, + GLuint offset, GLuint length ) +{ + if (!mmesa->iload_buffer) { + fprintf(stderr, "mgaFireILoad: no buffer\n"); + return; + } + + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaFireILoad idx %d ofs 0x%x length %d\n", + mmesa->iload_buffer->idx, (int)offset, (int)length ); + + mga_iload_dma_ioctl( mmesa, offset, length ); +} + +void mgaGetILoadBufferLocked( mgaContextPtr mmesa ) +{ + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) + fprintf(stderr, "mgaGetIloadBuffer (buffer now %p)\n", + mmesa->iload_buffer); + + mmesa->iload_buffer = mga_get_buffer_ioctl( mmesa ); +} + + + void mgaDDFlush( GLcontext *ctx ) { - XF86DRIClipRectPtr pbox = mmesa->pClipRects; + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + + FLUSH_BATCH( mmesa ); + + /* This may be called redundantly - dispatch_age may trail what + * has actually been sent and processed by the hardware. + */ + if (GET_DISPATCH_AGE( mmesa ) < mmesa->sarea->last_enqueue) { + LOCK_HARDWARE( mmesa ); + if (0) fprintf(stderr, "mgaDDFlush %d %d\n", GET_DISPATCH_AGE( mmesa ), mmesa->sarea->last_enqueue); + mgaUpdateLock( mmesa, DRM_LOCK_FLUSH ); + UNLOCK_HARDWARE( mmesa ); + } +} + + + +void mgaFireEltsLocked( mgaContextPtr mmesa, + GLuint start, + GLuint end, + GLuint discard ) +{ + drm_clip_rect_t *pbox = (drm_clip_rect_t *)mmesa->pClipRects; int nbox = mmesa->numClipRects; + drmBufPtr buffer = mmesa->elt_buf; + drm_mga_indices_t elts; int i; - if (mmesa->dirty) + + if (0) fprintf(stderr, "FireElts %d %d\n", start/4, end/4); + + if (!buffer) + return; + + if (mmesa->dirty_cliprects & mmesa->draw_buffer) + mgaUpdateRects( mmesa, mmesa->draw_buffer ); + + if (mmesa->dirty & ~MGA_UPLOAD_CLIPRECTS) mgaEmitHwStateLocked( mmesa ); - for (i = 0 ; i < nbox ; ) + /* FIXME: Workaround bug in kernel module. + */ + mmesa->sarea->dirty |= MGA_UPLOAD_CTX; + + elts.idx = buffer->idx; + elts.start = start; + elts.end = end; + elts.discard = 0; + + if (!nbox) + elts.end = start; + + if (nbox >= MGA_NR_SAREA_CLIPRECTS) + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + + if (elts.end == start || !(mmesa->dirty & MGA_UPLOAD_CLIPRECTS)) { - int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, nbox); - XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)mmesa->sarea->boxes; - mmesa->sarea->nbox = nr - i; + if (nbox == 1) + mmesa->sarea->nbox = 0; + else + mmesa->sarea->nbox = nbox; + + if (0) + fprintf(stderr, "Firing elts -- case a nbox %d\n", nbox); + + elts.discard = discard; + ioctl(mmesa->driFd, DRM_IOCTL_MGA_INDICES, &elts); + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } + else + { + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, nbox); + drm_clip_rect_t *b = mmesa->sarea->boxes; + + if (mmesa->scissor) { + mmesa->sarea->nbox = 0; + + for ( ; i < nr ; i++) { + *b = pbox[i]; + if (intersect_rect(b, b, &mmesa->scissor_rect)) { + mmesa->sarea->nbox++; + b++; + } + } + + /* Culled? + */ + if (!mmesa->sarea->nbox) { + if (nr < nbox) continue; + elts.end = start; + } + } else { + mmesa->sarea->nbox = nr - i; + for ( ; i < nr ; i++) + *b++ = pbox[i]; + } - for ( ; i < nr ; i++) - *b++ = pbox[i]; - - mga_vertex_dma_ioctl( mmesa ); + /* Potentially finished with the buffer? + */ + if (nr == nbox) + elts.discard = discard; - break; /* fix dma multiple dispatch */ + if (0) + fprintf(stderr, "Firing elts -- case b nbox %d\n", nbox); + + mmesa->sarea->dirty |= MGA_UPLOAD_CLIPRECTS; + ioctl(mmesa->driFd, DRM_IOCTL_MGA_INDICES, &elts); + age_mmesa(mmesa, mmesa->sarea->last_enqueue); + } } - mga_get_buffer_ioctl( mmesa ); + mmesa->dirty &= ~MGA_UPLOAD_CLIPRECTS; +} + +void mgaGetEltBufLocked( mgaContextPtr mmesa ) +{ + mmesa->elt_buf = mga_get_buffer_ioctl( mmesa ); } +void mgaReleaseBufLocked( mgaContextPtr mmesa, drmBufPtr buffer ) +{ + drm_mga_vertex_t vertex; + + if (!buffer) return; + + vertex.idx = buffer->idx; + vertex.used = 0; + vertex.discard = 1; + ioctl(mmesa->driFd, DRM_IOCTL_MGA_VERTEX, &vertex); +} void mgaDDInitIoctlFuncs( GLcontext *ctx ) { ctx->Driver.Clear = mgaClear; - ctx->Driver.Flush = 0; + ctx->Driver.Flush = mgaDDFlush; ctx->Driver.Finish = mgaDDFinish; } diff --git a/xc/lib/GL/mesa/src/drv/mga/mgaioctl.h b/xc/lib/GL/mesa/src/drv/mga/mgaioctl.h index 22ca26e17..900e4a4f8 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgaioctl.h +++ b/xc/lib/GL/mesa/src/drv/mga/mgaioctl.h @@ -9,9 +9,37 @@ GLbitfield mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean all, void mgaSwapBuffers( mgaContextPtr mmesa ); + + +mgaUI32 *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords ); + + +void mgaGetILoadBufferLocked( mgaContextPtr mmesa ); + + +void mgaFireILoadLocked( mgaContextPtr mmesa, + GLuint offset, GLuint length ); + +void mgaWaitAgeLocked( mgaContextPtr mmesa, int age ); +void mgaWaitAge( mgaContextPtr mmesa, int age ); +int mgaUpdateLock( mgaContextPtr mmesa, drmLockFlags flags ); + void mgaFlushVertices( mgaContextPtr mmesa ); void mgaFlushVerticesLocked( mgaContextPtr mmesa ); + +void mgaFireEltsLocked( mgaContextPtr mmesa, + GLuint start, + GLuint end, + GLuint discard ); + +void mgaGetEltBufLocked( mgaContextPtr mmesa ); +void mgaReleaseBufLocked( mgaContextPtr mmesa, drmBufPtr buffer ); + +void mgaFlushEltsLocked( mgaContextPtr mmesa ); +void mgaFlushElts( mgaContextPtr mmesa ) ; + + /* upload texture */ @@ -19,5 +47,12 @@ void mgaDDFinish( GLcontext *ctx ); void mgaDDInitIoctlFuncs( GLcontext *ctx ); +#define FLUSH_BATCH(mmesa) do { \ + if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) \ + fprintf(stderr, "FLUSH_BATCH in %s\n", __FUNCTION__); \ + if (mmesa->vertex_dma_buffer) mgaFlushVertices(mmesa); \ + else if (mmesa->next_elt != mmesa->first_elt) mgaFlushElts(mmesa); \ +} while (0) + #endif diff --git a/xc/lib/GL/mesa/src/drv/mga/mgalib.h b/xc/lib/GL/mesa/src/drv/mga/mgalib.h index 3c4cdbbd8..e00525f7b 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgalib.h +++ b/xc/lib/GL/mesa/src/drv/mga/mgalib.h @@ -101,6 +101,21 @@ typedef void (*mga_interp_func)( GLfloat t, #define MGA_BLEND_ENV_COLOR 0x1 #define MGA_BLEND_MULTITEX 0x2 +struct mga_elt_tab { + void (*emit_unclipped_verts)( struct vertex_buffer *VB ); + + void (*build_tri_verts)( mgaContextPtr mmesa, + struct vertex_buffer *VB, + GLfloat *O, GLuint *elt ); + + void (*interp)( GLfloat t, GLfloat *O, + const GLfloat *I, const GLfloat *J ); + + void (*project_and_emit_verts)( mgaContextPtr mmesa, + const GLfloat *verts, + GLuint *elts, + int nr ); +}; struct mga_context_t { @@ -177,7 +192,7 @@ struct mga_context_t { */ int dirty_cliprects; /* which sets of cliprects are uptodate? */ int draw_buffer; /* which buffer are we rendering to */ - int drawOffset; /* draw buffer address in space */ + unsigned int drawOffset; /* draw buffer address in space */ int read_buffer; int readOffset; int drawX, drawY; /* origin of drawable in draw buffer */ @@ -192,8 +207,8 @@ struct mga_context_t { /* Texture aging and DMA based aging. */ unsigned int texAge[MGA_NR_TEX_HEAPS];/* texture LRU age */ - int dirtyAge; /* buffer age for synchronization */ - int lastSwap; /* throttling runaway apps */ + unsigned int dirtyAge; /* buffer age for synchronization */ + unsigned int lastSwap; /* throttling runaway apps */ @@ -208,6 +223,17 @@ struct mga_context_t { __DRIscreenPrivate *driScreen; mgaScreenPrivate *mgaScreen; drm_mga_sarea_t *sarea; + + + /* New setupdma path + */ + drmBufPtr elt_buf, retained_buf; + GLuint *first_elt, *next_elt; + GLfloat *next_vert; + GLuint next_vert_phys; + GLuint first_vert_phys; + struct mga_elt_tab *elt_tab; + GLfloat device_matrix[16]; }; diff --git a/xc/lib/GL/mesa/src/drv/mga/mgapipeline.h b/xc/lib/GL/mesa/src/drv/mga/mgapipeline.h index d42abddfe..dc0179227 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgapipeline.h +++ b/xc/lib/GL/mesa/src/drv/mga/mgapipeline.h @@ -12,4 +12,7 @@ extern GLboolean mgaDDBuildPrecalcPipeline( GLcontext *ctx ); extern void mgaDDFastPath( struct vertex_buffer *VB ); extern void mgaDDFastPathInit( void ); +extern void mgaDDEltPath( struct vertex_buffer *VB ); +extern void mgaDDEltPathInit( void ); + #endif diff --git a/xc/lib/GL/mesa/src/drv/mga/mgarender.c b/xc/lib/GL/mesa/src/drv/mga/mgarender.c deleted file mode 100644 index 6f406db2d..000000000 --- a/xc/lib/GL/mesa/src/drv/mga/mgarender.c +++ /dev/null @@ -1,334 +0,0 @@ -#include <stdio.h> -#include "mgadd.h" -#include "mgavb.h" -#include "mgadma.h" -#include "mgalib.h" -#include "mgatris.h" -#include "mgastate.h" -#include "xsmesaP.h" -#include "enums.h" - -#define POINT(x) mga_draw_point(&gWin[x], psize) -#define LINE(x,y) mga_draw_line(&gWin[x], &gWin[y], lwidth) -#define TRI(x,y,z) mga_draw_triangle(&gWin[x], &gWin[y], &gWin[z]) - - -/* Direct, and no clipping required. I haven't written the clip funcs - * yet, so this is only useful for the fast path, which does its own - * clipping. - */ -#define RENDER_POINTS( start, count ) \ -do { \ - GLuint e; \ - for(e=start;e<=count;e++) \ - POINT(elt[e]); \ -} while (0) - -#define RENDER_LINE( i1, i ) \ -do { \ - GLuint e1 = elt[i1], e = elt[i]; \ - LINE( e1, e ); \ -} while (0) - - -#define RENDER_TRI( i2, i1, i, pv, parity) \ -do { \ -{ GLuint e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ - if (parity) {GLuint tmp = e2; e2 = e1; e1 = tmp;} \ - TRI(e2, e1, e); \ -}} while (0) - - -#define RENDER_QUAD( i3, i2, i1, i, pv) \ -do { \ - GLuint e3 = elt[i3], e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ - TRI(e3, e2, e); \ - TRI(e2, e1, e); \ -} while (0) - -#define LOCAL_VARS \ - mgaVertexPtr gWin = MGA_DRIVER_DATA(VB)->verts; \ - const GLuint *elt = VB->EltPtr->data; \ - const GLfloat lwidth = VB->ctx->Line.Width; \ - const GLfloat psize = VB->ctx->Point.Size; \ - GLcontext *ctx = VB->ctx; \ - (void) lwidth; (void)psize; (void)ctx; (void) gWin; - - -#define TAG(x) x##_mga_smooth_indirect -#include "render_tmp.h" - - - - -#define RENDER_POINTS( start, count ) \ -do { \ - GLuint e; \ - for(e=start;e<=count;e++) \ - POINT(e); \ -} while (0) - -#define RENDER_LINE( i1, i ) \ -do { \ - LINE( i1, i ); \ -} while (0) - - -#define RENDER_TRI( i2, i1, i, pv, parity) \ -do { \ - GLuint e2 = i2, e1 = i1; \ - if (parity) {GLuint tmp = e2; e2 = e1; e1 = tmp;} \ - TRI(e2, e1, i); \ -} while (0) - - -#define RENDER_QUAD( i3, i2, i1, i, pv) \ -do { \ - TRI(i3, i2, i); \ - TRI(i2, i1, i); \ -} while (0) - -#define LOCAL_VARS \ - mgaVertexPtr gWin = MGA_DRIVER_DATA(VB)->verts; \ - const GLfloat lwidth = VB->ctx->Line.Width; \ - const GLfloat psize = VB->ctx->Point.Size; \ - GLcontext *ctx = VB->ctx; \ - (void) lwidth; (void)psize; (void)ctx; (void) gWin; - -#define TAG(x) x##_mga_smooth_direct -#include "render_tmp.h" - - - - - -/* Vertex array rendering via. the SetupDma function - no clipping required. - */ -#define RENDER_POINTS( start, count ) \ -do { \ - FatalError("Dead code in mgarender.c\n"); \ -} while (0) - -#define RENDER_LINE( i1, i ) \ -do { \ - FatalError("Dead code in mgarender.c\n"); \ -} while (0) - - -#define RENDER_TRI( i2, i1, i, pv, parity) \ -do { \ - GLuint e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ - if (/*parity*/0) {GLuint tmp = e2; e2 = e1; e1 = tmp;} \ - TRI(e2, e1, e); \ -} while (0) - -#define RENDER_QUAD( i3, i2, i1, i, pv) \ -do { \ - GLuint e3 = elt[i3], e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ - TRI(e3, e2, e); \ - TRI(e2, e1, e); \ -} while (0) - -#define LOCAL_VARS \ - mgaVertexBufferPtr mgaVB = MGA_DRIVER_DATA(VB); \ - mgaUI32 phys = mgaVB->vert_phys_start; \ - const GLuint *elt = VB->EltPtr->data; \ - (void) phys; (void) elt; - -#define PRESERVE_VB_DEFS -#undef TRI -#define VERT_ADDR_10( phys, elt ) ( phys + elt * 48 ) -#define TRI( ee0, ee1, ee2 ) \ -{ \ - mgaVB->elt_buf[0] = VERT_ADDR_10(phys, ee0); \ - mgaVB->elt_buf[1] = VERT_ADDR_10(phys, ee1); \ - mgaVB->elt_buf[2] = VERT_ADDR_10(phys, ee2); \ - mgaVB->elt_buf += 3; \ -} -#define TAG(x) x##_mga_elt_10 -#include "render_tmp.h" - - -#define TAG(x) x##_mga_elt_8 -#undef TRI -#define VERT_ADDR_8( phys, elt ) ( phys + elt * 32 ) -#define TRI( ee0, ee1, ee2 ) \ -{ \ - mgaVB->elt_buf[0] = VERT_ADDR_8(phys, ee0); \ - mgaVB->elt_buf[1] = VERT_ADDR_8(phys, ee1); \ - mgaVB->elt_buf[2] = VERT_ADDR_8(phys, ee2); \ - mgaVB->elt_buf += 3; \ -} -#include "render_tmp.h" - - - - -/* Currently only used on the fast path - need a set of render funcs - * for clipped primitives. - */ -void mgaDDRenderElementsDirect( struct vertex_buffer *VB ) -{ - mgaVertexBufferPtr mgaVB = MGA_DRIVER_DATA(VB); - GLcontext *ctx = VB->ctx; - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - GLenum prim = ctx->CVA.elt_mode; - GLuint nr = VB->EltPtr->count; - render_func func = render_tab_mga_smooth_indirect[prim]; - GLuint p = 0; - mgaUI32 *start = mgaVB->elt_buf; - - struct vertex_buffer *saved_vb = ctx->VB; - - if (mmesa->new_state) - mgaDDUpdateHwState( ctx ); - - /* Are we using Setup DMA? - */ - if (start) { - switch (MGA_CONTEXT(ctx)->vertsize) { - case 10: - func = render_tab_mga_elt_10[prim]; - break; - case 8: - func = render_tab_mga_elt_8[prim]; - break; - default: - } - } - - ctx->VB = VB; - - do { - func( VB, 0, nr, 0 ); - } while (ctx->Driver.MultipassFunc && - ctx->Driver.MultipassFunc( VB, ++p )); - - ctx->VB = saved_vb; - - - if (start && nr) { - if (0) - fprintf(stderr, "%d/%d elts\n", nr, mgaVB->elt_buf-start); - mgaSetupDma( start, mgaVB->elt_buf - start ); - mgaVB->elt_buf = mgaVB->vert_buf = 0; - } -} - - -void mgaDDRenderElementsImmediate( struct vertex_buffer *VB ) -{ - GLcontext *ctx = VB->ctx; - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - GLuint nr = VB->EltPtr->count; - render_func *tab = render_tab_mga_smooth_indirect; - GLuint parity = VB->Parity; - GLuint p = 0; - GLuint i, next; - - if (mmesa->new_state) - mgaDDUpdateHwState( ctx ); - - do { - for ( i= VB->CopyStart ; i < nr ; parity = 0, i = next ) - { - GLenum prim = VB->Primitive[i]; - next = VB->NextPrimitive[i]; - tab[prim]( VB, i, next, parity ); - } - } while (ctx->Driver.MultipassFunc && - ctx->Driver.MultipassFunc( VB, ++p )); -} - - -void mgaDDRenderDirect( struct vertex_buffer *VB ) -{ - GLcontext *ctx = VB->ctx; - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - GLuint nr = VB->Count; - render_func *tab = render_tab_mga_smooth_direct; - GLuint parity = VB->Parity; - GLuint p = 0; - GLuint i, next; - - if (mmesa->new_state) - mgaDDUpdateHwState( ctx ); - - do { - for ( i= VB->CopyStart ; i < nr ; parity = 0, i = next ) - { - GLenum prim = VB->Primitive[i]; - next = VB->NextPrimitive[i]; - tab[prim]( VB, i, next, parity ); - } - } while (ctx->Driver.MultipassFunc && - ctx->Driver.MultipassFunc( VB, ++p )); -} - - -static void optimized_render_vb_triangle_mga_smooth_indirect(struct vertex_buffer *VB, - GLuint start, - GLuint count, - GLuint parity) -{ - mgaVertexPtr gWin = MGA_DRIVER_DATA(VB)->verts; - const GLuint *elt = VB->EltPtr->data; - GLcontext *ctx = VB->ctx; - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - - mgaUI32 vertsize = mmesa->vertsize; - - /* We know how many dwords we need so we can allocate all of it - * in one call */ - mgaUI32 *wv = mgaAllocSecondaryBuffer( count * vertsize ); - - int vertex; - - (void)ctx; (void) gWin; (void) parity; - - - for(vertex=start+2;vertex<count;vertex+=3){ - GLuint e2=elt[vertex-2],e1=elt[vertex-1],e=elt[vertex]; - mgaUI32 *src; - - int j; - - if(parity){ - GLuint tmp=e2; - e2=e1; - e1=tmp; - } - - src=&gWin[e2].ui[0]; - - for(j=vertsize;j;j--){ - *wv++=*src++; - } - - src=&gWin[e1].ui[0]; - for(j=vertsize;j;j--){ - *wv++=*src++; - } - - src=&gWin[e].ui[0]; - for(j=vertsize;j;j--){ - *wv++=*src++; - } - } - -} - - -void mgaDDRenderInit() -{ - - render_init_mga_smooth_indirect(); - render_init_mga_smooth_direct(); - render_init_mga_elt_10(); - render_init_mga_elt_8(); - - render_tab_mga_smooth_indirect[GL_TRIANGLES] = - optimized_render_vb_triangle_mga_smooth_indirect; -} - - diff --git a/xc/lib/GL/mesa/src/drv/mga/mgarender.h b/xc/lib/GL/mesa/src/drv/mga/mgarender.h deleted file mode 100644 index c772ac459..000000000 --- a/xc/lib/GL/mesa/src/drv/mga/mgarender.h +++ /dev/null @@ -1,10 +0,0 @@ - -#ifndef _MGA_RENDER_H -#define _MGA_RENDER_H - -extern void mgaDDRenderElementsDirect( struct vertex_buffer *VB ); -extern void mgaDDRenderElementsImmediate( struct vertex_buffer *VB ); -extern void mgaDDRenderDirect( struct vertex_buffer *VB ); -extern void mgaDDRenderInit(); - -#endif diff --git a/xc/lib/GL/mesa/src/drv/mga/mgastate.c b/xc/lib/GL/mesa/src/drv/mga/mgastate.c index ff9063e0b..7a3b82930 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgastate.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgastate.c @@ -16,7 +16,7 @@ #include "mgavb.h" #include "mgatris.h" #include "mgaregs.h" -#include "mga_drm_public.h" +#include "mgabuffers.h" static void mgaUpdateZMode(const GLcontext *ctx) { @@ -60,17 +60,20 @@ static void mgaUpdateZMode(const GLcontext *ctx) static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; } static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; } static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; } @@ -78,6 +81,7 @@ static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA ) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; } @@ -87,6 +91,7 @@ static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname, const GLfloat *param) { if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; } } @@ -95,6 +100,7 @@ static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname, static void mgaDDShadeModel(GLcontext *ctx, GLenum mode) { if (1) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; mgaMsg(8, "mgaDDShadeModel: %x\n", mode); } @@ -103,11 +109,13 @@ static void mgaDDShadeModel(GLcontext *ctx, GLenum mode) static void mgaDDDepthFunc(GLcontext *ctx, GLenum func) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH; } static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH; } @@ -134,6 +142,7 @@ static void mgaUpdateFogAttrib( GLcontext *ctx ) static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_FOG; } @@ -148,10 +157,11 @@ static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) static void mgaUpdateAlphaMode(GLcontext *ctx) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; int a = 0; /* determine source of alpha for blending and testing */ - if ( !ctx->Texture.Enabled || (mmesa->Fallback & MGA_FALLBACK_TEXTURE)) + if ( !ctx->Texture.Enabled ) a |= AC_alphasel_diffused; else { switch (ctx->Texture.Unit[0].EnvMode) { @@ -168,7 +178,7 @@ static void mgaUpdateAlphaMode(GLcontext *ctx) } - /* alpha test control - disabled by default. + /* alpha test control. */ if (ctx->Color.AlphaEnabled) { GLubyte ref = ctx->Color.AlphaRef; @@ -219,13 +229,13 @@ static void mgaUpdateAlphaMode(GLcontext *ctx) case GL_ONE_MINUS_SRC_ALPHA: a |= AC_src_om_src_alpha; break; case GL_DST_ALPHA: - if (0) /*(mgaScreen->Attrib & MGA_PF_HASALPHA)*/ + if (mgaScreen->Attrib & MGA_PF_HASALPHA) a |= AC_src_dst_alpha; else a |= AC_src_one; break; case GL_ONE_MINUS_DST_ALPHA: - if (0) /*(mgaScreen->Attrib & MGA_PF_HASALPHA)*/ + if (mgaScreen->Attrib & MGA_PF_HASALPHA) a |= AC_src_om_dst_alpha; else a |= AC_src_zero; @@ -250,13 +260,13 @@ static void mgaUpdateAlphaMode(GLcontext *ctx) case GL_ONE_MINUS_SRC_COLOR: a |= AC_dst_om_src_color; break; case GL_DST_ALPHA: - if (0) /*(mgaDB->Attrib & MGA_PF_HASALPHA)*/ + if (mgaScreen->Attrib & MGA_PF_HASALPHA) a |= AC_dst_dst_alpha; else a |= AC_dst_one; break; case GL_ONE_MINUS_DST_ALPHA: - if (0) /*(mgaScreen->Attrib & MGA_PF_HASALPHA)*/ + if (mgaScreen->Attrib & MGA_PF_HASALPHA) a |= AC_dst_om_dst_alpha; else a |= AC_dst_zero; @@ -282,50 +292,44 @@ static void mgaUpdateAlphaMode(GLcontext *ctx) * Hardware clipping */ -static void mgaUpdateClipping(const GLcontext *ctx) +void mgaUpdateClipping(const GLcontext *ctx) { -#if 0 - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - __DRIdrawablePrivate *dPriv = mmesa->driDrawable; - int x1,x2,y1,y2; - - if ( ctx->Scissor.Enabled) { - x1 = ctx->Scissor.X; - x2 = ctx->Scissor.X + ctx->Scissor.Width - 1; - y1 = dPriv->Height - ctx->Scissor.Y - ctx->Scissor.Height; - y2 = dPriv->Height - ctx->Scissor.Y - 1; - } else { - x1 = 0; - y1 = 0; - x2 = mgaDB->Width-1; - y2 = mgaDB->Height-1; - } - - if (x1 < 0) x1 = 0; - if (y1 < 0) y1 = 0; - if (x2 >= mgaDB->Width) x2 = mgaDB->Width-1; - if (y2 >= mgaDB->Height) y2 = mgaDB->Height-1; - - if (x1 > x2 || y1 > y2) { - x1 = 0; x2 = 0; - y2 = 0; y1 = 1; - } - - - mmesa->Setup[MGA_CTXREG_CXBNDRY] = (MGA_FIELD(CXB_cxright,x2) | - MGA_FIELD(CXB_cxleft,x1)); - mmesa->Setup[MGA_CTXREG_YTOP] = y1*mgaDB->Pitch; - mmesa->Setup[MGA_CTXREG_YBOT] = y2*mgaDB->Pitch; - + mgaContextPtr mmesa = MGA_CONTEXT(ctx); - mmesa->dirty |= MGA_UPLOAD_CTX; -#endif + if (mmesa->driDrawable) + { + int x1 = mmesa->driDrawable->x + ctx->Scissor.X; + int y1 = mmesa->driDrawable->y + mmesa->driDrawable->h - (ctx->Scissor.Y+ + ctx->Scissor.Height); + int x2 = mmesa->driDrawable->x + ctx->Scissor.X+ctx->Scissor.Width; + int y2 = mmesa->driDrawable->y + mmesa->driDrawable->h - ctx->Scissor.Y; + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 < 0) x2 = 0; + if (y2 < 0) y2 = 0; + + mmesa->scissor_rect.x1 = x1; + mmesa->scissor_rect.y1 = y1; + mmesa->scissor_rect.x2 = x2; + mmesa->scissor_rect.y2 = y2; + + if (MGA_DEBUG&DEBUG_VERBOSE_2D) + fprintf(stderr, "SET SCISSOR %d,%d-%d,%d\n", + mmesa->scissor_rect.x1, + mmesa->scissor_rect.y1, + mmesa->scissor_rect.x2, + mmesa->scissor_rect.y2); + + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; + } } static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h ) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CLIP; } @@ -339,35 +343,6 @@ static void mgaDDDither(GLcontext *ctx, GLboolean enable) } -static GLboolean mgaDDSetBuffer(GLcontext *ctx, GLenum mode ) -{ - mgaContextPtr mmesa = MGA_CONTEXT(ctx); - - mmesa->Fallback &= ~MGA_FALLBACK_BUFFER; - - if (mode == GL_FRONT_LEFT) - { - mmesa->drawOffset = mmesa->mgaScreen->fbOffset; - mmesa->Setup[MGA_CTXREG_DSTORG] = mmesa->mgaScreen->fbOffset; - mmesa->dirty |= MGA_UPLOAD_CTX; - mgaXMesaSetFrontClipRects( mmesa ); - return GL_TRUE; - } - else if (mode == GL_BACK_LEFT) - { - mmesa->drawOffset = mmesa->mgaScreen->backOffset; - mmesa->Setup[MGA_CTXREG_DSTORG] = mmesa->mgaScreen->backOffset; - mmesa->dirty |= MGA_UPLOAD_CTX; - mgaXMesaSetBackClipRects( mmesa ); - return GL_TRUE; - } - else - { - mmesa->Fallback |= MGA_FALLBACK_BUFFER; - return GL_FALSE; - } -} - static void mgaDDSetColor(GLcontext *ctx, @@ -376,7 +351,7 @@ static void mgaDDSetColor(GLcontext *ctx, { mgaContextPtr mmesa = MGA_CONTEXT(ctx); - mmesa->MonoColor = mgaPackColor( mmesa->mgaScreen->fbFormat, + mmesa->MonoColor = mgaPackColor( mmesa->mgaScreen->Attrib, r, g, b, a ); } @@ -387,7 +362,7 @@ static void mgaDDClearColor(GLcontext *ctx, { mgaContextPtr mmesa = MGA_CONTEXT(ctx); - mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->fbFormat, + mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->Attrib, r, g, b, a ); } @@ -426,6 +401,7 @@ static void mgaUpdateCull( GLcontext *ctx ) static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum mode) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CULL; } @@ -461,6 +437,7 @@ static GLboolean mgaDDColorMask(GLcontext *ctx, } if (mmesa->Setup[MGA_CTXREG_PLNWT] != mask) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); mmesa->Setup[MGA_CTXREG_PLNWT] = mask; MGA_CONTEXT(ctx)->new_state |= MGA_NEW_MASK; mmesa->dirty |= MGA_UPLOAD_CTX; @@ -470,6 +447,83 @@ static GLboolean mgaDDColorMask(GLcontext *ctx, } /* ============================================================= + * Polygon stipple + * + * The mga supports a subset of possible 4x4 stipples natively, GL + * wants 32x32. Fortunately stipple is usually a repeating pattern. + */ +static int mgaStipples[16] = { + 0xffff, + 0xa5a5, + 0x5a5a, + 0xa0a0, + 0x5050, + 0x0a0a, + 0x0505, + 0x8020, + 0x0401, + 0x1040, + 0x0208, + 0x0802, + 0x4010, + 0x0104, + 0x2080, + 0x0000 +}; + +static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const GLubyte *m = mask; + GLubyte p[4]; + int i,j,k; + int active = (ctx->Polygon.StippleFlag && ctx->PB->primitive == GL_POLYGON); + GLuint stipple; + + FLUSH_BATCH(mmesa); + ctx->Driver.TriangleCaps |= DD_TRI_STIPPLE; + + if (active) { + mmesa->dirty |= MGA_UPLOAD_CTX; + mmesa->Setup[MGA_CTXREG_DWGCTL] &= ~(0xf<<20); + } + + p[0] = mask[0] & 0xf; p[0] |= p[0] << 4; + p[1] = mask[4] & 0xf; p[1] |= p[1] << 4; + p[2] = mask[8] & 0xf; p[2] |= p[2] << 4; + p[3] = mask[12] & 0xf; p[3] |= p[3] << 4; + + for (k = 0 ; k < 8 ; k++) + for (j = 0 ; j < 4; j++) + for (i = 0 ; i < 4 ; i++) + if (*m++ != p[j]) { + ctx->Driver.TriangleCaps &= ~DD_TRI_STIPPLE; + return; + } + + stipple = ( ((p[0] & 0xf) << 0) | + ((p[1] & 0xf) << 4) | + ((p[2] & 0xf) << 8) | + ((p[3] & 0xf) << 12) ); + + for (i = 0 ; i < 16 ; i++) + if (mgaStipples[i] == stipple) { + mmesa->poly_stipple = i<<20; + break; + } + + if (i == 16) { + ctx->Driver.TriangleCaps &= ~DD_TRI_STIPPLE; + return; + } + + if (active) { + mmesa->Setup[MGA_CTXREG_DWGCTL] &= ~(0xf<<20); + mmesa->Setup[MGA_CTXREG_DWGCTL] |= mmesa->poly_stipple; + } +} + +/* ============================================================= */ @@ -477,15 +531,16 @@ static GLboolean mgaDDColorMask(GLcontext *ctx, static void mgaDDPrintDirty( const char *msg, GLuint state ) { - fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n", + fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n", msg, (unsigned int) state, - (state & MGA_REQUIRE_QUIESCENT) ? "req-quiescent, " : "", + (state & MGA_WAIT_AGE) ? "wait-age, " : "", (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img, " : "", (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img, " : "", (state & MGA_UPLOAD_CTX) ? "upload-ctx, " : "", (state & MGA_UPLOAD_TEX0) ? "upload-tex0, " : "", - (state & MGA_UPLOAD_TEX1) ? "upload-tex1, " : "" + (state & MGA_UPLOAD_TEX1) ? "upload-tex1, " : "", + (state & MGA_UPLOAD_PIPE) ? "upload-pipe, " : "" ); } @@ -494,7 +549,7 @@ static void mgaDDPrintDirty( const char *msg, GLuint state ) */ void mgaEmitHwStateLocked( mgaContextPtr mmesa ) { - if (MGA_DEBUG & MGA_DEBUG_VERBOSE_MSG) + if (MGA_DEBUG & DEBUG_VERBOSE_MSG) mgaDDPrintDirty( "mgaEmitHwStateLocked", mmesa->dirty ); if ((mmesa->dirty & MGA_UPLOAD_TEX0IMAGE) && mmesa->CurrentTexObj[0]) @@ -503,27 +558,34 @@ void mgaEmitHwStateLocked( mgaContextPtr mmesa ) if ((mmesa->dirty & MGA_UPLOAD_TEX1IMAGE) && mmesa->CurrentTexObj[1]) mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[1]); - if (mmesa->dirty & MGA_UPLOAD_CTX) { + if (mmesa->dirty & MGA_UPLOAD_CTX) memcpy( mmesa->sarea->ContextState, mmesa->Setup, sizeof(mmesa->Setup)); - if (mmesa->CurrentTexObj[0]) + if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) memcpy(mmesa->sarea->TexState[0], mmesa->CurrentTexObj[0]->Setup, sizeof(mmesa->sarea->TexState[0])); - if (mmesa->CurrentTexObj[1]) + if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) memcpy(mmesa->sarea->TexState[1], mmesa->CurrentTexObj[1]->Setup, sizeof(mmesa->sarea->TexState[1])); - } - if (mmesa->dirty & MGA_UPLOAD_PIPE) - mmesa->sarea->WarpPipe = mmesa->setupindex & MGA_WARP_T2GZSAF; - + mmesa->sarea->WarpPipe = ((mmesa->setupindex & MGA_WARP_T2GZSAF) | + MGA_ALPHA_BIT | MGA_SPEC_BIT | MGA_FOG_BIT); + + mmesa->sarea->dirty |= mmesa->dirty; - mmesa->dirty = 0; + +#if 0 + mgaPrintSetupFlags("warp pipe", mmesa->sarea->WarpPipe); + fprintf(stderr, "in mgaEmitHwStateLocked: dirty now %x\n", + mmesa->sarea->dirty); +#endif + + mmesa->dirty &= (MGA_UPLOAD_CLIPRECTS|MGA_WAIT_AGE); } @@ -533,29 +595,50 @@ void mgaEmitHwStateLocked( mgaContextPtr mmesa ) static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) { + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + switch(cap) { case GL_ALPHA_TEST: - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; + FLUSH_BATCH( mmesa ); + mmesa->new_state |= MGA_NEW_ALPHA; break; case GL_BLEND: - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; + FLUSH_BATCH( mmesa ); + mmesa->new_state |= MGA_NEW_ALPHA; break; case GL_DEPTH_TEST: - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH; + FLUSH_BATCH( mmesa ); + mmesa->new_state |= MGA_NEW_DEPTH; break; case GL_SCISSOR_TEST: - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CLIP; + FLUSH_BATCH( mmesa ); + mmesa->scissor = state; + mmesa->new_state |= MGA_NEW_CLIP; break; case GL_FOG: - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_FOG; + FLUSH_BATCH( mmesa ); + mmesa->new_state |= MGA_NEW_FOG; break; case GL_CULL_FACE: - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CULL; + FLUSH_BATCH( mmesa ); + mmesa->new_state |= MGA_NEW_CULL; break; case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_3D: - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; + FLUSH_BATCH( mmesa ); + mmesa->new_state |= MGA_NEW_TEXTURE; + break; + case GL_POLYGON_STIPPLE: + if ((ctx->Driver.TriangleCaps & DD_TRI_STIPPLE) && + ctx->PB->primitive == GL_POLYGON) + { + FLUSH_BATCH(mmesa); + mmesa->dirty |= MGA_UPLOAD_CTX; + mmesa->Setup[MGA_CTXREG_DWGCTL] &= ~(0xf<<20); + if (state) + mmesa->Setup[MGA_CTXREG_DWGCTL] |= mmesa->poly_stipple; + } break; default: ; @@ -581,6 +664,7 @@ static void mgaWarpUpdateState( GLcontext *ctx ) { mmesa->warp_pipe = index; mmesa->new_state |= MGA_NEW_WARP; + mmesa->dirty |= MGA_UPLOAD_PIPE; } } @@ -611,21 +695,15 @@ void mgaDDUpdateHwState( GLcontext *ctx ) if (new_state) { - mmesa->new_state = 0; + FLUSH_BATCH( mmesa ); - /* Emit any vertices for the current state. This will also - * push the current state into the sarea. - */ -/* mgaFlushVertices( mmesa ); */ + mmesa->new_state = 0; if (MESA_VERBOSE&VERBOSE_DRIVER) mgaDDPrintState("UpdateHwState", new_state); if (new_state & MGA_NEW_DEPTH) - { mgaUpdateZMode(ctx); - mgaDDInitDepthFuncs(ctx); - } if (new_state & MGA_NEW_ALPHA) mgaUpdateAlphaMode(ctx); @@ -641,8 +719,6 @@ void mgaDDUpdateHwState( GLcontext *ctx ) if (new_state & (MGA_NEW_WARP|MGA_NEW_TEXTURE)) mgaUpdateTextureState(ctx); - - mmesa->new_state = 0; /* tex uploads scribble newstate */ } } @@ -654,8 +730,17 @@ void mgaDDUpdateHwState( GLcontext *ctx ) void mgaDDReducedPrimitiveChange( GLcontext *ctx, GLenum prim ) { - mgaFlushVertices( MGA_CONTEXT(ctx) ); - mgaUpdateCull(ctx); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + FLUSH_BATCH( mmesa ); + mgaUpdateCull(ctx); + + if (ctx->Polygon.StippleFlag && (ctx->Driver.TriangleCaps & DD_TRI_STIPPLE)) + { + mmesa->Setup[MGA_CTXREG_DWGCTL] &= ~(0xf<<20); + if (ctx->PB->primitive == GL_POLYGON) + mmesa->Setup[MGA_CTXREG_DWGCTL] |= mmesa->poly_stipple; + } } @@ -677,10 +762,16 @@ void mgaDDUpdateState( GLcontext *ctx ) /* Have to do this here to detect texture fallbacks in time: */ - if (MGA_CONTEXT(ctx)->new_state & MGA_NEW_TEXTURE) + if (mmesa->new_state & MGA_NEW_TEXTURE) mgaDDUpdateHwState( ctx ); - if (!mmesa->Fallback || mgaglx.noFallback) { + if (0) fprintf(stderr, "fallback %x indirect %x\n", mmesa->Fallback, + mmesa->IndirectTriangles); + + if (!mmesa->Fallback) { + ctx->IndirectTriangles &= ~DD_SW_RASTERIZE; + ctx->IndirectTriangles |= mmesa->IndirectTriangles; + ctx->Driver.PointsFunc=mmesa->PointsFunc; ctx->Driver.LineFunc=mmesa->LineFunc; ctx->Driver.TriangleFunc=mmesa->TriangleFunc; @@ -689,6 +780,60 @@ void mgaDDUpdateState( GLcontext *ctx ) } + +void mgaInitState( mgaContextPtr mmesa ) +{ + mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; + GLcontext *ctx = mmesa->glCtx; + + if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT) { + mmesa->draw_buffer = MGA_BACK; + mmesa->read_buffer = MGA_BACK; + mmesa->drawOffset = mmesa->mgaScreen->backOffset; + mmesa->readOffset = mmesa->mgaScreen->backOffset; + mmesa->Setup[MGA_CTXREG_DSTORG] = mgaScreen->backOffset; + } else { + mmesa->drawOffset = mmesa->mgaScreen->frontOffset; + mmesa->readOffset = mmesa->mgaScreen->frontOffset; + mmesa->draw_buffer = MGA_FRONT; + mmesa->read_buffer = MGA_FRONT; + mmesa->Setup[MGA_CTXREG_DSTORG] = mgaScreen->frontOffset; + } + +/* mmesa->Setup[MGA_CTXREG_MACCESS] = mgaScreen->mAccess; */ +/* mmesa->Setup[MGA_CTXREG_DWGCTL] = ( DC_clipdis_disable | */ +/* (0xC << DC_bop_SHIFT) | */ +/* DC_shftzero_enable | */ +/* DC_zmode_nozcmp | */ +/* DC_atype_zi ); */ + + + mmesa->Setup[MGA_CTXREG_MACCESS] = 0x1; + mmesa->Setup[MGA_CTXREG_DWGCTL] = 0xc4074; + + + mmesa->Setup[MGA_CTXREG_PLNWT] = ~0; + mmesa->Setup[MGA_CTXREG_ALPHACTRL] = ( AC_src_one | + AC_dst_zero | + AC_amode_FCOL | + AC_astipple_disable | + AC_aten_disable | + AC_atmode_noacmp | + AC_alphasel_fromtex ); + + mmesa->Setup[MGA_CTXREG_FOGCOLOR] = + MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F), + (GLubyte)(ctx->Fog.Color[1]*255.0F), + (GLubyte)(ctx->Fog.Color[2]*255.0F)); + + mmesa->Setup[MGA_CTXREG_WFLAG] = 0; + mmesa->Setup[MGA_CTXREG_TDUAL0] = 0; + mmesa->Setup[MGA_CTXREG_TDUAL1] = 0; + mmesa->Setup[MGA_CTXREG_FCOL] = 0; + mmesa->new_state = ~0; +} + + void mgaDDInitStateFuncs( GLcontext *ctx ) { ctx->Driver.UpdateState = mgaDDUpdateState; @@ -710,11 +855,14 @@ void mgaDDInitStateFuncs( GLcontext *ctx ) ctx->Driver.RenderStart = mgaDDUpdateHwState; ctx->Driver.RenderFinish = 0; - ctx->Driver.SetBuffer = mgaDDSetBuffer; + ctx->Driver.SetDrawBuffer = mgaDDSetDrawBuffer; + ctx->Driver.SetReadBuffer = mgaDDSetReadBuffer; ctx->Driver.Color = mgaDDSetColor; ctx->Driver.ClearColor = mgaDDClearColor; ctx->Driver.Dither = mgaDDDither; + ctx->Driver.PolygonStipple = mgaDDPolygonStipple; + ctx->Driver.Index = 0; ctx->Driver.ClearIndex = 0; ctx->Driver.IndexMask = 0; diff --git a/xc/lib/GL/mesa/src/drv/mga/mgatex.c b/xc/lib/GL/mesa/src/drv/mga/mgatex.c index be7ad6018..eafccbaa2 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgatex.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgatex.c @@ -47,22 +47,25 @@ * to it. */ static void mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t ) { - int i; if ( !t ) return; /* free the texture memory */ - mmFreeMem( t->MemBlock ); + if (t->MemBlock) { + mmFreeMem( t->MemBlock ); + t->MemBlock = 0; + + if (t->age > mmesa->dirtyAge) + mmesa->dirtyAge = t->age; + } /* free mesa's link */ - t->tObj->DriverData = NULL; + if (t->tObj) + t->tObj->DriverData = NULL; /* see if it was the driver's current object */ - for ( i = 0 ; i < 2 ; i++ ) { - if ( mmesa->CurrentTexObj[i] == t ) { - mmesa->CurrentTexObj[i] = NULL; - } - } + if (t->bound) + mmesa->CurrentTexObj[t->bound - 1] = 0; remove_from_list(t); free( t ); @@ -73,6 +76,9 @@ static void mgaSwapOutTexObj(mgaContextPtr mmesa, mgaTextureObjectPtr t) if (t->MemBlock) { mmFreeMem(t->MemBlock); t->MemBlock = 0; + + if (t->age > mmesa->dirtyAge) + mmesa->dirtyAge = t->age; } t->dirty_images = ~0; @@ -80,22 +86,76 @@ static void mgaSwapOutTexObj(mgaContextPtr mmesa, mgaTextureObjectPtr t) } -void mgaResetGlobalLRU( mgaContextPtr mmesa ) +static void mgaPrintLocalLRU( mgaContextPtr mmesa, int heap ) +{ + mgaTextureObjectPtr t; + int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]); + + fprintf(stderr, "\nLocal LRU, heap %d:\n", heap); + + foreach( t, &(mmesa->TexObjList[heap]) ) { + if (!t->tObj) + fprintf(stderr, "Placeholder %d at %x sz %x\n", + t->MemBlock->ofs / sz, + t->MemBlock->ofs, + t->MemBlock->size); + else + fprintf(stderr, "Texture (bound %d) at %x sz %x\n", + t->bound, + t->MemBlock->ofs, + t->MemBlock->size); + + } + + fprintf(stderr, "\n\n"); +} + +static void mgaPrintGlobalLRU( mgaContextPtr mmesa, int heap ) +{ + int i, j; + drm_mga_tex_region_t *list = mmesa->sarea->texList[heap]; + + fprintf(stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list); + + for (i = 0, j = MGA_NR_TEX_REGIONS ; i < MGA_NR_TEX_REGIONS ; i++) { + fprintf(stderr, "list[%d] age %d next %d prev %d\n", + j, list[j].age, list[j].next, list[j].prev); + j = list[j].next; + if (j == MGA_NR_TEX_REGIONS) break; + } + + if (j != MGA_NR_TEX_REGIONS) { + fprintf(stderr, "Loop detected in global LRU\n\n\n"); + for (i = 0 ; i < MGA_NR_TEX_REGIONS ; i++) { + fprintf(stderr, "list[%d] age %d next %d prev %d\n", + i, list[i].age, list[i].next, list[i].prev); + } + } + + fprintf(stderr, "\n\n"); +} + + +static void mgaResetGlobalLRU( mgaContextPtr mmesa, GLuint heap ) { - mgaTexRegion *list = mmesa->sarea->texList; - int sz = 1 << mmesa->mgaScreen->logTextureGranularity; + drm_mga_tex_region_t *list = mmesa->sarea->texList[heap]; + int sz = 1 << mmesa->mgaScreen->logTextureGranularity[heap]; int i; + mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap]; + + if (0) fprintf(stderr, "mgaResetGlobalLRU %d\n", (int)heap); + /* (Re)initialize the global circular LRU list. The last element * in the array (MGA_NR_TEX_REGIONS) is the sentinal. Keeping it * at the end of the array allows it to be addressed rationally * when looking up objects at a particular location in texture * memory. */ - for (i = 0 ; (i+1) * sz < mmesa->mgaScreen->textureSize ; i++) { + for (i = 0 ; (i+1) * sz <= mmesa->mgaScreen->textureSize[heap] ; i++) { list[i].prev = i-1; list[i].next = i+1; - list[i].age = 0; + list[i].age = mmesa->sarea->texAge[heap]; } i--; @@ -104,30 +164,41 @@ void mgaResetGlobalLRU( mgaContextPtr mmesa ) list[i].next = MGA_NR_TEX_REGIONS; list[MGA_NR_TEX_REGIONS].prev = i; list[MGA_NR_TEX_REGIONS].next = 0; - mmesa->sarea->texAge = 0; + } static void mgaUpdateTexLRU( mgaContextPtr mmesa, mgaTextureObjectPtr t ) { int i; - int logsz = mmesa->mgaScreen->logTextureGranularity; + int heap = t->heap; + int logsz = mmesa->mgaScreen->logTextureGranularity[heap]; int start = t->MemBlock->ofs >> logsz; int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz; - mgaTexRegion *list = mmesa->sarea->texList; + drm_mga_tex_region_t *list = mmesa->sarea->texList[heap]; - mmesa->texAge = ++mmesa->sarea->texAge; + mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap]; + + if (!t->MemBlock) { + fprintf(stderr, "no memblock\n\n"); + return; + } /* Update our local LRU */ - move_to_head( &(mmesa->TexObjList), t ); + move_to_head( &(mmesa->TexObjList[heap]), t ); + + + if (0) + fprintf(stderr, "mgaUpdateTexLRU heap %d list %p\n", heap, list); + /* Update the global LRU */ for (i = start ; i <= end ; i++) { list[i].in_use = 1; - list[i].age = mmesa->texAge; + list[i].age = mmesa->texAge[heap]; /* remove_from_list(i) */ @@ -141,8 +212,12 @@ static void mgaUpdateTexLRU( mgaContextPtr mmesa, mgaTextureObjectPtr t ) list[(unsigned)list[MGA_NR_TEX_REGIONS].next].prev = i; list[MGA_NR_TEX_REGIONS].next = i; } -} + if (0) { + mgaPrintGlobalLRU(mmesa, t->heap); + mgaPrintLocalLRU(mmesa, t->heap); + } +} /* Called for every shared texture region which has increased in age * since we last held the lock. @@ -151,23 +226,29 @@ static void mgaUpdateTexLRU( mgaContextPtr mmesa, mgaTextureObjectPtr t ) * and pushes a placeholder texture onto the LRU list to represent * the other client's textures. */ -void mgaTexturesGone( mgaContextPtr mmesa, - GLuint offset, - GLuint size, - GLuint in_use ) +static void mgaTexturesGone( mgaContextPtr mmesa, + GLuint heap, + GLuint offset, + GLuint size, + GLuint in_use ) { mgaTextureObjectPtr t, tmp; - - foreach_s ( t, tmp, &mmesa->TexObjList ) { + + + + foreach_s ( t, tmp, &(mmesa->TexObjList[heap]) ) { if (t->MemBlock->ofs >= offset + size || t->MemBlock->ofs + t->MemBlock->size <= offset) continue; + + + /* It overlaps - kick it off. Need to hold onto the currently bound * objects, however. */ - if (t == mmesa->CurrentTexObj[0] || t == mmesa->CurrentTexObj[1]) + if (t->bound) mgaSwapOutTexObj( mmesa, t ); else mgaDestroyTexObj( mmesa, t ); @@ -178,12 +259,54 @@ void mgaTexturesGone( mgaContextPtr mmesa, t = (mgaTextureObjectPtr) calloc(1,sizeof(*t)); if (!t) return; - t->MemBlock = mmAllocMem( mmesa->texHeap, size, 0, offset); - insert_at_head( &mmesa->TexObjList, t ); + t->heap = heap; + t->MemBlock = mmAllocMem( mmesa->texHeap[heap], size, 0, offset); + if (!t->MemBlock) { + fprintf(stderr, "Couldn't alloc placeholder sz %x ofs %x\n", + (int)size, (int)offset); + mmDumpMemInfo( mmesa->texHeap[heap]); + return; + } + insert_at_head( &(mmesa->TexObjList[heap]), t ); } } +void mgaAgeTextures( mgaContextPtr mmesa, int heap ) +{ + drm_mga_sarea_t *sarea = mmesa->sarea; + int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]); + int idx, nr = 0; + + /* Have to go right round from the back to ensure stuff ends up + * LRU in our local list... Fix with a cursor pointer. + */ + for (idx = sarea->texList[heap][MGA_NR_TEX_REGIONS].prev ; + idx != MGA_NR_TEX_REGIONS && nr < MGA_NR_TEX_REGIONS ; + idx = sarea->texList[heap][idx].prev, nr++) + { + if (sarea->texList[heap][idx].age > mmesa->texAge[heap]) { + mgaTexturesGone(mmesa, heap, idx * sz, sz, 1); + } + } + + if (nr == MGA_NR_TEX_REGIONS) { + mgaTexturesGone(mmesa, heap, 0, + mmesa->mgaScreen->textureSize[heap], 0); + mgaResetGlobalLRU( mmesa, heap ); + } + + + if (0) { + mgaPrintGlobalLRU( mmesa, heap ); + mgaPrintLocalLRU( mmesa, heap ); + } + + mmesa->texAge[heap] = sarea->texAge[heap]; + mmesa->dirty |= MGA_UPLOAD_TEX0IMAGE | MGA_UPLOAD_TEX1IMAGE; +} + + /* * mgaSetTexWrappings */ @@ -281,22 +404,22 @@ static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4]) { /* - * mgaUploadSubImage + * mgaUploadSubImageLocked * * Perform an iload based update of a resident buffer. This is used for * both initial loading of the entire image, and texSubImage updates. * * Performed with the hardware lock held. */ -static void mgaUploadSubImage( mgaContextPtr mmesa, - mgaTextureObjectPtr t, - int level, - int x, int y, int width, int height ) { +static void mgaUploadSubImageLocked( mgaContextPtr mmesa, + mgaTextureObjectPtr t, + int level, + int x, int y, int width, int height ) { int x2; int dwords; - int dstorg; + int offset; struct gl_texture_image *image; - int texelBytes, texelsPerDword, texelMaccess; + int texelBytes, texelsPerDword, texelMaccess, length; if ( level < 0 || level >= MGA_TEX_MAXLEVELS ) { mgaMsg( 1, "mgaUploadSubImage: bad level: %i\n", level ); @@ -310,15 +433,9 @@ static void mgaUploadSubImage( mgaContextPtr mmesa, } /* find the proper destination offset for this level */ - dstorg = (mmesa->mgaScreen->textureOffset + t->MemBlock->ofs + + offset = (t->MemBlock->ofs + t->offsets[level]); - /* turn on PCI/AGP if needed - if ( textureHeapPhysical ) { - dstorg |= 1 | mgaglx.use_agp; - } - */ - texelBytes = t->texelBytes; switch( texelBytes ) { case 1: @@ -363,7 +480,7 @@ static void mgaUploadSubImage( mgaContextPtr mmesa, x = (x + (texelsPerDword-1)) & ~(texelsPerDword-1); width = x2 - x; } - + /* we may not be able to upload the entire texture in one batch due to register limits or dma buffer limits. Recursively split it up. */ @@ -374,7 +491,8 @@ static void mgaUploadSubImage( mgaContextPtr mmesa, } mgaMsg(10, "mgaUploadSubImage: recursively subdividing\n" ); - mgaUploadSubImage( mmesa, t, level, x, y, width, height >> 1 ); + mgaUploadSubImageLocked( mmesa, t, level, x, y, + width, height >> 1 ); y += ( height >> 1 ); height -= ( height >> 1 ); } @@ -385,31 +503,50 @@ static void mgaUploadSubImage( mgaContextPtr mmesa, /* bump the performance counter */ mgaglx.c_textureSwaps += ( dwords << 2 ); - -#if 0 - - /* fill in the secondary buffer with properly converted texels - from the mesa buffer */ - mgaConvertTexture( dest, texelBytes, image, x, y, width, height ); - - /* send the secondary data */ - mgaSecondaryDma( TT_BLIT, dest, dwords ); -#endif - + length = dwords * 4; + + /* Fill in the secondary buffer with properly converted texels + * from the mesa buffer. */ + if(t->heap == MGA_CARD_HEAP) { + mgaGetILoadBufferLocked( mmesa ); + mgaConvertTexture( (mgaUI32 *)mmesa->iload_buffer->address, + texelBytes, image, x, y, width, height ); + if(length < 64) length = 64; + mgaMsg(10, "TexelBytes : %d, offset: %d, length : %d\n", + texelBytes, + mmesa->mgaScreen->textureOffset[t->heap] + + offset + + y * width * 4/texelsPerDword, + length); + + mgaFireILoadLocked( mmesa, + mmesa->mgaScreen->textureOffset[t->heap] + + offset + + y * width * 4/texelsPerDword, + length); + } else { + /* This works, is slower for uploads to card space and needs + * additional synchronization with the dma stream. + */ + mgaConvertTexture( (mgaUI32 *) + (mmesa->mgaScreen->texVirtual[t->heap] + + offset + + y * width * 4/texelsPerDword), + texelBytes, image, x, y, width, height ); + } } - static void mgaUploadTexLevel( mgaContextPtr mmesa, - mgaTextureObjectPtr t, - int l ) + mgaTextureObjectPtr t, + int l ) { - mgaUploadSubImage( mmesa, - t, - l, - 0, 0, - t->tObj->Image[l]->Width, - t->tObj->Image[l]->Height); + mgaUploadSubImageLocked( mmesa, + t, + l, + 0, 0, + t->tObj->Image[l]->Width, + t->tObj->Image[l]->Height); } @@ -527,9 +664,11 @@ static void mgaCreateTexObj(mgaContextPtr mmesa, struct gl_texture_object *tObj) /* fill in our mga texture object */ t->tObj = tObj; t->ctx = mmesa; + t->age = 0; + t->bound = 0; - insert_at_tail(&(mmesa->TexObjList), t); + insert_at_tail(&(mmesa->SwappedOut), t); t->MemBlock = 0; @@ -596,34 +735,61 @@ static void mgaCreateTexObj(mgaContextPtr mmesa, struct gl_texture_object *tObj) tObj->DriverData = t; } +static void mgaMigrateTexture( mgaContextPtr mmesa, mgaTextureObjectPtr t ) +{ + /* NOT DONE */ +} -int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t ) +static int mgaChooseTexHeap( mgaContextPtr mmesa, mgaTextureObjectPtr t ) { + return 0; +} + +int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t ) +{ + int heap; int i; int ofs; mgaglx.c_textureSwaps++; + heap = t->heap = mgaChooseTexHeap( mmesa, t ); + /* Do we need to eject LRU texture objects? */ if (!t->MemBlock) { while (1) { - t->MemBlock = mmAllocMem( mmesa->texHeap, t->totalSize, 12, 0 ); + mgaTextureObjectPtr tmp = mmesa->TexObjList[heap].prev; + + t->MemBlock = mmAllocMem( mmesa->texHeap[heap], + t->totalSize, + 6, 0 ); if (t->MemBlock) break; - if (mmesa->TexObjList.prev == &(mmesa->TexObjList)) { - fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize); - mmDumpMemInfo( mmesa->texHeap ); + if (mmesa->TexObjList[heap].prev->bound) { + fprintf(stderr, + "Hit bound texture in upload\n"); return -1; } - mgaDestroyTexObj( mmesa, mmesa->TexObjList.prev ); + if (mmesa->TexObjList[heap].prev == + &(mmesa->TexObjList[heap])) + { + fprintf(stderr, "Failed to upload texture, " + "sz %d\n", t->totalSize); + mmDumpMemInfo( mmesa->texHeap[heap] ); + return -1; + } + + mgaDestroyTexObj( mmesa, tmp ); } - ofs = t->MemBlock->ofs; + ofs = t->MemBlock->ofs + + mmesa->mgaScreen->textureOffset[heap] + ; t->Setup[MGA_TEXREG_ORG] = ofs; t->Setup[MGA_TEXREG_ORG1] = ofs + t->offsets[1]; @@ -638,8 +804,16 @@ int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t ) */ mgaUpdateTexLRU( mmesa, t ); + + if (MGA_DEBUG&DEBUG_VERBOSE_LRU) + fprintf(stderr, "dispatch age: %d age freed memory: %d\n", + GET_DISPATCH_AGE(mmesa), mmesa->dirtyAge); + + if (mmesa->dirtyAge >= GET_DISPATCH_AGE(mmesa)) + mgaWaitAgeLocked( mmesa, mmesa->dirtyAge ); + if (t->dirty_images) { - if (MGA_DEBUG & MGA_DEBUG_VERBOSE_MSG) + if (MGA_DEBUG&DEBUG_VERBOSE_LRU) fprintf(stderr, "*"); for (i = 0 ; i <= t->lastLevel ; i++) @@ -692,12 +866,10 @@ static void mgaUpdateTextureEnvG200( GLcontext *ctx ) } } -/* I don't have the alpha values correct yet: - */ static void mgaUpdateTextureStage( GLcontext *ctx, int unit ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - mgaUI32 *reg = &mmesa->Setup[MGA_CTXREG_TDUAL0 + unit]; + GLuint *reg = &mmesa->Setup[MGA_CTXREG_TDUAL0 + unit]; GLuint source = mmesa->tmu_source[unit]; struct gl_texture_object *tObj = ctx->Texture.Unit[source].Current; @@ -725,13 +897,13 @@ static void mgaUpdateTextureStage( GLcontext *ctx, int unit ) *reg = ( TD0_color_arg2_diffuse | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | - TD0_alpha_sel_arg1); + TD0_alpha_sel_mul); else *reg = ( TD0_color_arg2_prevstage | TD0_color_alpha_prevstage | TD0_color_sel_mul | TD0_alpha_arg2_prevstage | - TD0_alpha_sel_arg1); + TD0_alpha_sel_mul); break; case GL_DECAL: *reg = (TD0_color_arg2_fcol | @@ -751,20 +923,49 @@ static void mgaUpdateTextureStage( GLcontext *ctx, int unit ) TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_diffuse | - TD0_alpha_sel_arg1); + TD0_alpha_sel_add); else *reg = ( TD0_color_arg2_prevstage | TD0_color_alpha_prevstage | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | - TD0_alpha_sel_arg1); + TD0_alpha_sel_add); break; case GL_BLEND: - /* Use a multipass mechanism to do this: + if (0) + fprintf(stderr, "GL_BLEND unit %d flags %x\n", unit, + mmesa->blend_flags); + + if (mmesa->blend_flags) + mmesa->Fallback |= MGA_FALLBACK_TEXTURE; + return; + + /* Do singletexture GL_BLEND with 'all ones' env-color + * by using both texture units. Multitexture gl_blend + * is a fallback. */ - mmesa->Fallback |= MGA_FALLBACK_TEXTURE; + if (unit == 0) { + /* Part 1: R1 = Rf ( 1 - Rt ) + * A1 = Af At + */ + *reg = ( TD0_color_arg2_diffuse | + TD0_color_arg1_inv_enable | + TD0_color_sel_mul | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg1); + } else { + /* Part 2: R2 = R1 + Rt + * A2 = A1 + */ + *reg = ( TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + } + break; default: } @@ -782,9 +983,8 @@ static void mgaUpdateTextureObject( GLcontext *ctx, int unit ) { mgaMsg(15,"mgaUpdateTextureState %d\n", unit); /* disable texturing until it is known to be good */ - mmesa->Setup[MGA_CTXREG_DWGCTL] = - (( mmesa->Setup[MGA_CTXREG_DWGCTL] & DC_opcod_MASK ) | - DC_opcod_trap); + mmesa->Setup[MGA_CTXREG_DWGCTL] &= DC_opcod_MASK; + mmesa->Setup[MGA_CTXREG_DWGCTL] |= DC_opcod_trap; enabled = (ctx->Texture.Enabled>>(source*4))&TEXTURE0_ANY; if (enabled != TEXTURE0_2D) { @@ -797,6 +997,8 @@ static void mgaUpdateTextureObject( GLcontext *ctx, int unit ) { if ( !tObj || tObj != ctx->Texture.Unit[source].CurrentD[2] ) return; + +/* fprintf(stderr, "unit %d: %d\n", unit, tObj->Name); */ /* if the texture object doesn't exist at all (never used or swapped out), create it now, uploading all texture images */ @@ -804,7 +1006,6 @@ static void mgaUpdateTextureObject( GLcontext *ctx, int unit ) { if ( !tObj->DriverData ) { /* clear the current pointer so that texture object can be swapped out if necessary to make room */ - mmesa->CurrentTexObj[source] = NULL; mgaCreateTexObj( mmesa, tObj ); if ( !tObj->DriverData ) { @@ -815,9 +1016,8 @@ static void mgaUpdateTextureObject( GLcontext *ctx, int unit ) { } /* we definately have a valid texture now */ - mmesa->Setup[MGA_CTXREG_DWGCTL] = - (( mmesa->Setup[MGA_CTXREG_DWGCTL] & DC_opcod_MASK ) | - DC_opcod_texture_trap); + mmesa->Setup[MGA_CTXREG_DWGCTL] &= DC_opcod_MASK; + mmesa->Setup[MGA_CTXREG_DWGCTL] |= DC_opcod_texture_trap; t = (mgaTextureObjectPtr)tObj->DriverData; @@ -825,6 +1025,11 @@ static void mgaUpdateTextureObject( GLcontext *ctx, int unit ) { mmesa->dirty |= (MGA_UPLOAD_TEX0IMAGE << unit); mmesa->CurrentTexObj[unit] = t; + t->bound = unit+1; + + if (t->MemBlock) + mgaUpdateTexLRU( mmesa, t ); + t->Setup[MGA_TEXREG_CTL2] &= ~TMC_dualtex_enable; if (ctx->Texture.Enabled == (TEXTURE0_2D|TEXTURE1_2D)) @@ -848,23 +1053,31 @@ void mgaUpdateTextureState( GLcontext *ctx ) mgaContextPtr mmesa = MGA_CONTEXT( ctx ); mmesa->Fallback &= ~MGA_FALLBACK_TEXTURE; + if (mmesa->CurrentTexObj[0]) mmesa->CurrentTexObj[0]->bound = 0; + if (mmesa->CurrentTexObj[1]) mmesa->CurrentTexObj[1]->bound = 0; + mmesa->CurrentTexObj[0] = 0; + mmesa->CurrentTexObj[1] = 0; + if (MGA_IS_G400(mmesa)) { mgaUpdateTextureObject( ctx, 0 ); mgaUpdateTextureStage( ctx, 0 ); - mmesa->Setup[MGA_CTXREG_TDUAL1] = mmesa->Setup[MGA_CTXREG_TDUAL0]; + mmesa->Setup[MGA_CTXREG_TDUAL1] = + mmesa->Setup[MGA_CTXREG_TDUAL0]; if (mmesa->multitex) { mgaUpdateTextureObject( ctx, 1 ); mgaUpdateTextureStage( ctx, 1 ); } + + mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1; } else { mgaUpdateTextureObject( ctx, 0 ); - mgaUpdateTextureEnvG200( ctx ); + mgaUpdateTextureEnvG200( ctx ); } /* schedule the register writes */ - mmesa->dirty |= MGA_UPLOAD_CTX; + mmesa->dirty |= MGA_UPLOAD_CTX | MGA_UPLOAD_TEX0; } @@ -880,14 +1093,57 @@ Driver functions called directly from mesa /* * mgaTexEnv */ -void mgaTexEnv( GLcontext *ctx, GLenum pname, const GLfloat *param ) { +void mgaTexEnv( GLcontext *ctx, GLenum pname, const GLfloat *param ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); mgaMsg( 10, "mgaTexEnv( %i )\n", pname ); + if (pname == GL_TEXTURE_ENV_MODE) { /* force the texture state to be updated */ - MGA_CONTEXT(ctx)->CurrentTexObj[0] = 0; + FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; } + else if (pname == GL_TEXTURE_ENV_COLOR) + { + struct gl_texture_unit *texUnit = + &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + GLfloat *fc = texUnit->EnvColor; + GLubyte c[4]; + GLuint col; + + + c[0] = fc[0]; + c[1] = fc[1]; + c[2] = fc[2]; + c[3] = fc[3]; + + /* No alpha at 16bpp? + */ + col = mgaPackColor( mmesa->mgaScreen->Attrib, + c[0], c[1], c[2], c[3] ); + + mmesa->envcolor = (c[3]<<24) | (c[0]<<16) | (c[1]<<8) | (c[2]); + + if (mmesa->Setup[MGA_CTXREG_FCOL] != col) { + FLUSH_BATCH(mmesa); + mmesa->Setup[MGA_CTXREG_FCOL] = col; + mmesa->dirty |= MGA_UPLOAD_CTX; + + mmesa->blend_flags &= ~MGA_BLEND_ENV_COLOR; + + /* Actually just require all four components to be + * equal. This permits a single-pass GL_BLEND. + * + * More complex multitexture/multipass fallbacks + * for blend can be done later. + */ + if (mmesa->envcolor != 0x0 && + mmesa->envcolor != 0xffffffff) + mmesa->blend_flags |= MGA_BLEND_ENV_COLOR; + } + } + } /* @@ -907,6 +1163,7 @@ void mgaTexImage( GLcontext *ctx, GLenum target, mgaUpdateTextureState time. */ t = (mgaTextureObjectPtr) tObj->DriverData; if ( t ) { + if (t->bound) FLUSH_BATCH(mmesa); /* if this is the current object, it will force an update */ mgaDestroyTexObj( mmesa, t ); mmesa->new_state |= MGA_NEW_TEXTURE; @@ -936,6 +1193,7 @@ void mgaTexSubImage( GLcontext *ctx, GLenum target, mgaUpdateTextureState time. */ t = (mgaTextureObjectPtr) tObj->DriverData; if ( t ) { + if (t->bound) FLUSH_BATCH(mmesa); /* if this is the current object, it will force an update */ mgaDestroyTexObj( mmesa, t ); mmesa->new_state |= MGA_NEW_TEXTURE; @@ -956,7 +1214,9 @@ void mgaTexSubImage( GLcontext *ctx, GLenum target, */ void mgaTexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, - GLenum pname, const GLfloat *params ) { + GLenum pname, const GLfloat *params ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); mgaTextureObjectPtr t; mgaMsg( 10, "mgaTexParameter( %p, %i )\n", tObj, pname ); @@ -973,52 +1233,68 @@ void mgaTexParameter( GLcontext *ctx, GLenum target, switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: + if (t->bound) FLUSH_BATCH(mmesa); mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: + if (t->bound) FLUSH_BATCH(mmesa); mgaSetTexWrapping(t,tObj->WrapS,tObj->WrapT); break; case GL_TEXTURE_BORDER_COLOR: + if (t->bound) FLUSH_BATCH(mmesa); mgaSetTexBorderColor(t,tObj->BorderColor); break; default: return; } - /* force the texture state to be updated */ - MGA_CONTEXT(ctx)->CurrentTexObj[0] = NULL; - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; + + mmesa->new_state |= MGA_NEW_TEXTURE; } /* * mgaBindTexture */ void mgaBindTexture( GLcontext *ctx, GLenum target, - struct gl_texture_object *tObj ) { + struct gl_texture_object *tObj ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); mgaMsg( 10, "mgaBindTexture( %p )\n", tObj ); - + + FLUSH_BATCH(mmesa); + + if (mmesa->CurrentTexObj[ctx->Texture.CurrentUnit]) { + mmesa->CurrentTexObj[ctx->Texture.CurrentUnit]->bound = 0; + mmesa->CurrentTexObj[ctx->Texture.CurrentUnit] = 0; + } + /* force the texture state to be updated */ - MGA_CONTEXT(ctx)->CurrentTexObj[0] = NULL; MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; } /* * mgaDeleteTexture */ -void mgaDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) { +void mgaDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + mgaTextureObjectPtr t = (mgaTextureObjectPtr)tObj->DriverData; mgaMsg( 10, "mgaDeleteTexture( %p )\n", tObj ); - /* delete our driver data */ - if ( tObj->DriverData ) { - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - mgaDestroyTexObj( mmesa, - (mgaTextureObjectPtr)(tObj->DriverData) ); + if ( t ) { + if (t->bound) { + FLUSH_BATCH(mmesa); + mmesa->CurrentTexObj[t->bound-1] = 0; + mmesa->new_state |= MGA_NEW_TEXTURE; + } + + mgaDestroyTexObj( mmesa, t ); mmesa->new_state |= MGA_NEW_TEXTURE; } } diff --git a/xc/lib/GL/mesa/src/drv/mga/mgatris.c b/xc/lib/GL/mesa/src/drv/mga/mgatris.c index bd8ef083f..387a79f3e 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgatris.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgatris.c @@ -27,6 +27,7 @@ #include <stdio.h> #include <math.h> +#include "types.h" #include "vb.h" #include "pipeline.h" @@ -122,34 +123,14 @@ void mgaDDTrifuncInit() init_twoside_offset(); init_twoside_offset_flat(); - /* Hmmm... - */ - for (i = 0 ; i < 0x20 ; i++) { - if (i & ~MGA_FLAT_BIT) { - points_tab[i] = points_tab[i&MGA_FLAT_BIT]; - line_tab[i] = line_tab[i&MGA_FLAT_BIT]; - } - } - for (i = 0 ; i < 0x20 ; i++) - if ((i & (MGA_NODRAW_BIT|MGA_FALLBACK_BIT)) == MGA_NODRAW_BIT || - mgaglx.nullprims) + if ((i & (MGA_NODRAW_BIT|MGA_FALLBACK_BIT)) == MGA_NODRAW_BIT) { quad_tab[i] = mga_null_quad; tri_tab[i] = mga_null_triangle; line_tab[i] = mga_null_line; points_tab[i] = mga_null_points; } - - if (mgaglx.noFallback) { - for (i = 0 ; i < 0x10 ; i++) { - points_tab[i|MGA_FALLBACK_BIT] = points_tab[i]; - line_tab[i|MGA_FALLBACK_BIT] = line_tab[i]; - tri_tab[i|MGA_FALLBACK_BIT] = tri_tab[i]; - quad_tab[i|MGA_FALLBACK_BIT] = quad_tab[i]; - } - } - } @@ -162,50 +143,61 @@ void mgaDDChooseRenderState( GLcontext *ctx ) mgaContextPtr mmesa = MGA_CONTEXT( ctx ); GLuint flags = ctx->TriangleCaps; - ctx->IndirectTriangles &= ~DD_SW_RASTERIZE; + if (mmesa->Fallback) + return; + + mmesa->IndirectTriangles = 0; if (flags) { GLuint ind = 0; GLuint shared = 0; - GLuint fallback = MGA_FALLBACK_BIT; - - if (mgaglx.noFallback) fallback = 0; if (flags & DD_Z_NEVER) shared |= MGA_NODRAW_BIT; if (flags & DD_FLATSHADE) shared |= MGA_FLAT_BIT; - if (flags & DD_MULTIDRAW) shared |= fallback; - if (flags & (DD_SELECT|DD_FEEDBACK)) shared |= MGA_FALLBACK_BIT; + if (flags & (DD_MULTIDRAW| + DD_SELECT| + DD_FEEDBACK)) shared |= MGA_FALLBACK_BIT; if (flags & DD_STENCIL) shared |= MGA_FALLBACK_BIT; ind = shared; +#if 0 if (flags & DD_POINT_SMOOTH) ind |= MGA_ANTIALIAS_BIT; - if (flags & DD_POINT_ATTEN) ind |= fallback; +#else + if (flags & DD_POINT_SMOOTH) ind |= MGA_FALLBACK_BIT; +#endif mmesa->renderindex = ind; mmesa->PointsFunc = points_tab[ind]; if (ind & MGA_FALLBACK_BIT) - ctx->IndirectTriangles |= DD_POINT_SW_RASTERIZE; + mmesa->IndirectTriangles |= DD_POINT_SW_RASTERIZE; ind = shared; +#if 0 if (flags & DD_LINE_SMOOTH) ind |= MGA_ANTIALIAS_BIT; - if (flags & DD_LINE_STIPPLE) ind |= fallback; +#else + if (flags & DD_LINE_SMOOTH) ind |= MGA_FALLBACK_BIT; +#endif + if (flags & DD_LINE_STIPPLE) ind |= MGA_FALLBACK_BIT; mmesa->renderindex |= ind; mmesa->LineFunc = line_tab[ind]; if (ind & MGA_FALLBACK_BIT) - ctx->IndirectTriangles |= DD_LINE_SW_RASTERIZE; + mmesa->IndirectTriangles |= DD_LINE_SW_RASTERIZE; ind = shared; if (flags & DD_TRI_SMOOTH) ind |= MGA_ANTIALIAS_BIT; if (flags & DD_TRI_OFFSET) ind |= MGA_OFFSET_BIT; if (flags & DD_TRI_LIGHT_TWOSIDE) ind |= MGA_TWOSIDE_BIT; - if (flags & (DD_TRI_UNFILLED|DD_TRI_STIPPLE)) ind |= fallback; + if (flags & DD_TRI_UNFILLED) ind |= MGA_FALLBACK_BIT; + if ((flags & DD_TRI_STIPPLE) && + (ctx->IndirectTriangles & DD_TRI_STIPPLE)) ind |= MGA_FALLBACK_BIT; mmesa->renderindex |= ind; mmesa->TriangleFunc = tri_tab[ind]; mmesa->QuadFunc = quad_tab[ind]; if (ind & MGA_FALLBACK_BIT) - ctx->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | DD_QUAD_SW_RASTERIZE); + mmesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | + DD_QUAD_SW_RASTERIZE); } else if (mmesa->renderindex) { diff --git a/xc/lib/GL/mesa/src/drv/mga/mgatritmp.h b/xc/lib/GL/mesa/src/drv/mga/mgatritmp.h index ac5a545d2..2a9d16b86 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgatritmp.h +++ b/xc/lib/GL/mesa/src/drv/mga/mgatritmp.h @@ -98,19 +98,31 @@ static void TAG(quad)( GLcontext *ctx, GLuint v0, } -#if ((IND & ~MGA_FLAT_BIT) == 0) - static void TAG(line)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint pv ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); mgaVertexPtr mgaVB = MGA_DRIVER_DATA(ctx->VB)->verts; float width = ctx->Line.Width; - if (IND & MGA_FLAT_BIT) { + if (IND & (MGA_TWOSIDE_BIT|MGA_FLAT_BIT)) { mgaVertex tmp0 = mgaVB[v0]; mgaVertex tmp1 = mgaVB[v1]; - *(int *)&tmp0.warp1.color = *(int *)&mgaVB[pv].warp1.color; - *(int *)&tmp1.warp1.color = *(int *)&mgaVB[pv].warp1.color; + + if (IND & MGA_TWOSIDE_BIT) { + GLubyte (*vbcolor)[4] = ctx->VB->ColorPtr->data; + + if (IND & MGA_FLAT_BIT) { + MGA_COLOR((char *)&tmp0.warp1.color,vbcolor[pv]); + *(int *)&tmp1.warp1.color = *(int *)&tmp0.warp1.color; + } else { + MGA_COLOR((char *)&tmp0.warp1.color,vbcolor[v0]); + MGA_COLOR((char *)&tmp1.warp1.color,vbcolor[v1]); + } + + } else { + *(int *)&tmp0.warp1.color = *(int *)&mgaVB[pv].warp1.color; + *(int *)&tmp1.warp1.color = *(int *)&mgaVB[pv].warp1.color; + } mga_draw_line( mmesa, &tmp0, &tmp1, width ); } else @@ -125,13 +137,20 @@ static void TAG(points)( GLcontext *ctx, GLuint first, GLuint last ) mgaVertexPtr mgaVB = MGA_DRIVER_DATA(VB)->verts; GLfloat sz = ctx->Point.Size * .5; int i; - + for(i=first;i<=last;i++) - if(VB->ClipMask[i]==0) - mga_draw_point( mmesa, &mgaVB[i], sz ); + if(VB->ClipMask[i]==0) { + if (IND & MGA_TWOSIDE_BIT) { + GLubyte (*vbcolor)[4] = VB->ColorPtr->data; + mgaVertex tmp0 = mgaVB[i]; + MGA_COLOR((char *)&tmp0.warp1.color, vbcolor[i]); + mga_draw_point( mmesa, &tmp0, sz ); + } else + mga_draw_point( mmesa, &mgaVB[i], sz ); + } } -#endif + static void TAG(init)( void ) @@ -139,10 +158,9 @@ static void TAG(init)( void ) tri_tab[IND] = TAG(triangle); quad_tab[IND] = TAG(quad); -#if ((IND & ~MGA_FLAT_BIT) == 0) line_tab[IND] = TAG(line); points_tab[IND] = TAG(points); -#endif + } diff --git a/xc/lib/GL/mesa/src/drv/mga/mgavb.c b/xc/lib/GL/mesa/src/drv/mga/mgavb.c index 4772e8a34..3f246d9a7 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgavb.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgavb.c @@ -104,7 +104,7 @@ static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ GLfloat yoffset = mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y; \ int i; \ (void) xoffset; (void) yoffset; \ - \ + if (0) fprintf(stderr, "V"); \ gl_import_client_data( VB, VB->ctx->RenderFlags, \ (VB->ClipOrMask \ ? VEC_WRITABLE|VEC_GOOD_STRIDE \ diff --git a/xc/lib/GL/mesa/src/drv/r128/Imakefile b/xc/lib/GL/mesa/src/drv/r128/Imakefile new file mode 100644 index 000000000..4cd07b8ff --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/Imakefile @@ -0,0 +1,325 @@ +XCOMM $XFree86$ + +#include <Threads.tmpl> + +#define DoNormalLib NormalLibGlx +#define DoSharedLib SharedLibGlx +#define DoExtraLib SharedLibGlx +#define DoDebugLib DebugLibGlx +#define DoProfileLib ProfileLibGlx + +#if Malloc0ReturnsNull +ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL +#endif + +#if BuildXF86DRI + DRI_DEFINES = GlxDefines -DDRIVERTS + DRI_INCLUDES = -I../../../../dri \ + -I../../../../glx \ + -I../../../dri \ + -I$(TOP)/include \ + -I$(TOP)/include/GL \ + -I$(XF86OSSRC) \ + -I$(XF86COMSRC) \ + -I$(SERVERSRC)/GL/dri \ + -I$(XF86DRIVERSRC)/r128 \ + -I../../../include \ + -I../.. \ + -I../../X \ + -I../common +#endif + +LinkSourceFile(mm.c, ../common) +LinkSourceFile(mm.h, ../common) +LinkSourceFile(hwlog.c, ../common) +LinkSourceFile(hwlog.h, ../common) + +MESA_INCLUDES = -I. -I.. -I../../include + + DEFINES = $(ALLOC_DEFINES) $(DRI_DEFINES) + INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) + + R128SRCS = r128_cce.c \ + r128_clear.c \ + r128_context.c \ + r128_dd.c \ + r128_fastpath.c \ + r128_pipeline.c \ + r128_screen.c \ + r128_span.c \ + r128_state.c \ + r128_swap.c \ + r128_tex.c \ + r128_tris.c \ + r128_vb.c \ + r128_xmesa.c + + R128OBJS = r128_cce.o \ + r128_clear.o \ + r128_context.o \ + r128_dd.o \ + r128_fastpath.o \ + r128_pipeline.o \ + r128_screen.o \ + r128_span.o \ + r128_state.o \ + r128_swap.o \ + r128_tex.o \ + r128_tris.o \ + r128_vb.o \ + r128_xmesa.o + +#if !GlxUseBuiltInDRIDriver + DRISRCS = ../../../dri/dri_mesa.c \ + ../../../../dri/dri_tmm.c + + DRIOBJS = ../../../dri/dri_mesa.o \ + ../../../../dri/dri_tmm.o + + DRMSRCS = ../../../../dri/drm/xf86drm.c \ + ../../../../dri/drm/xf86drmHash.c \ + ../../../../dri/drm/xf86drmRandom.c \ + ../../../../dri/drm/xf86drmSL.c \ + ../../../../dri/drm/xf86drmR128.c + + DRMOBJS = ../../../../dri/drm/xf86drm.o \ + ../../../../dri/drm/xf86drmHash.o \ + ../../../../dri/drm/xf86drmRandom.o \ + ../../../../dri/drm/xf86drmSL.o \ + ../../../../dri/drm/xf86drmR128.o + + MESASRCS = ../../aatriangle.c \ + ../../accum.c \ + ../../alpha.c \ + ../../alphabuf.c \ + ../../attrib.c \ + ../../bbox.c \ + ../../bitmap.c \ + ../../blend.c \ + ../../buffers.c \ + ../../clip.c \ + ../../colortab.c \ + ../../config.c \ + ../../context.c \ + ../../copypix.c \ + ../../cva.c \ + ../../debug_xform.c \ + ../../depth.c \ + ../../dlist.c \ + ../../drawpix.c \ + ../../enable.c \ + ../../enums.c \ + ../../eval.c \ + ../../extensions.c \ + ../../feedback.c \ + ../../fog.c \ + ../../get.c \ + ../../glapi.c \ + ../../glapinoop.c \ + ../../glthread.c \ + ../../hash.c \ + ../../image.c \ + ../../imaging.c \ + ../../light.c \ + ../../lines.c \ + ../../logic.c \ + ../../masking.c \ + ../../matrix.c \ + ../../mem.c \ + ../../mmath.c \ + ../../pb.c \ + ../../pipeline.c \ + ../../pixel.c \ + ../../pixeltex.c \ + ../../points.c \ + ../../polygon.c \ + ../../quads.c \ + ../../rastpos.c \ + ../../readpix.c \ + ../../rect.c \ + ../../scissor.c \ + ../../shade.c \ + ../../span.c \ + ../../stages.c \ + ../../state.c \ + ../../stencil.c \ + ../../teximage.c \ + ../../texobj.c \ + ../../texstate.c \ + ../../texture.c \ + ../../texutil.c \ + ../../translate.c \ + ../../triangle.c \ + ../../varray.c \ + ../../vb.c \ + ../../vbcull.c \ + ../../vbfill.c \ + ../../vbindirect.c \ + ../../vbrender.c \ + ../../vbxform.c \ + ../../vector.c \ + ../../vertices.c \ + ../../winpos.c \ + ../../xform.c \ + ../../zoom.c \ + ../../X86/common_x86.c + + MESAOBJS = ../../aatriangle.o \ + ../../accum.o \ + ../../alpha.o \ + ../../alphabuf.o \ + ../../attrib.o \ + ../../bbox.o \ + ../../bitmap.o \ + ../../blend.o \ + ../../buffers.o \ + ../../clip.o \ + ../../colortab.o \ + ../../config.o \ + ../../context.o \ + ../../copypix.o \ + ../../cva.o \ + ../../debug_xform.o \ + ../../depth.o \ + ../../dlist.o \ + ../../drawpix.o \ + ../../enable.o \ + ../../enums.o \ + ../../eval.o \ + ../../extensions.o \ + ../../feedback.o \ + ../../fog.o \ + ../../get.o \ + ../../hash.o \ + ../../hint.o \ + ../../image.o \ + ../../imaging.o \ + ../../light.o \ + ../../lines.o \ + ../../logic.o \ + ../../masking.o \ + ../../matrix.o \ + ../../mem.o \ + ../../mmath.o \ + ../../pb.o \ + ../../pipeline.o \ + ../../pixel.o \ + ../../pixeltex.o \ + ../../points.o \ + ../../polygon.o \ + ../../quads.o \ + ../../rastpos.o \ + ../../readpix.o \ + ../../rect.o \ + ../../scissor.o \ + ../../shade.o \ + ../../span.o \ + ../../stages.o \ + ../../state.o \ + ../../stencil.o \ + ../../teximage.o \ + ../../texobj.o \ + ../../texstate.o \ + ../../texture.o \ + ../../texutil.o \ + ../../translate.o \ + ../../triangle.o \ + ../../varray.o \ + ../../vb.o \ + ../../vbcull.o \ + ../../vbfill.o \ + ../../vbindirect.o \ + ../../vbrender.o \ + ../../vbxform.o \ + ../../vector.o \ + ../../vertices.o \ + ../../winpos.o \ + ../../xform.o \ + ../../zoom.o + +#ifdef i386Architecture + X86_SRCS = ../../X86/x86.c \ + ../../X86/x86a.S \ + ../../X86/common_x86.c \ + ../../X86/common_x86asm.S \ + ../../X86/vertex.S + + X86_OBJS = ../../X86/x86.o \ + ../../X86/x86a.o \ + ../../X86/common_x86.o \ + ../../X86/common_x86asm.o \ + ../../X86/vertex.o + + MMX_SRCS = ../../X86/mmx_blend.S + + MMX_OBJS = ../../X86/mmx_blend.o + +XCOMM Disabling 3Dnow code for the time being. +#if 0 + 3DNOW_SRCS = ../../X86/3dnow.c \ + ../../X86/3dnow_norm_raw.S \ + ../../X86/3dnow_xform_masked1.S \ + ../../X86/3dnow_xform_masked2.S \ + ../../X86/3dnow_xform_masked3.S \ + ../../X86/3dnow_xform_masked4.S \ + ../../X86/3dnow_xform_raw1.S \ + ../../X86/3dnow_xform_raw2.S \ + ../../X86/3dnow_xform_raw3.S \ + ../../X86/3dnow_xform_raw4.S \ + ../../X86/vertex_3dnow.S + + 3DNOW_OBJS = ../../X86/3dnow.o \ + ../../X86/3dnow_norm_raw.o \ + ../../X86/3dnow_xform_masked1.o \ + ../../X86/3dnow_xform_masked2.o \ + ../../X86/3dnow_xform_masked3.o \ + ../../X86/3dnow_xform_masked4.o \ + ../../X86/3dnow_xform_raw1.o \ + ../../X86/3dnow_xform_raw2.o \ + ../../X86/3dnow_xform_raw3.o \ + ../../X86/3dnow_xform_raw4.o \ + ../../X86/vertex_3dnow.o +#endif + +#endif +#endif + + ASMSRCS = $(X86_SRCS) $(MMX_SRCS) $(3DNOW_SRCS) + ASMOBJS = $(X86_OBJS) $(MMX_OBJS) $(3DNOW_OBJS) + + COMMONSRCS = mm.c hwlog.c + COMMONOBJS = mm.o hwlog.o + + SRCS = $(DRISRCS) $(DRMSRCS) $(MESASRCS) $(ASMSRCS) \ + $(COMMONSRCS) $(R128SRCS) + OBJS = $(DRIOBJS) $(DRMOBJS) $(MESAOBJS) $(ASMOBJS) \ + $(COMMONOBJS) $(R128OBJS) + +REQUIREDLIBS += -lm +#if !GlxBuiltInMga +REQUIREDLIBS += -L../../../.. -lGL +#endif + +#if !GlxUseBuiltInDRIDriver +#undef DoNormalLib NormalLibGlx +#undef DoExtraLib SharedLibGlx +#undef DoDebugLib DebugLibGlx +#undef DoProfileLib ProfileLibGlx +#endif + +#include <Library.tmpl> + +LibraryObjectRule() + +SubdirLibraryRule($(OBJS)) +NormalLintTarget($(SRCS)) + +#if !GlxUseBuiltInDRIDriver +LIBNAME = r128_dri.so +ALL_OBJS = $(OBJS) +ALL_DEPS = DONE +SharedDepModuleTarget($(LIBNAME),$(ALL_DEPS),$(ALL_OBJS)) +InstallDynamicModule($(LIBNAME),$(MODULEDIR)/dri,.) +#endif + +DependTarget() diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_cce.c b/xc/lib/GL/mesa/src/drv/r128/r128_cce.c new file mode 100644 index 000000000..e949dd37c --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_cce.c @@ -0,0 +1,389 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_reg.h" +#include "r128_cce.h" + +#if USE_USER_SPACE_RING + +#define USE_IOCTLS 0 +#define DO_SECURITY_CHECK 1 +#define R128_TIMEOUT 2000000 + +#if DEBUG +static void r128RingStatus(r128ScreenPtr pScrn) +{ + unsigned char *R128MMIO = pScrn->mmio; + + R128_DEBUG(("GUI_STAT = 0x%08x\n", + (unsigned int)INREG(R128_GUI_STAT))); + R128_DEBUG(("PM4_STAT = 0x%08x\n", + (unsigned int)INREG(R128_PM4_STAT))); + R128_DEBUG(("PM4_BUFFER_DL_WPTR = 0x%08x\n", + (unsigned int)INREG(R128_PM4_BUFFER_DL_WPTR))); + R128_DEBUG(("PM4_BUFFER_DL_RPTR = 0x%08x\n", + (unsigned int)INREG(R128_PM4_BUFFER_DL_RPTR))); + R128_DEBUG(("ringWrite = 0x%08x\n", pScrn->SAREA->ringWrite)); + R128_DEBUG(("*ringReadPtr = 0x%08x\n", *pScrn->ringReadPtr)); +} +#endif + +/* FIXME: Requires access to secure registers */ +static int INPLL(r128ScreenPtr pScrn, int addr) +{ + unsigned char *R128MMIO = pScrn->mmio; + + OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); + return INREG(R128_CLOCK_CNTL_DATA); +} + +/* FIXME: Requires access to secure registers */ +static void r128EngineFlush(r128ScreenPtr pScrn) +{ + unsigned char *R128MMIO = pScrn->mmio; + int i; + + OUTREGP(R128_PC_NGUI_CTLSTAT, R128_PC_FLUSH_ALL, ~R128_PC_FLUSH_ALL); + for (i = 0; i < R128_TIMEOUT; i++) { + if (!(INREG(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) break; + } +} + +/* FIXME: Requires access to secure registers */ +static void r128EngineReset(r128ScreenPtr pScrn) +{ +#if USE_IOCTLS +#if DEBUG + r128RingStatus(pScrn); +#endif + + (void)drmR128EngineReset(pScrn->driScreen->fd); +#else + unsigned char *R128MMIO = pScrn->mmio; + CARD32 clock_cntl_index; + CARD32 mclk_cntl; + CARD32 gen_reset_cntl; + +#if DEBUG + r128RingStatus(pScrn); +#endif + + r128EngineFlush(pScrn); + + clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX); + mclk_cntl = INPLL(pScrn, R128_MCLK_CNTL); + + OUTPLL(R128_MCLK_CNTL, mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CPP); + + gen_reset_cntl = INREG(R128_GEN_RESET_CNTL); + + OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); + INREG(R128_GEN_RESET_CNTL); + OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); + INREG(R128_GEN_RESET_CNTL); + + OUTPLL(R128_MCLK_CNTL, mclk_cntl); + OUTREG(R128_CLOCK_CNTL_INDEX, clock_cntl_index); + OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl); + + /* Reset the ring buffer status */ + if (R128CCE_USE_RING_BUFFER(pScrn->CCEMode)) { + OUTREG(R128_PM4_BUFFER_DL_WPTR, 0); + OUTREG(R128_PM4_BUFFER_DL_RPTR, 0); + pScrn->SAREA->ringWrite = 0; + *pScrn->ringReadPtr = 0; + } +#endif + fprintf(stderr, "Error: Rage 128 timed out... exiting\n"); + exit(-1); +} + +#define r128CCEWaitForFifo(pScrn, entries) \ +do { \ + if (pScrn->CCEFifoSlots < entries) \ + r128CCEWaitForFifoFunction(pScrn, entries); \ + pScrn->CCEFifoSlots -= entries; \ +} while (0) + +/* Wait for at least `entries' slots are free. The actual number of + slots available is stored in info->CCEFifoSize. */ +static void r128CCEWaitForFifoFunction(r128ScreenPtr pScrn, int entries) +{ + unsigned char *R128MMIO = pScrn->mmio; + int i; + + for (;;) { + for (i = 0; i < R128_TIMEOUT; i++) { + pScrn->CCEFifoSlots = INREG(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK; + if (pScrn->CCEFifoSlots >= entries) return; + } + R128_DEBUG(("Reseting Engine: PM4_STAT = 0x%08x\n", + (unsigned int)INREG(R128_PM4_STAT))); + r128EngineReset(pScrn); + } +} + +/* Wait until the CCE is completely idle: the FIFO has drained and the + CCE is idle. */ +void r128CCEWaitForIdle(r128ScreenPtr pScrn) +{ +#if USE_IOCTLS + if (drmR128WaitForIdle(pScrn->driScreen->fd) < 0) { + fprintf(stderr, "Error: Rage 128 timed out... exiting\n"); + exit(-1); + } +#else + unsigned char *R128MMIO = pScrn->mmio; + int i; + + if (R128CCE_USE_RING_BUFFER(pScrn->CCEMode)) { + OUTREGP(R128_PM4_BUFFER_DL_WPTR, + R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE); + + for (;;) { + for (i = 0; i < R128_TIMEOUT; i++) { + if (*pScrn->ringReadPtr == pScrn->SAREA->ringWrite) { + int pm4stat = INREG(R128_PM4_STAT); + if ((pm4stat & R128_PM4_FIFOCNT_MASK) == pScrn->CCEFifoSize + && !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) + return; + } + } + R128_DEBUG(("Reseting Engine: PM4_STAT = 0x%08x\n", + (unsigned int)INREG(R128_PM4_STAT))); + r128EngineReset(pScrn); + } + } else { + r128CCEWaitForFifoFunction(pScrn, pScrn->CCEFifoSize); + + for (;;) { + for (i = 0; i < R128_TIMEOUT; i++) { + if (!(INREG(R128_PM4_STAT) + & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + r128EngineFlush(pScrn); + return; + } + } + R128_DEBUG(("Reseting Engine: PM4_STAT = 0x%08x\n", + (unsigned int)INREG(R128_PM4_STAT))); + r128EngineReset(pScrn); + } + } +#endif +} + +/* Send a packet to the CCE via the PIO registers */ +static void r128CCESubmitPacketPIO(r128ContextPtr r128ctx, + CARD32 *buf, int count) +{ + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; +#if DO_SECURITY_CHECK + CARD32 tmp = 0; + int psize = 0; + int writing = 1; + int addr = R128_PM4_FIFO_DATA_EVEN; +#endif + +#if DO_SECURITY_CHECK + while (count > 0) { + tmp = *buf++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + r128CCEWaitForFifo(r128ctx->r128Screen, 1); + OUTREG(addr, tmp); + addr ^= 0x0004; + } + + count--; + } + + if (addr == R128_PM4_FIFO_DATA_ODD) { + r128CCEWaitForFifo(r128ctx->r128Screen, 1); + OUTREG(addr, R128_CCE_PACKET2); + } +#else + while (count > 1) { + r128CCEWaitForFifo(r128ctx->r128Screen, 2); + OUTREG(R128_PM4_FIFO_DATA_EVEN, *buf++); + OUTREG(R128_PM4_FIFO_DATA_ODD, *buf++); + count -= 2; + } + + if (count) { + r128CCEWaitForFifo(r128ctx->r128Screen, 2); + OUTREG(R128_PM4_FIFO_DATA_EVEN, *buf); + OUTREG(R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2); + } +#endif +} + +/* Send a packet to the CCE via the ring */ +static void r128CCESubmitPacketRing(r128ContextPtr r128ctx, + CARD32 *buf, int count) +{ + r128ScreenPtr r128scrn = r128ctx->r128Screen; + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + int ringWrite = r128scrn->SAREA->ringWrite; + int *ringWritePtr = r128scrn->ringStartPtr + ringWrite; + int timeout; +#if DO_SECURITY_CHECK + CARD32 tmp = 0; + int psize = 0; + int writing = 1; +#endif + + if (count > r128scrn->ringEntries) { + /* FIXME */ + return; + } + + while (count > 0) { +#if DO_SECURITY_CHECK + tmp = *buf++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + ringWrite++; + *ringWritePtr++ = tmp; + } +#else + ringWrite++; + *ringWritePtr++ = *buf++; +#endif + if (ringWrite >= r128scrn->ringEntries) { + ringWrite = 0; + ringWritePtr = r128scrn->ringStartPtr; + } + timeout = 0; + while (ringWrite == *r128scrn->ringReadPtr) { + (void)INREG(R128_PM4_BUFFER_DL_RPTR); + if (timeout++ >= R128_TIMEOUT) r128EngineReset(r128scrn); + } + + count--; + } + + if (ringWrite < 32) { + memcpy(r128scrn->ringEndPtr, + r128scrn->ringStartPtr, + ringWrite * sizeof(int)); + } + + r128scrn->SAREA->ringWrite = ringWrite; + OUTREG(R128_PM4_BUFFER_DL_WPTR, ringWrite); +} + +void r128CCESubmitPackets(r128ContextPtr r128ctx, CARD32 *buf, int count) +{ +#if USE_IOCTLS + if (drmR128SubmitPackets(r128ctx->r128Screen->driScreen->fd, + r128ctx->CCEbuf, r128ctx->CCEcount, + 0) < 0) { + r128EngineReset(r128ctx->r128Screen); + fprintf(stderr, "Error: Illegal CCE packet... exiting\n"); + exit(-1); + } +#else + if (R128CCE_USE_RING_BUFFER(r128ctx->r128Screen->CCEMode)) + r128CCESubmitPacketRing(r128ctx, buf, count); + else + r128CCESubmitPacketPIO(r128ctx, buf, count); +#endif +} + +#endif diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_cce.h b/xc/lib/GL/mesa/src/drv/r128/r128_cce.h new file mode 100644 index 000000000..162686cb7 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_cce.h @@ -0,0 +1,142 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_CCE_H_ +#define _R128_CCE_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include "r128_dri.h" +#include "r128_reg.h" + +#include "xf86drmR128.h" + +typedef union { + float f; + int i; +} floatTOint; + +#define R128_DEFAULT_TOTAL_CCE_TIMEOUT 1000000 /* usecs */ + +/* Insert an integer value into the CCE ring buffer. */ +#define R128CCE(v) \ + do { \ + r128ctx->CCEbuf[r128ctx->CCEcount] = (v); \ + r128ctx->CCEcount++; \ + } while (0) + +/* Insert an floating point value into the CCE ring buffer. */ +#define R128CCEF(v) \ + do { \ + floatTOint fTi; \ + fTi.f = (v); \ + r128ctx->CCEbuf[r128ctx->CCEcount] = fTi.i; \ + r128ctx->CCEcount++; \ + } while (0) + +#if USE_USER_SPACE_RING + +#define R128CCE_SUBMIT_PACKETS() \ + do { \ + r128CCESubmitPackets(r128ctx, r128ctx->CCEbuf, r128ctx->CCEcount); \ + r128ctx->CCEcount = 0; \ + } while (0) + +#define R128CCE_WAIT_FOR_IDLE(r128ctx) \ + r128CCEWaitForIdle(r128ctx->r128Screen) + +#else /* if !USE_USER_SPACE_RING */ + +#define R128CCE_SUBMIT_PACKETS() \ + do { \ + CARD32 *_buf; \ + int _c = r128ctx->CCEcount; \ + int _fd = r128ctx->r128Screen->driScreen->fd; \ + int _to = 0; \ + int _ret; \ + \ + do { \ + _buf = r128ctx->CCEbuf + (r128ctx->CCEcount - _c); \ + _ret = drmR128SubmitPackets(_fd, _buf, &_c, 0); \ + } while (_ret < 0 && _ret == -EBUSY && _to++ < r128ctx->CCEtimeout); \ + if (_ret < 0) { \ + (void)drmR128EngineReset(_fd); \ + fprintf(stderr, "Error: Could not submit packet... exiting\n"); \ + exit(-1); \ + } \ + r128ctx->CCEcount = 0; \ + } while (0) + +#define R128CCE_WAIT_FOR_IDLE(r128ctx) \ + do { \ + int _fd = r128ctx->r128Screen->driScreen->fd; \ + int _to = 0; \ + int _ret; \ + \ + (void)drmR128EngineFlush(_fd); \ + do { \ + _ret = drmR128CCEWaitForIdle(_fd); \ + } while (_ret < 0 && _ret == -EBUSY && _to++ < r128ctx->CCEtimeout); \ + if (_ret < 0) { \ + (void)drmR128EngineReset(_fd); \ + fprintf(stderr, "Error: Rage 128 timed out... exiting\n"); \ + exit(-1); \ + } \ + } while (0) + +#endif + +#define R128CCE_WAIT_FOR_IDLE_LOCK(r128ctx) \ + do { \ + LOCK_HARDWARE(r128ctx); \ + R128CCE_WAIT_FOR_IDLE(r128ctx); \ + UNLOCK_HARDWARE(r128ctx); \ + } while (0) + + +/* Insert a type-[0123] packet header into the ring buffer */ +#define R128CCE0(p,r,n) R128CCE((p) | ((n) << 16) | ((r) >> 2)) +#define R128CCE1(p,r1,r2) R128CCE((p) | (((r2) >> 2) << 11) | ((r1) >> 2)) +#define R128CCE2(p) R128CCE((p)) +#define R128CCE3(p,n) R128CCE((p) | ((n) << 16)) + + +#if USE_USER_SPACE_RING +extern void r128CCEWaitForIdle(r128ScreenPtr pScrn); +extern void r128CCESubmitPackets(r128ContextPtr r128ctx, + CARD32 *buf, int count); +#endif + +#endif +#endif /* _R128_CCE_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_ccevb.h b/xc/lib/GL/mesa/src/drv/r128/r128_ccevb.h new file mode 100644 index 000000000..2084b8672 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_ccevb.h @@ -0,0 +1,224 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_CCEVB_H_ +#define _R128_CCEVB_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include "xf86drmR128.h" + +typedef struct { + CARD32 *buf; /* Pointer to current VB */ + int index; /* Index of current VB */ + int start; /* in bytes from the beginning of the VB map */ + int size; /* in vertices */ + int count; /* in vertices */ + drmR128PrimType prim; /* Primitive type for vertices in VB */ + int done; /* VB has been sent to ring */ +} r128CCEVertBuf, *r128CCEVertBufPtr; + + + +/* Flush the CPU's write-combining cache */ +/* FIXME: This code is both processor and compiler specific */ +#define R128_FLUSH_WC_MEMORY() \ + do { \ + int xchangeDummy; \ + \ + __asm__ volatile("push %%eax ;" \ + "xchg %%eax, %0 ;" \ + "pop %%eax" : : "m" (xchangeDummy)); \ + __asm__ volatile("push %%eax ;" \ + "push %%ebx ;" \ + "push %%ecx ;" \ + "push %%edx ;" \ + "movl $0,%%eax ;" \ + "cpuid ;" \ + "pop %%edx ;" \ + "pop %%ecx ;" \ + "pop %%ebx ;" \ + "pop %%eax" : /* no outputs */ : /* no inputs */); \ + } while (0) + + +/* Get a new VB from the pool of vertex buffers in AGP space */ +/* NOTE: By default the primitive type for a VB is set to individual tris */ +#define R128CCE_GET_NEW_VB(r128ctx) \ + do { \ + r128CCEVertBufPtr vb = &r128ctx->vb; \ + int to = 0; \ + int fd = r128ctx->r128Screen->driScreen->fd; \ + int num; \ + int index; \ + int size; \ + \ + vb->buf = NULL; \ + \ + LOCK_HARDWARE(r128ctx); \ + while (!vb->buf && to++ < r128ctx->CCEtimeout) { \ + /* Ask the kernel a new vertex buffer */ \ + num = drmR128GetVertexBuffers(fd, 1, &index, &size); \ + \ + if (num > 0) { \ + vb->buf = (CARD32 *)(r128ctx->r128Screen-> \ + vbBufs->list[index].address); \ + vb->index = index; \ + vb->start = index*r128ctx->r128Screen->vbBufSize; \ + vb->size = size/sizeof(r128_vertex); \ + vb->count = 0; \ + vb->prim = DRM_R128_PRIM_TRI_LIST; \ + vb->done = GL_FALSE; \ + } \ + } \ + UNLOCK_HARDWARE(r128ctx); \ + \ + if (!vb->buf) { \ + (void)drmR128EngineReset(fd); \ + fprintf(stderr, "Error: Could not get new VB... exiting\n"); \ + exit(-1); \ + } \ + } while (0) + +/* Submit a VB to the hardware for processing */ +/* NOTE: This macro is only called while holding the hardware lock */ +#define R128CCE_SUBMIT_VB(r128ctx) \ + do { \ + int index = r128ctx->vb.index; \ + int size = r128ctx->vb.count; \ + int fd = r128ctx->r128Screen->driScreen->fd; \ + int to = 0; \ + int ret; \ + CARD32 prim; \ + \ + switch (r128ctx->vb.prim) { \ + case DRM_R128_PRIM_NONE: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_NONE; \ + break; \ + case DRM_R128_PRIM_POINT: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_POINT; \ + break; \ + case DRM_R128_PRIM_LINE: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_LINE; \ + break; \ + case DRM_R128_PRIM_POLY_LINE: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE; \ + break; \ + case DRM_R128_PRIM_TRI_LIST: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; \ + break; \ + case DRM_R128_PRIM_TRI_FAN: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN; \ + break; \ + case DRM_R128_PRIM_TRI_STRIP: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP; \ + break; \ + case DRM_R128_PRIM_TRI_TYPE2: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2; \ + break; \ + default: \ + prim = R128_CCE_VC_CNTL_PRIM_TYPE_NONE; \ + break; \ + } \ + \ + /* Send the vertex buffer to the hardware */ \ + BEGIN_CLIP_LOOP(r128ctx); \ + \ + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3); \ + R128CCE(r128ctx->r128Screen->vbOffset + r128ctx->vb.start); \ + R128CCE(r128ctx->vb.count); \ + R128CCE(R128_FULL_VERTEX_FORMAT); \ + R128CCE(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | \ + (r128ctx->vb.count << R128_CCE_VC_CNTL_NUM_SHIFT)); \ + R128CCE_SUBMIT_PACKETS(); \ + \ + END_CLIP_LOOP(r128ctx); \ + \ + /* Tell the kernel to release the vertex buffer */ \ + do { \ + ret = drmR128FlushVertexBuffers(fd, 1, &index, &size, \ + r128ctx->vb.prim); \ + } while (ret < 0 && ret == -EBUSY && to++ < r128ctx->CCEtimeout); \ + if (ret < 0) { \ + (void)drmR128EngineReset(fd); \ + fprintf(stderr, "Error: Could not flush VB... exiting\n"); \ + exit(-1); \ + } \ + \ + r128ctx->vb.done = GL_TRUE; \ + } while (0) + +/* Flush the vertex buffer (assuming we already hold the lock) */ +#define R128CCE_FLUSH_VB(r128ctx) \ + do { \ + if (r128ctx->vb.count && !r128ctx->vb.done) { \ + /* FIXME: Is this _really_ needed? */ \ + if (!R128CCE_USE_RING_BUFFER(r128ctx->r128Screen->CCEMode)) \ + R128CCE_WAIT_FOR_IDLE(r128ctx); \ + \ + R128CCE_SUBMIT_VB(r128ctx); \ + } \ + } while (0) + +/* Flush the vertex buffer */ +#define R128CCE_FLUSH_VB_LOCK(r128ctx) \ + do { \ + LOCK_HARDWARE(r128ctx); \ + R128CCE_FLUSH_VB(r128ctx); \ + UNLOCK_HARDWARE(r128ctx); \ + } while (0) + +/* Reserve space in a VB to store `n' vertices, and set the pointer `p' + to point to the next vertex in the current VB. If adding these + vertices to the VB would exceed the size of the VB, then flush the + current VB, get a new one from the pool of VBs, reserve space in the + new VB for the `n' vertices, and set the pointer `p' to point to the + first vertex in the new VB. */ +#define R128CCE_ALLOC_VB_SPACE(r128ctx, p, n) \ + do { \ + r128CCEVertBufPtr vb = &r128ctx->vb; \ + \ + if (vb->done) R128CCE_GET_NEW_VB(r128ctx); \ + \ + if (vb->count + (n) > vb->size) { \ + R128CCE_FLUSH_VB_LOCK(r128ctx); \ + R128CCE_GET_NEW_VB(r128ctx); \ + } \ + \ + (p) = (r128_vertex *)vb->buf + vb->count; \ + vb->count += (n); \ + } while (0) + +#endif +#endif /* _R128_CCEVB_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_clear.c b/xc/lib/GL/mesa/src/drv/r128/r128_clear.c new file mode 100644 index 000000000..9ab0581b0 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_clear.c @@ -0,0 +1,248 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_state.h" +#include "r128_vb.h" +#include "r128_clear.h" + +/* Clear the depth buffer */ +void r128ClearDepthBuffer(r128ContextPtr r128ctx, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch) +{ + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; + int nc; + XF86DRIClipRectPtr c; + int dst_bpp; + CARD32 write_mask; + + if (!(r128ctx->regs.tex_cntl_c & R128_Z_WRITE_ENABLE)) return; + + switch (r128ctx->regs.z_sten_cntl_c & R128_Z_PIX_WIDTH_MASK) { + case R128_Z_PIX_WIDTH_16: + write_mask = 0x0000ffff; + dst_bpp = R128_GMC_DST_16BPP; + break; + case R128_Z_PIX_WIDTH_24: + write_mask = 0x00ffffff; + dst_bpp = R128_GMC_DST_32BPP; + break; + case R128_Z_PIX_WIDTH_32: + write_mask = 0xffffffff; + dst_bpp = R128_GMC_DST_32BPP; + break; + default: return; + } + + cx += dPriv->x; + cy = dPriv->y + dPriv->h - cy - ch; + + LOCK_HARDWARE(r128ctx); + + /* Flush any outstanding vertex buffers */ + R128CCE_FLUSH_VB(r128ctx); + + /* Init the clip rects here in case they changed during the + LOCK_HARDWARE macro */ + c = dPriv->pClipRects; + nc = dPriv->numClipRects; + + /* Set the write mask so that we _only_ clear the Z buffer */ + R128CCE0(R128_CCE_PACKET0, R128_DP_WRITE_MASK, 0); + R128CCE(write_mask); + + /* Temporarily disable Z and stencil buffer and texture mapping modes */ + R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); + R128CCE(r128ctx->regs.tex_cntl_c & ~(R128_Z_ENABLE | + R128_STENCIL_ENABLE | + R128_TEXMAP_ENABLE)); + + /* Cycle through the clip rects */ + while (nc--) { + int x = c[nc].x1; + int y = c[nc].y1; + int w = c[nc].x2 - x; + int h = c[nc].y2 - y; + + if (!all) { + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + + if (w <= 0 || h <= 0) continue; + } + + x += r128ctx->r128Screen->depthX; + y += r128ctx->r128Screen->depthY; + + R128CCE3(R128_CCE_PACKET3_CNTL_PAINT_MULTI, 3); + R128CCE(R128_GMC_BRUSH_SOLID_COLOR + | dst_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_3D_FCN_EN /* FIXME?? */ + | R128_GMC_CLR_CMP_CNTL_DIS /* FIXME?? */ + | R128_AUX_CLIP_DIS /* FIXME?? */ + | R128_GMC_WR_MSK_DIS); /* FIXME?? */ + R128CCE(r128ctx->ClearDepth); + R128CCE((x << 16) | y); + R128CCE((w << 16) | h); + } + +#if 0 + /* Set the write mask so that we _only_ clear the Z buffer */ + R128CCE0(R128_CCE_PACKET0, R128_DP_WRITE_MASK, 0); + R128CCE(0xffffffff); + + /* Restore Z and stencil buffer and texture mapping modes */ + R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); + R128CCE(r128ctx->regs.tex_cntl_c); +#else + /* FIXME: We should be able to optimize this by restoring only the + registers that change (above) */ + /* NOTE: The restore of TEX_CNTL_C and R128_DP_WRITE_MASK is handled by + vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALL_DIRTY; +#endif + + R128CCE_SUBMIT_PACKETS(); + + UNLOCK_HARDWARE(r128ctx); +} + +/* Clear a color buffer */ +void r128ClearColorBuffer(r128ContextPtr r128ctx, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch, + GLint drawX, GLint drawY) +{ + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; + int nc; + XF86DRIClipRectPtr c; + int dst_bpp; + + switch (r128ctx->r128Screen->bpp) { + case 8: + dst_bpp = R128_GMC_DST_8BPP_CI; + break; + case 16: + if (r128ctx->r128Screen->depth == 15) dst_bpp = R128_GMC_DST_15BPP; + else dst_bpp = R128_GMC_DST_16BPP; + break; + case 24: + dst_bpp = R128_GMC_DST_24BPP; + break; + case 32: + default: + dst_bpp = R128_GMC_DST_32BPP; + break; + } + + cx += dPriv->x; + cy = dPriv->y + dPriv->h - cy - ch; + + LOCK_HARDWARE(r128ctx); + + /* Flush any outstanding vertex buffers */ + R128CCE_FLUSH_VB(r128ctx); + + /* Init the clip rects here in case they changed during the + LOCK_HARDWARE macro */ + c = dPriv->pClipRects; + nc = dPriv->numClipRects; + + /* Temporarily disable Z and stencil buffer and texture mapping modes */ + R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); + R128CCE(r128ctx->regs.tex_cntl_c & ~(R128_Z_ENABLE | + R128_STENCIL_ENABLE | + R128_TEXMAP_ENABLE)); + + /* Cycle through the clip rects */ + while (nc--) { + int x = c[nc].x1; + int y = c[nc].y1; + int w = c[nc].x2 - x; + int h = c[nc].y2 - y; + + if (!all) { + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - h; + + if (w <= 0 || h <= 0) continue; + } + + x += drawX; + y += drawY; + + R128CCE3(R128_CCE_PACKET3_CNTL_PAINT_MULTI, 3); + R128CCE(R128_GMC_BRUSH_SOLID_COLOR + | dst_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_3D_FCN_EN /* FIXME?? */ + | R128_GMC_CLR_CMP_CNTL_DIS /* FIXME?? */ + | R128_AUX_CLIP_DIS); /* FIXME?? */ + R128CCE(r128ctx->ClearColor); + R128CCE((x << 16) | y); + R128CCE((w << 16) | h); + } + +#if 0 + /* Restore Z and stencil buffer and texture mapping modes */ + R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); + R128CCE(r128ctx->regs.tex_cntl_c); +#else + /* FIXME: We should be able to optimize this by restoring only the + registers that change (above) */ + /* NOTE: The restore of TEX_CNTL_C is handled by + vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALL_DIRTY; +#endif + + R128CCE_SUBMIT_PACKETS(); + + UNLOCK_HARDWARE(r128ctx); +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_clear.h b/xc/lib/GL/mesa/src/drv/r128/r128_clear.h new file mode 100644 index 000000000..7018b05b4 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_clear.h @@ -0,0 +1,47 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_CLEAR_H_ +#define _R128_CLEAR_H_ + +#ifdef GLX_DIRECT_RENDERING + +extern void r128ClearDepthBuffer(r128ContextPtr r128ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height); +extern void r128ClearColorBuffer(r128ContextPtr r128ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height, + GLint drawX, GLint drawY); + +#endif +#endif /* _R128_CLEAR_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_context.c b/xc/lib/GL/mesa/src/drv/r128/r128_context.c new file mode 100644 index 000000000..01573f559 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_context.c @@ -0,0 +1,203 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include <stdlib.h> + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_cce.h" +#include "r128_dd.h" +#include "r128_state.h" +#include "r128_span.h" +#include "r128_tex.h" +#include "r128_vb.h" +#include "r128_pipeline.h" + +#include "context.h" +#include "simple_list.h" + +/* Create the device specific context */ +GLboolean r128CreateContext(Display *dpy, GLvisual *glVisual, + __DRIcontextPrivate *driContextPriv) +{ + r128ContextPtr r128ctx; + r128ScreenPtr r128scrn; + GLcontext *glCtx = driContextPriv->mesaContext; + int i; + char *v; + + r128ctx = (r128ContextPtr)Xmalloc(sizeof(*r128ctx)); + if (!r128ctx) return GL_FALSE; + + /* Initialize r128Context */ + r128ctx->glCtx = glCtx; + r128ctx->display = dpy; + r128ctx->driContext = driContextPriv; + r128ctx->driDrawable = NULL; /* Set by XMesaMakeCurrent */ + + if (getenv("LIBGL_SOFTWARE_RENDERING")) + r128ctx->SWonly = GL_TRUE; + else + r128ctx->SWonly = GL_FALSE; + if (getenv("LIBGL_NO_SOFTWARE_FALLBACKS")) + r128ctx->SWfallbackDisable = GL_TRUE; + else + r128ctx->SWfallbackDisable = GL_FALSE; + r128scrn = r128ctx->r128Screen = + (r128ScreenPtr)(driContextPriv->driScreenPriv->private); + + r128ctx->CurrentTexObj[0] = NULL; + r128ctx->CurrentTexObj[1] = NULL; + make_empty_list(&r128ctx->SwappedOut); + for (i = 0; i < r128scrn->NRTexHeaps; i++) { + make_empty_list(&r128ctx->TexObjList[i]); + r128ctx->texHeap[i] = mmInit(0, r128scrn->texSize[i]); + r128ctx->lastTexAge[i] = -1; + } + + r128ctx->lastSwapAge = 0; + + r128ctx->useFastPath = GL_FALSE; + + r128ctx->vb.start = 0; + r128ctx->vb.count = 0; + r128ctx->vb.size = 0; + r128ctx->vb.index = 0; + r128ctx->vb.buf = NULL; + r128ctx->vb.done = GL_TRUE; + + if (r128scrn->IsPCI || getenv("LIBGL_DISABLE_VERTEX_BUFFERS")) + r128ctx->disableVB = GL_TRUE; + else + r128ctx->disableVB = GL_FALSE; + + r128ctx->CCEbuf = (CARD32 *)malloc(sizeof(*r128ctx->CCEbuf) * + r128scrn->ringEntries); + r128ctx->CCEcount = 0; + + if ((v = getenv("LIBGL_CCE_TIMEOUT"))) + r128ctx->CCEtimeout = strtoul(v, NULL, 10); + else + r128ctx->CCEtimeout = (R128_DEFAULT_TOTAL_CCE_TIMEOUT / + R128_DEFAULT_CCE_TIMEOUT); + if (r128ctx->CCEtimeout <= 0) r128ctx->CCEtimeout = 1; + + /* Initialize GLcontext */ + glCtx->DriverCtx = (void *)r128ctx; + + r128DDInitExtensions(glCtx); + + r128DDInitDriverFuncs(glCtx); + r128DDInitStateFuncs(glCtx); + r128DDInitSpanFuncs(glCtx); + r128DDInitTextureFuncs(glCtx); + + glCtx->Driver.TriangleCaps = (DD_TRI_CULL + | DD_TRI_LIGHT_TWOSIDE + | DD_TRI_OFFSET); +#if 0 + /* FIXME */ + glCtx->TriangleCaps |= DD_CLIP_FOG_COORD; +#endif + + /* Reset Mesa's current 2D texture pointers to the driver's textures */ + glCtx->Shared->DefaultD[2][0].DriverData = NULL; + glCtx->Shared->DefaultD[2][1].DriverData = NULL; + + /* If Mesa has current a vertex buffer, make sure the driver's VB + data is up to date */ + if (glCtx->VB) r128DDRegisterVB(glCtx->VB); + + /* Register the fast path */ + if (glCtx->NrPipelineStages) + glCtx->NrPipelineStages = + r128RegisterPipelineStages(glCtx->PipelineStage, + glCtx->PipelineStage, + glCtx->NrPipelineStages); + + r128DDInitState(r128ctx); + + driContextPriv->driverPrivate = (void *)r128ctx; + + return GL_TRUE; +} + +/* Destroy the device specific context */ +void r128DestroyContext(r128ContextPtr r128ctx) +{ + if (r128ctx) { + r128TexObjPtr t, next_t; + int i; + + free(r128ctx->CCEbuf); + + for (i = 0; i < r128ctx->r128Screen->NRTexHeaps; i++) { + foreach_s (t, next_t, &r128ctx->TexObjList[i]) + r128DestroyTexObj(r128ctx, t); + } + + foreach_s (t, next_t, &r128ctx->SwappedOut) + r128DestroyTexObj(r128ctx, t); + + gl_destroy_context(r128ctx->glCtx); + Xfree(r128ctx); + } +} + +/* Load the device specific context into the hardware. The actual + setting of the hardware state is done in the r128UpdateHWState(). */ +r128ContextPtr r128MakeCurrent(r128ContextPtr oldCtx, + r128ContextPtr newCtx, + __DRIdrawablePrivate *dPriv) +{ + if (oldCtx) { + if (!R128CCE_USE_RING_BUFFER(newCtx->r128Screen->CCEMode)) + newCtx->dirty |= R128_REQUIRE_QUIESCENCE; + if (oldCtx != newCtx) { + newCtx->dirty |= R128_UPDATE_CONTEXT; + newCtx->dirty_context |= R128_CTX_ALL_DIRTY; + } + if (oldCtx->driDrawable != dPriv) + newCtx->dirty |= R128_UPDATE_WINPOS; + } else { + newCtx->dirty |= R128_UPDATE_CONTEXT; + newCtx->dirty_context |= R128_CTX_ALL_DIRTY; + } + + newCtx->driDrawable = dPriv; + + return newCtx; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_context.h b/xc/lib/GL/mesa/src/drv/r128/r128_context.h new file mode 100644 index 000000000..189a22cbe --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_context.h @@ -0,0 +1,219 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_CONTEXT_H_ +#define _R128_CONTEXT_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include "r128_texobj.h" +#include "r128_fastpath.h" +#include "r128_ccevb.h" + +/* Flags for what needs to be updated before a new primitive is rendered */ +#define R128_CLEAN 0x0000 +#define R128_REQUIRE_QUIESCENCE 0x0001 +#define R128_UPDATE_CONTEXT 0x0002 +#define R128_UPDATE_WINPOS 0x0004 +#define R128_UPDATE_TEX0IMAGES 0x0008 +#define R128_UPDATE_TEX1IMAGES 0x0010 +#define R128_UPDATE_TEXSTATE 0x0020 +#define R128_ALL_DIRTY 0xffff + +/* Flags for what context state needs to be updated */ +#define R128_CTX_CLEAN 0x0000 +#define R128_CTX_MISC 0x0001 +#define R128_CTX_ENGINESTATE 0x0002 +#define R128_CTX_TEX0STATE 0x0004 +#define R128_CTX_TEX1STATE 0x0008 +#define R128_CTX_TEXENVSTATE 0x0010 +#define R128_CTX_FOGSTATE 0x0020 +#define R128_CTX_FOGTABLE 0x0040 +#define R128_CTX_ZSTENSTATE 0x0080 +#define R128_CTX_SCISSORS 0x0100 +#define R128_CTX_ALPHASTATE 0x0200 +#define R128_CTX_SETUPSTATE 0x0400 +#define R128_CTX_WIN_Z_POS 0x0800 +#define R128_CTX_FLUSH_PIX_CACHE 0x1000 +#define R128_CTX_ALL_DIRTY 0xffff + +/* Flags for software fallback cases */ +#define R128_FALLBACK_TEXTURE 0x0001 +#define R128_FALLBACK_DRAW_BUFFER 0x0002 +#define R128_FALLBACK_READ_BUFFER 0x0004 +#define R128_FALLBACK_COLORMASK 0x0008 +#define R128_FALLBACK_STIPPLE 0x0010 + +/* NOTE: The groups below need to be kept together so that a single + memcpy can be used to transfer data to the ring buffer */ +typedef struct { + CARD32 scale_3d_cntl; /* 0x1a00 */ + + CARD32 aux_sc_cntl; /* 0x1660 */ + CARD32 aux1_sc_left; + CARD32 aux1_sc_right; + CARD32 aux1_sc_top; + CARD32 aux1_sc_bottom; + CARD32 aux2_sc_left; + CARD32 aux2_sc_right; + CARD32 aux2_sc_top; + CARD32 aux2_sc_bottom; + CARD32 aux3_sc_left; + CARD32 aux3_sc_right; + CARD32 aux3_sc_top; + CARD32 aux3_sc_bottom; /* 0x1690 */ + + CARD32 dst_pitch_offset_c; /* 0x1c80 */ + CARD32 dp_gui_master_cntl; + CARD32 sc_top_left_c; + CARD32 sc_bottom_right_c; + CARD32 z_offset_c; + CARD32 z_pitch_c; + CARD32 z_sten_cntl_c; + CARD32 tex_cntl_c; + CARD32 misc_3d_state_cntl_reg; + CARD32 texture_clr_cmp_clr_c; + CARD32 texture_clr_cmp_msk_c; + CARD32 fog_color_c; + CARD32 prim_tex_cntl_c; + CARD32 prim_texture_combine_cntl_c; + CARD32 tex_size_pitch_c; + CARD32 prim_tex_offset[R128_TEX_MAXLEVELS]; /* 0x1ce4 */ + + CARD32 sec_tex_cntl_c; /* 0x1d00 */ + CARD32 sec_tex_combine_cntl_c; + CARD32 sec_tex_offset[R128_TEX_MAXLEVELS]; + CARD32 constant_color_c; + CARD32 prim_texture_border_color_c; + CARD32 sec_texture_border_color_c; + CARD32 sten_ref_mask_c; + CARD32 plane_3d_mask_c; /* 0x1d44 */ + + CARD32 setup_cntl; /* 0x1bc4 */ + + CARD32 pm4_vc_fpu_setup; /* 0x071c */ + + CARD32 fog_3d_table_start; /* 0x1810 */ + CARD32 fog_3d_table_end; + CARD32 fog_3d_table_density; /* 0x181c */ + + CARD32 window_xy_offset; /* 0x1bcc */ + + CARD32 dp_write_mask; /* 0x16cc */ + + CARD32 pc_gui_ctlstat; /* 0x1748 */ +} r128ContextRegs; + +typedef struct { + GLcontext *glCtx; /* Mesa context */ + int dirty; /* Hardware state to be updated */ + int dirty_context; /* Context state to be updated */ + + int SWonly; /* Force software-only rendering */ + int SWfallbackDisable; /* Disable software fallbacks */ + + r128TexObjPtr CurrentTexObj[2]; /* Ptr to current texture + object associated with + each texture unit */ + /* List of tex swapped in per heap*/ + r128TexObj TexObjList[R128_NR_TEX_HEAPS]; + r128TexObj SwappedOut; /* List of textures swapped out */ + memHeap_t *texHeap[R128_NR_TEX_HEAPS]; /* Global tex heaps */ + /* Last known global tex heap ages */ + int lastTexAge[R128_NR_TEX_HEAPS]; + + CARD32 lastSwapAge; /* Last known swap age */ + + GLenum FogMode; /* Current fog equation */ + + int Scissor; + XF86DRIClipRectRec ScissorRect; /* Current software scissor */ + + int useFastPath; /* Currently using Fast Path code */ + int SetupIndex; /* Raster setup function index */ + int SetupDone; /* Partial raster setup done? */ + int RenderIndex; /* Render state function index */ + r128InterpFunc interp; /* Current vert interp function */ + + r128CCEVertBuf vb; /* VB currently being filled */ + int disableVB; /* Disable the use of vertex buffers */ + + points_func PointsFunc; /* Current Points, Line, Triangle */ + line_func LineFunc; /* and Quad rendering functions */ + triangle_func TriangleFunc; + quad_func QuadFunc; + + CARD32 IndirectTriangles; /* Flags for point, line, + tri and quad software + fallbacks */ + CARD32 Fallback; /* Need software fallback */ + + r128ContextRegs regs; /* Hardware state */ + CARD32 Color; /* Current draw color */ + CARD32 ClearColor; /* Color used to clear color buffer */ + CARD32 ClearDepth; /* Value used to clear depth buffer */ + + int drawX; /* x-offset to current draw buffer */ + int drawY; /* y-offset to current draw buffer */ + + int readX; /* x-offset to current read buffer */ + int readY; /* y-offset to current read buffer */ + + CARD32 *CCEbuf; /* buffer to submit to CCE */ + int CCEcount; /* number of dwords in CCEbuf */ + + int CCEtimeout; /* number of times to loop + before exiting */ + + Display *display; /* X server display */ + + __DRIcontextPrivate *driContext; /* DRI context */ + __DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */ + + r128ScreenPtr r128Screen; /* Screen private DRI data */ +} r128ContextRec, *r128ContextPtr; + +#define R128_MESACTX(r128ctx) ((r128ctx)->glCtx) +#define R128_DRIDRAWABLE(r128ctx) ((r128ctx)->driDrawable) +#define R128_DRISCREEN(r128ctx) ((r128ctx)->r128Screen->driScreen) + +extern GLboolean r128CreateContext(Display *dpy, GLvisual *glVisual, + __DRIcontextPrivate *driContextPriv); +extern void r128DestroyContext(r128ContextPtr r128ctx); +extern r128ContextPtr r128MakeCurrent(r128ContextPtr oldCtx, + r128ContextPtr newCtx, + __DRIdrawablePrivate *dPriv); + +#endif +#endif /* _R128_CONTEXT_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_dd.c b/xc/lib/GL/mesa/src/drv/r128/r128_dd.c new file mode 100644 index 000000000..0ed7ae471 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_dd.c @@ -0,0 +1,182 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_cce.h" +#include "r128_clear.h" +#include "r128_state.h" +#include "r128_vb.h" +#include "r128_pipeline.h" +#include "r128_dd.h" + +/* Driver entry point for clearing color and ancillary buffers */ +static GLbitfield r128DDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint x, GLint y, GLint width, GLint height) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + if (r128ctx->SWonly) { + /* FIXME: Provide software fallback for this case?? */ + } + + if (mask & DD_FRONT_LEFT_BIT) { + r128ClearColorBuffer(r128ctx, all, x, y, width, height, + r128ctx->r128Screen->fbX, + r128ctx->r128Screen->fbY); + mask &= ~DD_FRONT_LEFT_BIT; + } + + if (mask & DD_BACK_LEFT_BIT) { + r128ClearColorBuffer(r128ctx, all, x, y, width, height, + r128ctx->r128Screen->backX, + r128ctx->r128Screen->backY); + mask &= ~DD_BACK_LEFT_BIT; + } + + if (mask & DD_DEPTH_BIT) { + r128ClearDepthBuffer(r128ctx, all, x, y, width, height); + mask &= ~DD_DEPTH_BIT; + } + +#if 0 + /* FIXME: Add stencil support */ + if (mask & DD_STENCIL_BIT) { + r128ClearStencilBuffer(r128ctx, all, x, y, width, height); + mask &= ~DD_STENCIL_BIT; + } +#endif + + return mask; +} + +/* Return the current color buffer size */ +static void r128DDGetBufferSize(GLcontext *ctx, GLuint *width, GLuint *height) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + *width = r128ctx->driDrawable->w; + *height = r128ctx->driDrawable->h; +} + +/* Return various strings for glGetString() */ +static const GLubyte *r128DDGetString(GLcontext *ctx, GLenum name) +{ + switch (name) { + case GL_VENDOR: + return (GLubyte *)"Precision Insight, Inc."; + case GL_RENDERER: + return (GLubyte *)"Mesa DRI Rage128 20000320"; + default: + return NULL; + } +} + +/* Send all commands to the hardware. If vertex buffers or indirect + buffers are in use, then we need to make sure they are sent to the + hardware. All commands that are normally sent to the ring are + already considered `flushed'. */ +static void r128DDFlush(GLcontext *ctx) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + R128CCE_FLUSH_VB_LOCK(r128ctx); +} + +/* Make sure all commands have been sent to the hardware and have + completed processing. */ +static void r128DDFinish(GLcontext *ctx) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + r128DDFlush(ctx); + R128CCE_WAIT_FOR_IDLE_LOCK(r128ctx); +} + +/* Return various parameters requested by Mesa */ +static GLint r128DDGetParameteri(const GLcontext *ctx, GLint param) +{ + switch (param) { +#if 0 + /* FIXME: Support for these needs to be added to Mesa */ + case DD_MAX_TEXTURE_SIZE: return 1024; + case DD_MAX_TEXTURES: return 2; +#endif +#if 0 + case DD_HAVE_HARDWARE_FOG: return 1; /* FIXME: Add HW fog support */ +#endif + default: return 0; + } +} + +/* Initialize the extensions supported by this driver */ +void r128DDInitExtensions(GLcontext *ctx) +{ + /* FIXME: Are there other extensions to enable/disable??? */ + gl_extensions_disable(ctx, "GL_EXT_shared_texture_palette"); + gl_extensions_disable(ctx, "GL_EXT_paletted_texture"); + gl_extensions_disable(ctx, "GL_EXT_point_parameters"); + gl_extensions_disable(ctx, "ARB_imaging"); + gl_extensions_disable(ctx, "GL_EXT_blend_minmax"); + gl_extensions_disable(ctx, "GL_EXT_blend_logic_op"); + gl_extensions_disable(ctx, "GL_EXT_blend_subtract"); + gl_extensions_disable(ctx, "GL_INGR_blend_func_separate"); + + if (getenv("LIBGL_NO_MULTITEXTURE")) + gl_extensions_disable(ctx, "GL_ARB_multitexture"); +} + +/* Initialize the driver's misc functions */ +void r128DDInitDriverFuncs(GLcontext *ctx) +{ + ctx->Driver.Clear = r128DDClear; + + ctx->Driver.GetBufferSize = r128DDGetBufferSize; + ctx->Driver.GetString = r128DDGetString; + ctx->Driver.Finish = r128DDFinish; + ctx->Driver.Flush = r128DDFlush; + + ctx->Driver.Error = NULL; + ctx->Driver.GetParameteri = r128DDGetParameteri; + + ctx->Driver.DrawPixels = NULL; + ctx->Driver.Bitmap = NULL; + + ctx->Driver.RegisterVB = r128DDRegisterVB; + ctx->Driver.UnregisterVB = r128DDUnregisterVB; + ctx->Driver.BuildPrecalcPipeline = r128DDBuildPrecalcPipeline; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_dd.h b/xc/lib/GL/mesa/src/drv/r128/r128_dd.h new file mode 100644 index 000000000..91aa02586 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_dd.h @@ -0,0 +1,44 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_DD_H_ +#define _R128_DD_H_ + +#ifdef GLX_DIRECT_RENDERING + +extern void r128DDInitExtensions(GLcontext *ctx); +extern void r128DDInitDriverFuncs(GLcontext *ctx); + +#endif +#endif /* _R128_DD_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c new file mode 100644 index 000000000..330e5a23d --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c @@ -0,0 +1,551 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_state.h" +#include "r128_vb.h" +#include "r128_tris.h" +#include "r128_fastpath.h" + +#include "mmath.h" +#include "cva.h" +#include "vertices.h" + +/* FIXME: These routines were copied from the i810 driver, and were only + slightly modified for the Rage 128. They still need to be optmizied + and cleaned up. Also, support for USE_RHW2 needs to be added. */ + +typedef struct r128_fast_table { + r128BuildVerticesFunc build_vertices; + r128InterpFunc interp; +} r128FastPathTable; + +#define POINT(x) r128DrawPointVB(r128ctx, &vert[x].v, psize) +#define LINE(x,y) r128DrawLineVB(r128ctx, &vert[x].v, &vert[y].v, lwidth) +#define TRI(x,y,z) r128DrawTriangleVB(r128ctx, &vert[x].v, &vert[y].v, &vert[z].v) + +/* Direct, and no clipping required. The clip funcs have not been + written yet, so this is only useful for the fast path. */ +#define RENDER_POINTS(start, count) \ +do { \ + GLuint e; \ + for (e = start; e <= count; e++) \ + POINT(elt[e]); \ +} while (0) + +#define RENDER_LINE(i1, i) \ +do { \ + GLuint e1 = elt[i1], e = elt[i]; \ + LINE(e1, e); \ +} while (0) + +#define RENDER_TRI(i2, i1, i, pv, parity) \ +do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ + if (parity) { \ + GLuint tmp = e2; \ + e2 = e1; \ + e1 = tmp; \ + } \ + TRI(e2, e1, e); \ +} while (0) + +#define RENDER_QUAD(i3, i2, i1, i, pv) \ +do { \ + GLuint e3 = elt[i3], e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ + TRI(e3, e2, e); \ + TRI(e2, e1, e); \ +} while (0) + +#define LOCAL_VARS \ + r128VertexPtr vert = R128_DRIVER_DATA(VB)->verts; \ + const GLuint *elt = VB->EltPtr->data; \ + GLcontext *ctx = VB->ctx; \ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); \ + const GLfloat lwidth = ctx->Line.Width; \ + const GLfloat psize = ctx->Point.Size; \ + (void) lwidth; (void)psize; (void) vert; + +#define TAG(x) x##_r128_smooth_indirect +#include "render_tmp.h" + + + +#define NEGATIVE(f) (f < 0) +#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) +#define LINTERP(T, A, B) ((A) + (T) * ((B) - (A))) + + +#define INTERP_RGBA(t, out, a, b) \ +do { \ + int i; \ + for (i = 0; i < 4; i++) { \ + GLfloat fa = UBYTE_COLOR_TO_FLOAT_COLOR(a[i]); \ + GLfloat fb = UBYTE_COLOR_TO_FLOAT_COLOR(b[i]); \ + GLfloat fo = LINTERP(t, fa, fb); \ + FLOAT_COLOR_TO_UBYTE_COLOR(out[i], fo); \ + } \ +} while (0) + + +#define CLIP(SGN, V, PLANE) \ +do { \ + if (mask & PLANE) { \ + GLuint *indata = inlist[in]; \ + GLuint *outdata = inlist[in ^= 1]; \ + GLuint nr = n; \ + GLfloat *J = verts[indata[nr-1]].f; \ + GLfloat dpJ = (SGN J[V]) + J[3]; \ + \ + inlist[0] = vlist1; \ + for (i = n = 0 ; i < nr ; i++) { \ + GLuint elt_i = indata[i]; \ + GLfloat *I = verts[elt_i].f; \ + GLfloat dpI = (SGN I[V]) + I[3]; \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLfloat *O = verts[next_vert].f; \ + GLfloat t, *in, *out; \ + \ + if (NEGATIVE(dpI)) { \ + t = dpI / (dpI - dpJ); \ + in = I; \ + out = J; \ + } else { \ + t = dpJ / (dpJ - dpI); \ + in = J; \ + out = I; \ + } \ + \ + interp(t, O, in, out); \ + \ + clipmask[next_vert] = 0; \ + outdata[n++] = next_vert++; \ + } \ + \ + clipmask[elt_i] |= PLANE; /* don't set up */ \ + \ + if (!NEGATIVE(dpI)) { \ + outdata[n++] = elt_i; \ + clipmask[elt_i] &= ~PLANE; /* set up after all */ \ + } \ + \ + J = I; \ + dpJ = dpI; \ + } \ + \ + if (n < 3) return; \ + } \ +} while (0) + +#define LINE_CLIP(x,y,z,w,PLANE) \ +do { \ + if (mask & PLANE) { \ + GLfloat dpI = DOT4V(I,x,y,z,w); \ + GLfloat dpJ = DOT4V(J,x,y,z,w); \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLfloat *O = verts[next_vert].f; \ + GLfloat t = dpI / (dpI - dpJ); \ + \ + interp(t, O, I, J); \ + \ + clipmask[next_vert] = 0; \ + \ + if (NEGATIVE(dpI)) { \ + clipmask[elts[0]] |= PLANE; \ + I = O; \ + elts[0] = next_vert++; \ + } else { \ + clipmask[elts[1]] |= PLANE; \ + J = O; \ + elts[1] = next_vert++; \ + } \ + } else if (NEGATIVE(dpI)) return; \ + } \ +} while (0) + + +static void r128TriClip(GLuint **p_elts, + r128Vertex *verts, + GLubyte *clipmask, + GLuint *p_next_vert, + GLubyte mask, + r128InterpFunc interp) +{ + GLuint *elts = *p_elts; + GLuint next_vert = *p_next_vert; + GLuint in = 0; + GLuint n = 3; + GLuint vlist1[VB_MAX_CLIPPED_VERTS]; + GLuint vlist2[VB_MAX_CLIPPED_VERTS]; + GLuint *inlist[2]; + GLuint *out; + GLuint i; + + inlist[0] = elts; + inlist[1] = vlist2; + + CLIP(-,0,CLIP_RIGHT_BIT); + CLIP(+,0,CLIP_LEFT_BIT); + CLIP(-,1,CLIP_TOP_BIT); + CLIP(+,1,CLIP_BOTTOM_BIT); + CLIP(-,2,CLIP_FAR_BIT); + CLIP(+,2,CLIP_NEAR_BIT); + + /* Convert the planar polygon to a list of triangles */ + out = inlist[in]; + + for (i = 2 ; i < n ; i++) { + elts[0] = out[0]; + elts[1] = out[i-1]; + elts[2] = out[i]; + elts += 3; + } + + *p_next_vert = next_vert; + *p_elts = elts; +} + + +static void r128LineClip(GLuint **p_elts, + r128Vertex *verts, + GLubyte *clipmask, + GLuint *p_next_vert, + GLubyte mask, + r128InterpFunc interp) +{ + GLuint *elts = *p_elts; + GLfloat *I = verts[elts[0]].f; + GLfloat *J = verts[elts[1]].f; + GLuint next_vert = *p_next_vert; + + LINE_CLIP(1,0,0,-1,CLIP_LEFT_BIT); + LINE_CLIP(-1,0,0,1,CLIP_RIGHT_BIT); + LINE_CLIP(0,1,0,-1,CLIP_TOP_BIT); + LINE_CLIP(0,-1,0,1,CLIP_BOTTOM_BIT); + LINE_CLIP(0,0,1,-1,CLIP_FAR_BIT); + LINE_CLIP(0,0,-1,1,CLIP_NEAR_BIT); + + *p_next_vert = next_vert; + *p_elts += 2; +} + + + +#define CLIP_POINT(e) \ +do { \ + if (mask[e]) *out++ = e; \ +} while (0) + +#define CLIP_LINE(e1, e0) \ +do { \ + GLubyte ormask = mask[e0] | mask[e1]; \ + out[0] = e1; \ + out[1] = e0; \ + out += 2; \ + if (ormask) { \ + out-=2; \ + if (!(mask[e0] & mask[e1])) { \ + r128LineClip(&out, verts, mask, &next_vert, ormask, interp); \ + } \ + } \ +} while (0) + +#define CLIP_TRIANGLE(e2, e1, e0) \ +do { \ + GLubyte ormask; \ + out[0] = e2; \ + out[1] = e1; \ + out[2] = e0; \ + out += 3; \ + ormask = mask[e2] | mask[e1] | mask[e0]; \ + if (ormask) { \ + out -= 3; \ + if (!(mask[e2] & mask[e1] & mask[e0])) { \ + r128TriClip(&out, verts, mask, &next_vert, ormask, interp); \ + } \ + } \ +} while (0) + + + +/* Build a table of functions to clip each primitive type. These + * produce a list of elements in the appropriate 'reduced' primitive, + * ie (points, lines, triangles) containing all the clipped and + * unclipped primitives from the original list. + */ +#define LOCAL_VARS \ + r128ContextPtr r128ctx = R128_CONTEXT(VB->ctx); \ + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); \ + GLuint *elt = VB->EltPtr->data; \ + r128Vertex *verts = r128VB->verts; \ + GLuint next_vert = r128VB->last_vert; \ + GLuint *out = r128VB->clipped_elements.data; \ + GLubyte *mask = VB->ClipMask; \ + r128InterpFunc interp = r128ctx->interp; \ + (void) interp; (void) verts; + +#define POSTFIX \ + r128VB->clipped_elements.count = out - r128VB->clipped_elements.data; \ + r128VB->last_vert = next_vert; + + +#define INIT(x) + +#define RENDER_POINTS(start, count) \ +do { \ + GLuint i; \ + for (i = start; i < count; i++) \ + CLIP_POINT(elt[i]); \ +} while (0) + +#define RENDER_LINE(i1, i0) \ +do { \ + CLIP_LINE(elt[i1], elt[i0]); \ +} while (0) + +#define RENDER_TRI(i2, i1, i0, pv, parity) \ +do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e0 = elt[i0]; \ + if (parity) e2 = elt[i1], e1 = elt[i2]; \ + CLIP_TRIANGLE(e2, e1, e0); \ +} while (0) + +#define RENDER_QUAD(i3, i2, i1, i0, pv) \ +do { \ + CLIP_TRIANGLE(elt[i3], elt[i2], elt[i0]); \ + CLIP_TRIANGLE(elt[i2], elt[i1], elt[i0]); \ +} while (0) + +#define TAG(x) r128_clip_##x##_elt +#include "render_tmp.h" + + +/* Pack rgba and/or texture into the remaining half of a 32 byte vertex. + */ +#define CLIP_UBYTE_COLOR 4 +#define CLIP_UBYTE_B 0 +#define CLIP_UBYTE_G 1 +#define CLIP_UBYTE_R 2 +#define CLIP_UBYTE_A 3 +#define CLIP_S0 6 +#define CLIP_T0 7 +#define CLIP_S1 8 +#define CLIP_T1 9 + +#define TYPE (0) +#define TAG(x) x +#include "r128_fasttmp.h" + +#define TYPE (R128_RGBA_BIT) +#define TAG(x) x##_RGBA +#include "r128_fasttmp.h" + +#define TYPE (R128_TEX0_BIT) +#define TAG(x) x##_TEX0 +#include "r128_fasttmp.h" + +#define TYPE (R128_RGBA_BIT | R128_TEX0_BIT) +#define TAG(x) x##_RGBA_TEX0 +#include "r128_fasttmp.h" + +#define TYPE (R128_RGBA_BIT | R128_TEX0_BIT | R128_TEX1_BIT) +#define TAG(x) x##_RGBA_TEX0_TEX1 +#include "r128_fasttmp.h" + +/* This one *could* get away with sneaking TEX1 into the color and + * specular slots, thus fitting inside a cache line. Would be even + * better to switch to a smaller vertex. + */ +#define TYPE (R128_TEX0_BIT | R128_TEX1_BIT) +#define TAG(x) x##_TEX0_TEX1 +#include "r128_fasttmp.h" + + + +/* Render elements directly from original list of vertices. */ +static void r128RenderElementsDirect(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + GLenum prim = ctx->CVA.elt_mode; + GLuint nr = VB->EltPtr->count; + render_func func = render_tab_r128_smooth_indirect[prim]; + GLuint p = 0; + + if (r128ctx->dirty) r128UpdateHWState(r128ctx); + + do { + func(VB, 0, nr, 0); + } while (ctx->Driver.MultipassFunc && + ctx->Driver.MultipassFunc(VB, ++p)); +} + +/* Project vertices from clip to device space */ +static void r128ProjectVertices(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + GLmatrix *mat = &ctx->Viewport.WindowMap; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); + GLfloat m[16]; + + m[MAT_SX] = mat->m[MAT_SX]; + m[MAT_TX] = mat->m[MAT_TX]; + m[MAT_SY] = -mat->m[MAT_SY]; + m[MAT_TY] = -mat->m[MAT_TY] + r128ctx->driDrawable->h; + m[MAT_SZ] = mat->m[MAT_SZ]; + m[MAT_TZ] = mat->m[MAT_TZ]; + + switch (ctx->Visual->DepthBits) { + case 16: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; + case 24: m[MAT_SZ] /= 16777216.0; m[MAT_TZ] /= 16777216.0; break; + case 32: m[MAT_SZ] /= 4294967296.0; m[MAT_TZ] /= 4294967296.0; break; + default: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; + } + +#if USE_RHW2 + /* FIXME: Handle RHW2?? */ + gl_project_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4); +#else + gl_project_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4); +#endif +} + +/* Project clipped vertices from clip to device space */ +static void r128ProjectClippedVertices(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + GLmatrix *mat = &ctx->Viewport.WindowMap; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); + GLfloat m[16]; + + m[MAT_SX] = mat->m[MAT_SX]; + m[MAT_TX] = mat->m[MAT_TX]; + m[MAT_SY] = -mat->m[MAT_SY]; + m[MAT_TY] = -mat->m[MAT_TY] + r128ctx->driDrawable->h; + m[MAT_SZ] = mat->m[MAT_SZ]; + m[MAT_TZ] = mat->m[MAT_TZ]; + + switch (ctx->Visual->DepthBits) { + case 16: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; + case 24: m[MAT_SZ] /= 16777216.0; m[MAT_TZ] /= 16777216.0; break; + case 32: m[MAT_SZ] /= 4294967296.0; m[MAT_TZ] /= 4294967296.0; break; + default: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; + } + +#if USE_RHW2 + /* FIXME: Handle RHW2?? */ + gl_project_clipped_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4, + VB->ClipMask + VB->CopyStart); +#else + gl_project_clipped_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4, + VB->ClipMask + VB->CopyStart); +#endif +} + +static r128FastPathTable r128FastTab[0x80]; + +/* Initialize the table of fast path support functions */ +void r128FastPathInit(void) +{ + r128_clip_render_init_elt(); + render_init_r128_smooth_indirect(); + + r128_init_fastpath(&r128FastTab[0]); + r128_init_fastpath_RGBA(&r128FastTab[R128_RGBA_BIT]); + r128_init_fastpath_TEX0(&r128FastTab[R128_TEX0_BIT]); + r128_init_fastpath_RGBA_TEX0(&r128FastTab[R128_RGBA_BIT|R128_TEX0_BIT]); + r128_init_fastpath_TEX0_TEX1(&r128FastTab[R128_TEX0_BIT|R128_TEX1_BIT]); + r128_init_fastpath_RGBA_TEX0_TEX1(&r128FastTab[R128_RGBA_BIT|R128_TEX0_BIT| + R128_TEX1_BIT]); +} + +#define VALID_SETUP (R128_RGBA_BIT | R128_TEX0_BIT | R128_TEX1_BIT) + +void r128FastPath(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + GLenum prim = ctx->CVA.elt_mode; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128FastPathTable *tab = &r128FastTab[r128ctx->SetupIndex & VALID_SETUP]; + GLuint do_cliptest = 1; + + gl_prepare_arrays_cva(VB); /* still need this */ + + /* Reserve enough space for the pathological case */ + if (VB->EltPtr->count * 12 > R128_DRIVER_DATA(VB)->size) { + r128ResizeVB(VB, VB->EltPtr->count * 12); + do_cliptest = 1; + } + + tab->build_vertices(VB, do_cliptest); /* object->clip space */ + + if (r128ctx->dirty) r128UpdateHWState(r128ctx); + + if (VB->ClipOrMask) { + if (!VB->ClipAndMask) { + render_func *clip = r128_clip_render_tab_elt; + + r128ctx->interp = tab->interp; + clip[prim](VB, 0, VB->EltPtr->count, 0); /* build new elts */ + ctx->CVA.elt_mode = gl_reduce_prim[prim]; + VB->EltPtr = &(R128_DRIVER_DATA(VB)->clipped_elements); + r128ProjectClippedVertices(VB); /* clip->device space */ + r128RenderElementsDirect(VB); /* render using new list */ + } + } else { + r128ProjectVertices(VB); /* clip->device space */ + r128RenderElementsDirect(VB); /* render using orig list */ + } + + /* This indicates that there is no cached data to reuse */ + VB->pipeline->data_valid = 0; + VB->pipeline->new_state = 0; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.h b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.h new file mode 100644 index 000000000..47bb92049 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.h @@ -0,0 +1,48 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_FASTPATH_H_ +#define _R128_FASTPATH_H_ + +typedef void (*r128BuildVerticesFunc)(struct vertex_buffer *VB, + GLuint do_cliptest); +typedef void (*r128InterpFunc)(GLfloat t, + GLfloat *result, + const GLfloat *in, + const GLfloat *out); + +extern void r128FastPathInit(void); +extern void r128FastPath(struct vertex_buffer *VB); + +#endif /* _R128_FASTPATH_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_fasttmp.h b/xc/lib/GL/mesa/src/drv/r128/r128_fasttmp.h new file mode 100644 index 000000000..e76dd52b4 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_fasttmp.h @@ -0,0 +1,155 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +/* FIXME: These routines were copied from the i810 driver, and were only + slightly modified for the Rage 128. They still need to be optmizied + and cleaned up. Also, support for USE_RHW2 needs to be added. */ + +/* The first part of setup is applied to all vertices, clipped or + * unclipped. This data w!ill be used for clipping, and then all + * vertices with a zero clipmask will be projected to device space. + * + * This could be split into several loops, but - it seems that the + * large stride of the fxVertices makes cache issues the big + * performance factor, and that multiple loops mean multiple cache + * misses.... + */ +static void TAG(r128_setup_full)(struct vertex_buffer *VB, GLuint do_cliptest) +{ + GLcontext *ctx = VB->ctx; + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); + const GLfloat *m = ctx->ModelProjectMatrix.m; + GLuint start = VB->CopyStart; + GLuint count = VB->Count; + GLuint i; + + gl_xform_points3_v16_general(r128VB->verts[start].f, + m, + VB->ObjPtr->start, + VB->ObjPtr->stride, + count - start); + + if (do_cliptest) { + VB->ClipAndMask = ~0; + VB->ClipOrMask = 0; + gl_cliptest_points4_v16(r128VB->verts[start].f, + r128VB->verts[count].f, + &(VB->ClipOrMask), + &(VB->ClipAndMask), + VB->ClipMask + start); + } + + /* These branches are all resolved at compile time. Hopefully all + * the pointers are valid addresses even when not enabled. + */ + if (TYPE) { + GLubyte *color = VB->ColorPtr->start; + GLfloat *tex0_data = VB->TexCoordPtr[0]->start; + GLfloat *tex1_data = VB->TexCoordPtr[1]->start; + + GLuint color_stride = VB->ColorPtr->stride; + GLuint tex0_stride = VB->TexCoordPtr[0]->stride; + GLuint tex1_stride = VB->TexCoordPtr[1]->stride; + + GLfloat *f = r128VB->verts[start].f; + + for (i = start ; i < count ; i++, f += 16) { + if (TYPE & R128_RGBA_BIT) { + GLubyte *b = (GLubyte *)&f[CLIP_UBYTE_COLOR]; + GLubyte *col = color; color += color_stride; + b[CLIP_UBYTE_R] = col[0]; + b[CLIP_UBYTE_G] = col[1]; + b[CLIP_UBYTE_B] = col[2]; + b[CLIP_UBYTE_A] = col[3]; + } + if (TYPE & R128_TEX0_BIT) { + f[CLIP_S0] = tex0_data[0]; + f[CLIP_T0] = tex0_data[1]; + STRIDE_F(tex0_data, tex0_stride); + } + if (TYPE & R128_TEX1_BIT) { + f[CLIP_S1] = tex1_data[0]; + f[CLIP_T1] = tex1_data[1]; + STRIDE_F(tex1_data, tex1_stride); + } + } + } + + r128VB->clipped_elements.count = start; + r128VB->last_vert = count; +} + + +/* Changed to just put the interp func instead of the whole clip + * routine into the header. Less code and better chance of doing some + * of this stuff in assembly. + */ +static void TAG(r128_interp_vert)(GLfloat t, + GLfloat *O, + const GLfloat *I, + const GLfloat *J) +{ + O[0] = LINTERP(t, I[0], J[0]); + O[1] = LINTERP(t, I[1], J[1]); + O[2] = LINTERP(t, I[2], J[2]); + O[3] = LINTERP(t, I[3], J[3]); + + if (TYPE & R128_RGBA_BIT) { + INTERP_RGBA(t, + ((GLubyte *)&(O[4])), + ((GLubyte *)&(I[4])), + ((GLubyte *)&(J[4]))); + } + + if (TYPE & R128_TEX0_BIT) { + O[6] = LINTERP(t, I[6], J[6]); + O[7] = LINTERP(t, I[7], J[7]); + } + + if (TYPE & R128_TEX1_BIT) { + O[8] = LINTERP(t, I[8], J[8]); + O[9] = LINTERP(t, I[9], J[9]); + } +} + + +static void TAG(r128_init_fastpath)(r128FastPathTable *tab) +{ + tab->build_vertices = TAG(r128_setup_full); + tab->interp = TAG(r128_interp_vert); +} + +#undef TYPE +#undef TAG +#undef SIZE diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_init.h b/xc/lib/GL/mesa/src/drv/r128/r128_init.h new file mode 100644 index 000000000..fcaf70a51 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_init.h @@ -0,0 +1,92 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_INIT_H_ +#define _R128_INIT_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include <X11/Xlibint.h> + +#include "types.h" +#include "xf86drm.h" +#include "dri_tmm.h" +#include "dri_mesaint.h" + +#include "r128_screen.h" +#include "r128_context.h" + +/* NOTE: The vertex buffer code is currently unstable because of the + switches between CCE and MMIO mode in the X server. Fixing the X + server to use the CCE should fix this problem. So, for now, it is + recommended that you do not use it. */ + +#define DEBUG 1 +#define DEBUG_LOCKING 1 +#define USE_FAST_PATH 1 +#define USE_USER_SPACE_RING 0 + + +#if DEBUG + +#include <stdio.h> +#define R128_DEBUG(p) \ + do { \ + printf p ; \ + fflush(stdout); \ + } while (0) + +extern int R128_DEBUG_FLAGS; + +#define DEBUG_VERBOSE_2D 0x0001 +#define DEBUG_VERBOSE_CCE 0x0008 +#define DEBUG_VERBOSE_OUTREG 0x0010 +#define DEBUG_ALWAYS_SYNC 0x0040 +#define DEBUG_VERBOSE_MSG 0x0080 +#define DEBUG_NO_OUTRING 0x0100 +#define DEBUG_NO_OUTREG 0x0200 +#define DEBUG_VERBOSE_API 0x0400 +#define DEBUG_VALIDATE_RING 0x0800 +#define DEBUG_VERBOSE_LRU 0x1000 +#define DEBUG_VERBOSE_DRI 0x2000 +#define DEBUG_VERBOSE_IOCTL 0x4000 + +#else + +#define R128_DEBUG_FLAGS 0 + +#endif + +#endif +#endif /* _R128_INIT_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_lock.h b/xc/lib/GL/mesa/src/drv/r128/r128_lock.h new file mode 100644 index 000000000..7fd81f807 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_lock.h @@ -0,0 +1,134 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_LOCK_H_ +#define _R128_LOCK_H_ + +#ifdef GLX_DIRECT_RENDERING + +/* Turn DEBUG_LOCKING on to find locking conflicts (see r128_init.h) */ +#if DEBUG_LOCKING +extern char *prevLockFile; +extern int prevLockLine; + +#define DEBUG_LOCK() \ + do { \ + prevLockFile = (__FILE__); \ + prevLockLine = (__LINE__); \ + } while (0) + +#define DEBUG_RESET() \ + do { \ + prevLockFile = 0; \ + prevLockLine = 0; \ + } while (0) + +#define DEBUG_CHECK_LOCK() \ + do { \ + if (prevLockFile) { \ + fprintf(stderr, \ + "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \ + prevLockFile, prevLockLine, __FILE__, __LINE__); \ + exit(1); \ + } \ + } while (0) + +#else + +#define DEBUG_LOCK() +#define DEBUG_RESET() +#define DEBUG_CHECK_LOCK() + +#endif + +/* + * !!! We may want to separate locks from locks with validation. This + * could be used to improve performance for those things commands that + * do not do any drawing !!! + */ + +/* Lock the hardware using the current context */ +#define LOCK_HARDWARE(CC) \ + do { \ + char __ret = 0; \ + __DRIcontextPrivate *cPriv = CC->driContext; \ + __DRIscreenPrivate *sPriv = CC->r128Screen->driScreen; \ + \ + DEBUG_CHECK_LOCK(); \ + DRM_CAS(&sPriv->pSAREA->lock, cPriv->hHWContext, \ + DRM_LOCK_HELD|cPriv->hHWContext, __ret); \ + if (__ret) { \ + /* We lost the context, so we need to request the lock from \ + the kernel and update our state. */ \ + drmGetLock(sPriv->fd, cPriv->hHWContext, 0); \ + XMesaUpdateState(cPriv); \ + } \ + DEBUG_LOCK(); \ + } while (0) + +/* Unlock the hardware using the current context */ +#define UNLOCK_HARDWARE(CC) \ + do { \ + __DRIcontextPrivate *cPriv = CC->driContext; \ + __DRIscreenPrivate *sPriv = CC->r128Screen->driScreen; \ + \ + DRM_UNLOCK(sPriv->fd, &sPriv->pSAREA->lock, cPriv->hHWContext); \ + DEBUG_RESET(); \ + } while (0) + +/* + * This pair of macros makes a loop over the drawing operations, so it + * is not self contained and does not have the nice single statement + * semantics of most macros. + */ +#define BEGIN_CLIP_LOOP(CC) \ + do { \ + __DRIdrawablePrivate *_dPriv = CC->driDrawable; \ + XF86DRIClipRectPtr _pc = _dPriv->pClipRects; \ + int _nc, _sc; \ + \ + for (_nc = _dPriv->numClipRects; _nc > 0; _nc -= 3, _pc += 3) { \ + _sc = (_nc <= 3) ? _nc : 3; \ + r128SetClipRects(CC, _pc, _sc) + +/* FIXME: This should be a function call to turn off aux clipping */ +#define END_CLIP_LOOP(CC) \ + R128CCE0(R128_CCE_PACKET0, R128_AUX_SC_CNTL, 0); \ + R128CCE(0x00000000); \ + R128CCE_SUBMIT_PACKETS(); \ + } \ + } while (0) + +#endif +#endif /* _R128_LOCK_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_mesa.h b/xc/lib/GL/mesa/src/drv/r128/r128_mesa.h new file mode 100644 index 000000000..3a697b466 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_mesa.h @@ -0,0 +1,43 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_MESA_H_ +#define _R128_MESA_H_ + +#ifdef GLX_DIRECT_RENDERING + +#define R128_CONTEXT(ctx) ((r128ContextPtr)(ctx->DriverCtx)) + +#endif +#endif /* _R128_MESA_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.c b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.c new file mode 100644 index 000000000..55487ffcd --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.c @@ -0,0 +1,126 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_vb.h" +#include "r128_fastpath.h" +#include "r128_pipeline.h" + +#include "types.h" + +static struct gl_pipeline_stage r128FastStage = { + "R128 Fast Path", + (PIPE_OP_VERT_XFORM | + PIPE_OP_RAST_SETUP_0 | + PIPE_OP_RAST_SETUP_1 | + PIPE_OP_RENDER), + PIPE_PRECALC, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + r128FastPath +}; + +/* Build the PRECALC pipeline with our stage, if possible. Otherwise, + return GL_FALSE */ +GLboolean r128DDBuildPrecalcPipeline(GLcontext *ctx) +{ +#if USE_FAST_PATH + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + struct gl_pipeline *pipe = &ctx->CVA.pre; + + if (r128ctx->RenderIndex == 0 && + !(ctx->Enabled & (TEXTURE0_3D | + TEXTURE1_3D | + ENABLE_TEXMAT0 | + ENABLE_TEXMAT1 | + ENABLE_TEXGEN0 | + ENABLE_TEXGEN1 | + ENABLE_USERCLIP | + ENABLE_LIGHT | + ENABLE_FOG)) && + (ctx->Array.Flags & (VERT_OBJ_234 | + VERT_TEX0_4 | + VERT_TEX1_4 | + VERT_ELT)) == (VERT_OBJ_23 | + VERT_ELT)) { + pipe->stages[0] = &r128FastStage; + pipe->stages[1] = 0; + pipe->new_inputs = ctx->RenderFlags & VERT_DATA; + pipe->ops = pipe->stages[0]->ops; + + r128ctx->useFastPath = GL_TRUE; + return GL_TRUE; + } + + if (r128ctx->useFastPath) { + r128ctx->useFastPath = GL_FALSE; + + ctx->CVA.VB->ClipOrMask = 0; + ctx->CVA.VB->ClipAndMask = CLIP_ALL_BITS; + ctx->Array.NewArrayState |= ctx->Array.Summary; + } +#endif + + return GL_FALSE; +} + +/* Register the pipeline with our stages included */ +GLuint r128RegisterPipelineStages(struct gl_pipeline_stage *out, + const struct gl_pipeline_stage *in, + GLuint nr) +{ +#if USE_FAST_PATH + int i; + + for (i = 0; i < nr; i++) { + out[i] = in[i]; + switch (in[i].ops) { + case PIPE_OP_RAST_SETUP_0: + out[i].cva_state_change = (NEW_LIGHTING | + NEW_TEXTURING | + NEW_RASTER_OPS); + out[i].state_change = ~0; + out[i].check = r128CheckPartialRasterSetup; + out[i].run = r128PartialRasterSetup; + break; + + case PIPE_OP_RAST_SETUP_0|PIPE_OP_RAST_SETUP_1: + out[i].run = r128DoRasterSetup; + break; + } + } +#endif + + return nr; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.h b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.h new file mode 100644 index 000000000..280e6b943 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.h @@ -0,0 +1,43 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_PIPELINE_H_ +#define _R128_PIPELINE_H_ + +extern GLboolean r128DDBuildPrecalcPipeline(GLcontext *ctx); +extern GLuint r128RegisterPipelineStages(struct gl_pipeline_stage *out, + const struct gl_pipeline_stage *in, + GLuint nr); + +#endif /* _R128_PIPELINE_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_screen.c b/xc/lib/GL/mesa/src/drv/r128/r128_screen.c new file mode 100644 index 000000000..b385271f4 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_screen.c @@ -0,0 +1,258 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_dri.h" +#include "r128_reg.h" + +#include "r128_init.h" +#include "r128_context.h" +#include "r128_xmesa.h" +#include "r128_cce.h" +#include "r128_tris.h" +#include "r128_vb.h" +#include "r128_fastpath.h" + +#include <sys/mman.h> + +/* Create the device specific screen private data struct */ +r128ScreenPtr r128CreateScreen(__DRIscreenPrivate *sPriv) +{ + r128ScreenPtr r128Screen; + R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv; + + /* Allocate the private area */ + r128Screen = (r128ScreenPtr)Xmalloc(sizeof(*r128Screen)); + if (!r128Screen) return NULL; + + /* This is first since which regions we map depends on whether or + not we are using a PCI card */ + r128Screen->IsPCI = r128DRIPriv->IsPCI; + + r128Screen->mmioRgn.handle = r128DRIPriv->registerHandle; + r128Screen->mmioRgn.size = r128DRIPriv->registerSize; + if (drmMap(sPriv->fd, + r128Screen->mmioRgn.handle, + r128Screen->mmioRgn.size, + (drmAddressPtr)&r128Screen->mmio)) { + Xfree(r128Screen); + return NULL; + } + + if (!r128Screen->IsPCI) { + r128Screen->ringRgn.handle = r128DRIPriv->ringHandle; + r128Screen->ringRgn.size = r128DRIPriv->ringMapSize; + if (drmMap(sPriv->fd, + r128Screen->ringRgn.handle, + r128Screen->ringRgn.size, + (drmAddressPtr)&r128Screen->ring)) { + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + Xfree(r128Screen); + return NULL; + } + + r128Screen->ringReadRgn.handle = r128DRIPriv->ringReadPtrHandle; + r128Screen->ringReadRgn.size = r128DRIPriv->ringReadMapSize; + if (drmMap(sPriv->fd, + r128Screen->ringReadRgn.handle, + r128Screen->ringReadRgn.size, + (drmAddressPtr)&r128Screen->ringReadPtr)) { + drmUnmap((drmAddress)r128Screen->ring, r128Screen->ringRgn.size); + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + Xfree(r128Screen); + return NULL; + } + + r128Screen->vbRgn.handle = r128DRIPriv->vbHandle; + r128Screen->vbRgn.size = r128DRIPriv->vbMapSize; + r128Screen->vbOffset = r128DRIPriv->vbOffset; + if (drmMap(sPriv->fd, + r128Screen->vbRgn.handle, + r128Screen->vbRgn.size, + (drmAddressPtr)&r128Screen->vb)) { + drmUnmap((drmAddress)r128Screen->ringReadPtr, + r128Screen->ringReadRgn.size); + drmUnmap((drmAddress)r128Screen->ring, r128Screen->ringRgn.size); + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + Xfree(r128Screen); + return NULL; + } + r128Screen->vbOffset = r128DRIPriv->vbOffset; + r128Screen->vbBufSize = r128DRIPriv->vbBufSize; + + r128Screen->indRgn.handle = r128DRIPriv->indHandle; + r128Screen->indRgn.size = r128DRIPriv->indMapSize; + if (drmMap(sPriv->fd, + r128Screen->indRgn.handle, + r128Screen->indRgn.size, + (drmAddressPtr)&r128Screen->ind)) { + drmUnmap((drmAddress)r128Screen->vb, r128Screen->vbRgn.size); + drmUnmap((drmAddress)r128Screen->ringReadPtr, + r128Screen->ringReadRgn.size); + drmUnmap((drmAddress)r128Screen->ring, r128Screen->ringRgn.size); + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + Xfree(r128Screen); + return NULL; + } + + r128Screen->agpTexRgn.handle = r128DRIPriv->agpTexHandle; + r128Screen->agpTexRgn.size = r128DRIPriv->agpTexMapSize; + if (drmMap(sPriv->fd, + r128Screen->agpTexRgn.handle, + r128Screen->agpTexRgn.size, + (drmAddressPtr)&r128Screen->agpTex)) { + drmUnmap((drmAddress)r128Screen->ind, r128Screen->indRgn.size); + drmUnmap((drmAddress)r128Screen->vb, r128Screen->vbRgn.size); + drmUnmap((drmAddress)r128Screen->ringReadPtr, + r128Screen->ringReadRgn.size); + drmUnmap((drmAddress)r128Screen->ring, r128Screen->ringRgn.size); + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + Xfree(r128Screen); + return NULL; + } + r128Screen->agpTexOffset = r128DRIPriv->agpTexOffset; + + if (!(r128Screen->vbBufs = drmMapBufs(sPriv->fd))) { + drmUnmap((drmAddress)r128Screen->agpTex, + r128Screen->agpTexRgn.size); + drmUnmap((drmAddress)r128Screen->ind, r128Screen->indRgn.size); + drmUnmap((drmAddress)r128Screen->vb, r128Screen->vbRgn.size); + drmUnmap((drmAddress)r128Screen->ringReadPtr, + r128Screen->ringReadRgn.size); + drmUnmap((drmAddress)r128Screen->ring, r128Screen->ringRgn.size); + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + Xfree(r128Screen); + return NULL; + } + } + + r128Screen->deviceID = r128DRIPriv->deviceID; + + r128Screen->width = r128DRIPriv->width; + r128Screen->height = r128DRIPriv->height; + r128Screen->depth = r128DRIPriv->depth; + r128Screen->bpp = r128DRIPriv->bpp; + r128Screen->pixel_code = (r128Screen->bpp != 16 ? + r128Screen->bpp : + r128Screen->depth); + + r128Screen->fb = sPriv->pFB; + r128Screen->fbOffset = sPriv->fbOrigin; + r128Screen->fbStride = sPriv->fbStride; + r128Screen->fbSize = sPriv->fbSize; + + r128Screen->fbX = r128DRIPriv->fbX; + r128Screen->fbY = r128DRIPriv->fbY; + r128Screen->backX = r128DRIPriv->backX; + r128Screen->backY = r128DRIPriv->backY; + r128Screen->depthX = r128DRIPriv->depthX; + r128Screen->depthY = r128DRIPriv->depthY; + + r128Screen->texOffset[R128_LOCAL_TEX_HEAP] = (r128DRIPriv->textureY * + r128Screen->fbStride + + r128DRIPriv->textureX * + (r128Screen->bpp/8)); + r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureSize; + r128Screen->log2TexGran[R128_LOCAL_TEX_HEAP] = r128DRIPriv->log2TexGran; + + if (r128Screen->IsPCI) { + r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0; + r128Screen->texSize[R128_AGP_TEX_HEAP] = 0; + r128Screen->log2TexGran[R128_AGP_TEX_HEAP] = 0; + r128Screen->NRTexHeaps = R128_NR_TEX_HEAPS-1; + } else { + r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0; + r128Screen->texSize[R128_AGP_TEX_HEAP] = + r128DRIPriv->agpTexMapSize; + r128Screen->log2TexGran[R128_AGP_TEX_HEAP] = + r128DRIPriv->log2AGPTexGran; + r128Screen->NRTexHeaps = R128_NR_TEX_HEAPS; + } + +#if 1 + /* FIXME: For testing only */ + if (getenv("LIBGL_SHOW_BUFFERS")) { + r128Screen->backX = 0; + r128Screen->backY = r128DRIPriv->height/2; + r128Screen->depthX = r128DRIPriv->width/2; + r128Screen->depthY = r128DRIPriv->height/2; + } +#endif + + r128Screen->CCEMode = r128DRIPriv->CCEMode; + r128Screen->CCEFifoSize = r128DRIPriv->CCEFifoSize; + + r128Screen->ringEntries = r128DRIPriv->ringSize/sizeof(CARD32); + if (!r128Screen->IsPCI) { + r128Screen->ringStartPtr = (int *)r128Screen->ring; + r128Screen->ringEndPtr = (int *)(r128Screen->ring + + r128DRIPriv->ringSize); + } + + r128Screen->MMIOFifoSlots = 0; + r128Screen->CCEFifoSlots = 0; + + r128Screen->CCEFifoAddr = R128_PM4_FIFO_DATA_EVEN; + + r128Screen->SAREA = (R128SAREAPrivPtr)((char *)sPriv->pSAREA + + sizeof(XF86DRISAREARec)); + + r128Screen->driScreen = sPriv; + + r128FastPathInit(); + r128TriangleFuncsInit(); + r128SetupInit(); + + return r128Screen; +} + +/* Destroy the device specific screen private data struct */ +void r128DestroyScreen(__DRIscreenPrivate *sPriv) +{ + r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private; + + if (!r128Screen->IsPCI) { + drmUnmapBufs(r128Screen->vbBufs); + + drmUnmap((drmAddress)r128Screen->agpTex, r128Screen->agpTexRgn.size); + drmUnmap((drmAddress)r128Screen->ind, r128Screen->indRgn.size); + drmUnmap((drmAddress)r128Screen->vb, r128Screen->vbRgn.size); + drmUnmap((drmAddress)r128Screen->ringReadPtr, + r128Screen->ringReadRgn.size); + drmUnmap((drmAddress)r128Screen->ring, r128Screen->ringRgn.size); + } + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + + Xfree(r128Screen); + sPriv->private = NULL; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_screen.h b/xc/lib/GL/mesa/src/drv/r128/r128_screen.h new file mode 100644 index 000000000..02deb64e9 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_screen.h @@ -0,0 +1,129 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_SCREEN_H_ +#define _R128_SCREEN_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include "r128_sarea.h" + +typedef struct { + drmHandle handle; /* Handle to the DRM region */ + drmSize size; /* Size of the DRM region */ +} r128RegionRec, *r128RegionPtr; + +typedef struct { + /* MMIO register data */ + r128RegionRec mmioRgn; + unsigned char *mmio; + + /* CCE ring buffer data */ + r128RegionRec ringRgn; + unsigned char *ring; + + /* CCE ring read pointer data */ + r128RegionRec ringReadRgn; + + /* CCE vertex buffer data */ + r128RegionRec vbRgn; + unsigned char *vb; + int vbOffset; + int vbBufSize; + drmBufMapPtr vbBufs; + + /* CCE indirect buffer data */ + r128RegionRec indRgn; + unsigned char *ind; + + /* CCE AGP Texture data */ + r128RegionRec agpTexRgn; + unsigned char *agpTex; + int agpTexOffset; + + /* Frame buffer data */ + unsigned char *fb; + unsigned long fbOffset; + int fbStride; + int fbSize; + + int IsPCI; /* Current card is a PCI card */ + + int CCEMode; /* CCE mode that server/clients use */ + int CCEFifoSize; /* Size of the CCE command FIFO */ + + /* CCE ring buffer data */ + int ringEntries; + + volatile int *ringReadPtr; /* Pointer to current read addr */ + int *ringStartPtr; /* Pointer to end of ring buffer */ + int *ringEndPtr; /* Pointer to end of ring buffer */ + + /* DRI screen private data */ + int deviceID; /* PCI device ID */ + int width; /* Width in pixels of display */ + int height; /* Height in scanlines of display */ + int depth; /* Depth of display (8, 15, 16, 24) */ + int bpp; /* Bit depth of disp (8, 16, 24, 32) */ + int pixel_code; /* 8, 15, 16, 24, 32 */ + + int fbX; /* Start of frame buffer */ + int fbY; + int backX; /* Start of shared back buffer */ + int backY; + int depthX; /* Start of shared depth buffer */ + int depthY; + + /* Shared texture data */ + int NRTexHeaps; + int texOffset[R128_NR_TEX_HEAPS]; + int texSize[R128_NR_TEX_HEAPS]; + int log2TexGran[R128_NR_TEX_HEAPS]; + + int MMIOFifoSlots; /* Free slots in the FIFO (64 max) */ + int CCEFifoSlots; /* Free slots in the CCE FIFO */ + + int CCEFifoAddr; /* MMIO offset to write next CCE + value (only used when CCE is + in PIO mode). */ + R128SAREAPrivPtr SAREA; /* Pointer to SAREA private data */ + + __DRIscreenPrivate *driScreen; +} r128ScreenRec, *r128ScreenPtr; + +r128ScreenPtr r128CreateScreen(__DRIscreenPrivate *sPriv); +void r128DestroyScreen(__DRIscreenPrivate *sPriv); + +#endif +#endif /* _R128_SCREEN_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_span.c b/xc/lib/GL/mesa/src/drv/r128/r128_span.c new file mode 100644 index 000000000..b5d1774fd --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_span.c @@ -0,0 +1,329 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * Gareth Hughes <gareth@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_state.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_span.h" + +#define DBG 0 + +#define LOCAL_VARS \ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); \ + r128ScreenPtr r128scrn = r128ctx->r128Screen; \ + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; \ + GLuint pitch = r128scrn->fbStride; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(r128scrn->fb + \ + (r128ctx->drawX + dPriv->x) * (r128scrn->bpp/8) + \ + (r128ctx->drawY + dPriv->y) * pitch); \ + char *read_buf = (char *)(r128scrn->fb + \ + (r128ctx->readX + dPriv->x) * (r128scrn->bpp/8)+\ + (r128ctx->readY + dPriv->y) * pitch); \ + GLushort p; \ + (void) read_buf; (void) buf; (void) p + +#define LOCAL_DEPTH_VARS \ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); \ + r128ScreenPtr r128scrn = r128ctx->r128Screen; \ + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; \ + GLuint pitch = r128scrn->fbStride; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(r128scrn->fb + \ + (r128scrn->depthX + dPriv->x) * (r128scrn->bpp/8) + \ + (r128scrn->depthY + dPriv->y) * pitch); \ + (void) buf + +#define INIT_MONO_PIXEL(p) \ + p = R128_CONTEXT(ctx)->Color + +#define CLIPPIXEL(_x, _y) \ + ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy)) + + +#define CLIPSPAN(_x, _y, _n, _x1, _n1, _i) \ + if (( _y < miny) || (_y >= maxy)) { \ + _n1 = 0, _x1 = x; \ + } else { \ + _n1 = _n; \ + _x1 = _x; \ + if (_x1 < minx) _i += (minx - _x1), _x1 = minx; \ + if (_x1 + _n1 >= maxx) n1 -= (_x1 + n1 - maxx) + 1; \ + } + +#define Y_FLIP(_y) (height - _y - 1) + + +#define HW_LOCK() \ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); \ + LOCK_HARDWARE(r128ctx); \ + R128CCE_WAIT_FOR_IDLE(r128ctx); + +#define HW_CLIPLOOP() \ + do { \ + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; \ + int _nc = dPriv->numClipRects; \ + \ + while (_nc--) { \ + int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \ + int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \ + int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \ + int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y; + +#define HW_ENDCLIPLOOP() \ + } \ + } while (0) + +#define HW_UNLOCK() \ + UNLOCK_HARDWARE(r128ctx) + + + +/* 16 bit, RGB565 color spanline and pixel functions */ +#define WRITE_RGBA(_x, _y, r, g, b, a) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \ + (((int)g & 0xfc) << 3) | \ + (((int)b & 0xf8) >> 3) ) + +#define WRITE_PIXEL(_x, _y, p) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = p + +#define READ_RGBA(rgba, _x, _y) \ + do { \ + GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \ + rgba[0] = (p >> 8) & 0xf8; \ + rgba[1] = (p >> 3) & 0xfc; \ + rgba[2] = (p << 3) & 0xf8; \ + rgba[3] = 0xff; \ + } while (0) + +#define TAG(x) r128##x##_RGB565 +#include "spantmp.h" + + + +/* 15 bit, ARGB1555 color spanline and pixel functions */ +#define WRITE_RGBA(_x, _y, r, g, b, a) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = (((r & 0xf8) << 7) | \ + ((g & 0xf8) << 2) | \ + ((b & 0xf8) >> 3) | \ + ((a) ? 0x8000 : 0)) + +#define WRITE_PIXEL(_x, _y, p) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = p + +#define READ_RGBA(rgba, _x, _y) \ + do { \ + GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \ + rgba[0] = (p >> 7) & 0xf8; \ + rgba[1] = (p >> 2) & 0xf8; \ + rgba[2] = (p << 3) & 0xf8; \ + rgba[3] = (p & 0x8000) ? 0xff : 0; \ + } while (0) + +#define TAG(x) r128##x##_ARGB1555 +#include "spantmp.h" + + + +/* 16 bit depthbuffer functions */ +#define WRITE_DEPTH(_x, _y, d) \ + *(GLdepth *)(buf + _x*2 + _y*pitch) = d + +#define READ_DEPTH(d, _x, _y) \ + d = *(GLdepth *)(buf + _x*2 + _y*pitch) + +#define TAG(x) r128##x##_16 +#include "depthtmp.h" + + + +/* 24 bit, RGB888 color spanline and pixel functions */ +#define WRITE_RGBA(_x, _y, r, g, b, a) \ + *(GLuint *)(buf + _x*3 + _y*pitch) = ((r << 16) | \ + (g << 8) | \ + (b << 0)) + +#define WRITE_PIXEL(_x, _y, p) \ + *(GLuint *)(buf + _x*3 + _y*pitch) = p + +#define READ_RGBA(rgba, _x, _y) \ + do { \ + GLuint p = *(GLuint *)(read_buf + _x*3 + _y*pitch); \ + rgba[0] = (p >> 16) & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = (p >> 0) & 0xff; \ + rgba[3] = 0xff; \ + } while (0) + +#define TAG(x) r128##x##_RGB888 +#include "spantmp.h" + + + +/* 24 bit depthbuffer functions */ +#define WRITE_DEPTH(_x, _y, d) \ + *(GLdepth *)(buf + _x*3 + _y*pitch) = d + +#define READ_DEPTH(d, _x, _y) \ + d = *(GLdepth *)(buf + _x*3 + _y*pitch) + +#define TAG(x) r128##x##_24 +#include "depthtmp.h" + + + +/* 32 bit, ARGB8888 color spanline and pixel functions */ +#define WRITE_RGBA(_x, _y, r, g, b, a) \ + *(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) | \ + (g << 8) | \ + (b << 0) | \ + (a << 24) ) + +#define WRITE_PIXEL(_x, _y, p) \ + *(GLuint *)(buf + _x*4 + _y*pitch) = p + +#define READ_RGBA(rgba, _x, _y) \ + do { \ + GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \ + rgba[0] = (p >> 16) & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = (p >> 0) & 0xff; \ + rgba[3] = (p >> 24) & 0xff; \ + } while (0) + +#define TAG(x) r128##x##_ARGB8888 +#include "spantmp.h" + + + +/* 32 bit depthbuffer functions */ +#define WRITE_DEPTH(_x, _y, d) \ + *(GLdepth *)(buf + _x*4 + _y*pitch) = d + +#define READ_DEPTH(d, _x, _y) \ + d = *(GLdepth *)(buf + _x*4 + _y*pitch) + +#define TAG(x) r128##x##_32 +#include "depthtmp.h" + + + +void r128DDInitSpanFuncs(GLcontext *ctx) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + switch (r128ctx->r128Screen->pixel_code) { + case 8: /* Color Index mode not supported */ + break; + + case 15: + ctx->Driver.WriteRGBASpan = r128WriteRGBASpan_ARGB1555; + ctx->Driver.WriteRGBSpan = r128WriteRGBSpan_ARGB1555; + ctx->Driver.WriteMonoRGBASpan = r128WriteMonoRGBASpan_ARGB1555; + ctx->Driver.WriteRGBAPixels = r128WriteRGBAPixels_ARGB1555; + ctx->Driver.WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_ARGB1555; + ctx->Driver.ReadRGBASpan = r128ReadRGBASpan_ARGB1555; + ctx->Driver.ReadRGBAPixels = r128ReadRGBAPixels_ARGB1555; + + ctx->Driver.ReadDepthSpan = r128ReadDepthSpan_16; + ctx->Driver.WriteDepthSpan = r128WriteDepthSpan_16; + ctx->Driver.ReadDepthPixels = r128ReadDepthPixels_16; + ctx->Driver.WriteDepthPixels = r128WriteDepthPixels_16; + break; + + case 16: + ctx->Driver.WriteRGBASpan = r128WriteRGBASpan_RGB565; + ctx->Driver.WriteRGBSpan = r128WriteRGBSpan_RGB565; + ctx->Driver.WriteMonoRGBASpan = r128WriteMonoRGBASpan_RGB565; + ctx->Driver.WriteRGBAPixels = r128WriteRGBAPixels_RGB565; + ctx->Driver.WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_RGB565; + ctx->Driver.ReadRGBASpan = r128ReadRGBASpan_RGB565; + ctx->Driver.ReadRGBAPixels = r128ReadRGBAPixels_RGB565; + + ctx->Driver.ReadDepthSpan = r128ReadDepthSpan_16; + ctx->Driver.WriteDepthSpan = r128WriteDepthSpan_16; + ctx->Driver.ReadDepthPixels = r128ReadDepthPixels_16; + ctx->Driver.WriteDepthPixels = r128WriteDepthPixels_16; + break; + + case 24: + ctx->Driver.WriteRGBASpan = r128WriteRGBASpan_RGB888; + ctx->Driver.WriteRGBSpan = r128WriteRGBSpan_RGB888; + ctx->Driver.WriteMonoRGBASpan = r128WriteMonoRGBASpan_RGB888; + ctx->Driver.WriteRGBAPixels = r128WriteRGBAPixels_RGB888; + ctx->Driver.WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_RGB888; + ctx->Driver.ReadRGBASpan = r128ReadRGBASpan_RGB888; + ctx->Driver.ReadRGBAPixels = r128ReadRGBAPixels_RGB888; + + ctx->Driver.ReadDepthSpan = r128ReadDepthSpan_24; + ctx->Driver.WriteDepthSpan = r128WriteDepthSpan_24; + ctx->Driver.ReadDepthPixels = r128ReadDepthPixels_24; + ctx->Driver.WriteDepthPixels = r128WriteDepthPixels_24; + break; + + case 32: + ctx->Driver.WriteRGBASpan = r128WriteRGBASpan_ARGB8888; + ctx->Driver.WriteRGBSpan = r128WriteRGBSpan_ARGB8888; + ctx->Driver.WriteMonoRGBASpan = r128WriteMonoRGBASpan_ARGB8888; + ctx->Driver.WriteRGBAPixels = r128WriteRGBAPixels_ARGB8888; + ctx->Driver.WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_ARGB8888; + ctx->Driver.ReadRGBASpan = r128ReadRGBASpan_ARGB8888; + ctx->Driver.ReadRGBAPixels = r128ReadRGBAPixels_ARGB8888; + + ctx->Driver.ReadDepthSpan = r128ReadDepthSpan_32; + ctx->Driver.WriteDepthSpan = r128WriteDepthSpan_32; + ctx->Driver.ReadDepthPixels = r128ReadDepthPixels_32; + ctx->Driver.WriteDepthPixels = r128WriteDepthPixels_32; + break; + + default: + break; + } + + ctx->Driver.WriteCI8Span = NULL; + ctx->Driver.WriteCI32Span = NULL; + ctx->Driver.WriteMonoCISpan = NULL; + ctx->Driver.WriteCI32Pixels = NULL; + ctx->Driver.WriteMonoCIPixels = NULL; + ctx->Driver.ReadCI32Span = NULL; + ctx->Driver.ReadCI32Pixels = NULL; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_span.h b/xc/lib/GL/mesa/src/drv/r128/r128_span.h new file mode 100644 index 000000000..f83a4da9f --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_span.h @@ -0,0 +1,44 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Gareth Hughes <gareth@precisioninsight.com> + * + */ + +#ifndef _R128_SPAN_H_ +#define _R128_SPAN_H_ + +#ifdef GLX_DIRECT_RENDERING + +extern void r128DDInitSpanFuncs(GLcontext *ctx); + +#endif +#endif /* _R128_SPAN_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_state.c b/xc/lib/GL/mesa/src/drv/r128/r128_state.c new file mode 100644 index 000000000..3d1ceaa24 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_state.c @@ -0,0 +1,1309 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_state.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_tris.h" +#include "r128_vb.h" +#include "r128_tex.h" + +#include "mmath.h" + +#define INTERESTED (~(NEW_MODELVIEW | \ + NEW_PROJECTION | \ + NEW_TEXTURE_MATRIX | \ + NEW_USER_CLIP | \ + NEW_CLIENT_STATE | \ + NEW_TEXTURE_ENABLE)) + +static void r128DDUpdateState(GLcontext *ctx) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) { + fprintf(stderr, "r128DDUpdateState(%p)\n", ctx); + } + + if (ctx->NewState & INTERESTED) { + r128ChooseRenderState(ctx); + r128ChooseRasterSetupFunc(ctx); + } + + if (!r128ctx->Fallback) { + ctx->IndirectTriangles &= ~DD_SW_RASTERIZE; + ctx->IndirectTriangles |= r128ctx->IndirectTriangles; + + ctx->Driver.PointsFunc = r128ctx->PointsFunc; + ctx->Driver.LineFunc = r128ctx->LineFunc; + ctx->Driver.TriangleFunc = r128ctx->TriangleFunc; + ctx->Driver.QuadFunc = r128ctx->QuadFunc; + ctx->Driver.RectFunc = NULL; + } +} + +static void r128DDUpdateHWState(GLcontext *ctx) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + /* FIXME: state is being updated too often */ + if (r128ctx->dirty) + r128UpdateHWState(r128ctx); +} + +static void r128DDReducedPrimitiveChange(GLcontext *ctx, GLenum prim) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + /* FIXME: Also need to flush between tris and tristrips/fans when we + support them directly */ + R128CCE_FLUSH_VB_LOCK(r128ctx); +} + +static void r128DDClearColor(GLcontext *ctx, + GLubyte r, GLubyte g, GLubyte b, GLubyte a) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + r128ctx->ClearColor = r128PackColor(r128ctx->r128Screen->depth, + r, g, b, a); +} + +static void r128DDColor(GLcontext *ctx, + GLubyte r, GLubyte g, GLubyte b, GLubyte a) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + r128ctx->Color = r128PackColor(r128ctx->r128Screen->depth, r, g, b, a); +} + +static GLboolean r128DDSetDrawBuffer(GLcontext *ctx, GLenum mode) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + int x = r128ctx->driDrawable->x; + int y = r128ctx->driDrawable->y; + int found; + + r128ctx->Fallback &= ~R128_FALLBACK_DRAW_BUFFER; + + switch (mode) { + case GL_FRONT_LEFT: + r128ctx->drawX = r128ctx->r128Screen->fbX; + r128ctx->drawY = r128ctx->r128Screen->fbY; + found = GL_TRUE; + break; + case GL_BACK_LEFT: + r128ctx->drawX = r128ctx->r128Screen->backX; + r128ctx->drawY = r128ctx->r128Screen->backY; + found = GL_TRUE; + break; + default: + r128ctx->Fallback |= R128_FALLBACK_DRAW_BUFFER; + found = GL_FALSE; + break; + } + + x += r128ctx->drawX; + y += r128ctx->drawY; + + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) | + (x << R128_WINDOW_X_SHIFT)); + + /* Recalculate the Z buffer offset since we might be drawing to the + back buffer and window_xy_offset affects both color buffer and + depth drawing */ + r128ctx->regs.z_offset_c = ((r128ctx->r128Screen->depthX - + r128ctx->drawX) * + (r128ctx->r128Screen->bpp/8) + + (r128ctx->r128Screen->depthY - + r128ctx->drawY) * + r128ctx->r128Screen->fbStride); + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_WIN_Z_POS; + return found; +} + +static void r128DDSetReadBuffer(GLcontext *ctx, + GLframebuffer *colorBuffer, + GLenum mode) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + r128ctx->Fallback &= ~R128_FALLBACK_READ_BUFFER; + + switch (mode) { + case GL_FRONT_LEFT: + r128ctx->readX = r128ctx->r128Screen->fbX; + r128ctx->readY = r128ctx->r128Screen->fbY; + break; + case GL_BACK_LEFT: + r128ctx->readX = r128ctx->r128Screen->backX; + r128ctx->readY = r128ctx->r128Screen->backY; + break; + default: + r128ctx->Fallback |= R128_FALLBACK_READ_BUFFER; + break; + } +} + +static GLboolean r128DDColorMask(GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + GLuint mask = r128PackColor(r128ctx->r128Screen->pixel_code, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP]); + + if (r128ctx->regs.plane_3d_mask_c != mask) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.plane_3d_mask_c = mask; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_MISC; + } + + return GL_TRUE; +} + +static void r128DDDither(GLcontext *ctx, GLboolean enable) +{ +} + +static void r128DDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + CARD32 a = r128ctx->regs.misc_3d_state_cntl_reg; + + a &= ~(R128_ALPHA_TEST_MASK | R128_REF_ALPHA_MASK); + a |= ctx->Color.AlphaRef & R128_REF_ALPHA_MASK; + + switch (func) { + case GL_NEVER: a |= R128_ALPHA_TEST_NEVER; break; + case GL_LESS: a |= R128_ALPHA_TEST_LESS; break; + case GL_LEQUAL: a |= R128_ALPHA_TEST_LESSEQUAL; break; + case GL_EQUAL: a |= R128_ALPHA_TEST_EQUAL; break; + case GL_GEQUAL: a |= R128_ALPHA_TEST_GREATEREQUAL; break; + case GL_GREATER: a |= R128_ALPHA_TEST_GREATER; break; + case GL_NOTEQUAL: a |= R128_ALPHA_TEST_NEQUAL; break; + case GL_ALWAYS: a |= R128_ALPHA_TEST_ALWAYS; + break; + default: + /* ERROR!!! */ + return; + } + + if (r128ctx->regs.misc_3d_state_cntl_reg != a) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.misc_3d_state_cntl_reg = a; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALPHASTATE; + } +} + +static void r128DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + CARD32 b = r128ctx->regs.misc_3d_state_cntl_reg; + + b &= ~(R128_ALPHA_BLEND_SRC_MASK | R128_ALPHA_BLEND_DST_MASK); + + switch (sfactor) { + case GL_ZERO: b |= R128_ALPHA_BLEND_SRC_ZERO; + break; + case GL_ONE: b |= R128_ALPHA_BLEND_SRC_ONE; + break; + case GL_DST_COLOR: b |= R128_ALPHA_BLEND_SRC_DESTCOLOR; + break; + case GL_ONE_MINUS_DST_COLOR: b |= R128_ALPHA_BLEND_SRC_INVDESTCOLOR; + break; + case GL_SRC_ALPHA: b |= R128_ALPHA_BLEND_SRC_SRCALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: b |= R128_ALPHA_BLEND_SRC_INVSRCALPHA; + break; + case GL_DST_ALPHA: b |= R128_ALPHA_BLEND_SRC_DESTALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: b |= R128_ALPHA_BLEND_SRC_INVDESTALPHA; + break; + case GL_SRC_ALPHA_SATURATE: b |= R128_ALPHA_BLEND_SRC_SRCALPHASAT; + break; +#if 0 + /* FIXME: These are not supported directly by the Rage 128. + They could be emulated using something like the TexEnv + modes. */ + case GL_CONSTANT_COLOR: b |= 0; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: b |= 0; + break; + case GL_CONSTANT_ALPHA: b |= 0; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: b |= 0; + break; +#endif + default: + /* ERROR!!! */ + return; + } + + switch (dfactor) { + case GL_ZERO: b |= R128_ALPHA_BLEND_DST_ZERO; + break; + case GL_ONE: b |= R128_ALPHA_BLEND_DST_ONE; + break; + case GL_SRC_COLOR: b |= R128_ALPHA_BLEND_DST_SRCCOLOR; + break; + case GL_ONE_MINUS_SRC_COLOR: b |= R128_ALPHA_BLEND_DST_INVSRCCOLOR; + break; + case GL_SRC_ALPHA: b |= R128_ALPHA_BLEND_DST_SRCALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: b |= R128_ALPHA_BLEND_DST_INVSRCALPHA; + break; + case GL_DST_ALPHA: b |= R128_ALPHA_BLEND_DST_DESTALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: b |= R128_ALPHA_BLEND_DST_INVDESTALPHA; + break; +#if 0 + /* FIXME: These are not supported directly by the Rage 128. + They could be emulated using something like the TexEnv + modes. */ + case GL_CONSTANT_COLOR: b |= 0; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: b |= 0; + break; + case GL_CONSTANT_ALPHA: b |= 0; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: b |= 0; + break; +#endif + default: + /* ERROR!!! */ + return; + } + + if (r128ctx->regs.misc_3d_state_cntl_reg != b) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.misc_3d_state_cntl_reg = b; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALPHASTATE; + } +} + +static void r128DDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, + GLenum dfactorRGB, GLenum sfactorA, + GLenum dfactorA) +{ + if (sfactorRGB != sfactorA || dfactorRGB != dfactorA) { + /* ERROR!!! */ + return; + } + + r128DDBlendFunc(ctx, sfactorRGB, dfactorRGB); +} + +static void r128DDClearDepth(GLcontext *ctx, GLclampd d) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + switch (r128ctx->regs.z_sten_cntl_c & R128_Z_PIX_WIDTH_MASK) { + case R128_Z_PIX_WIDTH_16: r128ctx->ClearDepth = d * 0x0000ffff; break; + case R128_Z_PIX_WIDTH_24: r128ctx->ClearDepth = d * 0x00ffffff; break; + case R128_Z_PIX_WIDTH_32: r128ctx->ClearDepth = d * 0xffffffff; break; + default: return; + } +} + +static void r128DDCullFace(GLcontext *ctx, GLenum mode) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + CARD32 f = r128ctx->regs.pm4_vc_fpu_setup; + + if (!ctx->Polygon.CullFlag) return; + + f &= ~(R128_BACKFACE_MASK | R128_FRONTFACE_MASK); + + switch (mode) { + case GL_FRONT: f |= R128_BACKFACE_SOLID; break; + case GL_BACK: f |= R128_FRONTFACE_SOLID; break; + case GL_FRONT_AND_BACK: break; + default: return; + } + + if (r128ctx->regs.pm4_vc_fpu_setup != f) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.pm4_vc_fpu_setup = f; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_SETUPSTATE; + } +} + +static void r128DDFrontFace(GLcontext *ctx, GLenum mode) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + CARD32 f = r128ctx->regs.pm4_vc_fpu_setup; + + f &= ~R128_FRONT_DIR_MASK; + + switch (mode) { + case GL_CW: f |= R128_FRONT_DIR_CW; break; + case GL_CCW: f |= R128_FRONT_DIR_CCW; break; + default: return; + } + + if (r128ctx->regs.pm4_vc_fpu_setup != f) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.pm4_vc_fpu_setup = f; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_SETUPSTATE; + } +} + +static void r128DDDepthFunc(GLcontext *ctx, GLenum func) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + CARD32 z = r128ctx->regs.z_sten_cntl_c; + + z &= ~R128_Z_TEST_MASK; + + switch (func) { + case GL_NEVER: z |= R128_Z_TEST_NEVER; break; + case GL_LESS: z |= R128_Z_TEST_LESS; break; + case GL_LEQUAL: z |= R128_Z_TEST_LESSEQUAL; break; + case GL_EQUAL: z |= R128_Z_TEST_EQUAL; break; + case GL_GEQUAL: z |= R128_Z_TEST_GREATEREQUAL; break; + case GL_GREATER: z |= R128_Z_TEST_GREATER; break; + case GL_NOTEQUAL: z |= R128_Z_TEST_NEQUAL; break; + case GL_ALWAYS: z |= R128_Z_TEST_ALWAYS; break; + default: return; + } + + if (r128ctx->regs.z_sten_cntl_c != z) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.z_sten_cntl_c = z; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ZSTENSTATE; + } +} + +static void r128DDDepthMask(GLcontext *ctx, GLboolean flag) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + CARD32 t = r128ctx->regs.tex_cntl_c; + + if (flag) t |= R128_Z_WRITE_ENABLE; + else t &= ~R128_Z_WRITE_ENABLE; + + if (r128ctx->regs.tex_cntl_c != t) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.tex_cntl_c = t; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ENGINESTATE; + } +} + +static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + CARD32 t = r128ctx->regs.tex_cntl_c; + CARD32 f = r128ctx->regs.pm4_vc_fpu_setup; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) { + fprintf(stderr, "r128DDEnable( %p, 0x%x = %s )\n", + ctx, cap, state ? "GL_TRUE" : "GL_FALSE"); + } + + switch (cap) { + case GL_ALPHA_TEST: + if (state) t |= R128_ALPHA_TEST_ENABLE; + else t &= ~R128_ALPHA_TEST_ENABLE; + break; + + case GL_AUTO_NORMAL: return; + + case GL_BLEND: + if (state) t |= R128_ALPHA_ENABLE; + else t &= ~R128_ALPHA_ENABLE; + break; + + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + case GL_COLOR_MATERIAL: return; + + case GL_CULL_FACE: + f &= ~(R128_BACKFACE_MASK | R128_FRONTFACE_MASK); + if (state) { + switch (ctx->Polygon.CullFaceMode) { + case GL_FRONT: f |= R128_BACKFACE_SOLID; break; + case GL_BACK: f |= R128_FRONTFACE_SOLID; break; + case GL_FRONT_AND_BACK: break; + default: return; + } + } else { + f |= R128_BACKFACE_SOLID | R128_FRONTFACE_SOLID; + } + break; + + case GL_DEPTH_TEST: + if (state) t |= R128_Z_ENABLE; + else t &= ~R128_Z_ENABLE; + break; + + case GL_DITHER: + if (state) t |= R128_DITHER_ENABLE; + else t &= ~R128_DITHER_ENABLE; + break; + + case GL_FOG: + if (state) t |= R128_FOG_ENABLE; + else t &= ~R128_FOG_ENABLE; + break; + + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + case GL_LIGHTING: + case GL_LINE_SMOOTH: + case GL_LINE_STIPPLE: + case GL_INDEX_LOGIC_OP: + case GL_COLOR_LOGIC_OP: + case GL_MAP1_COLOR_4: + case GL_MAP1_INDEX: + case GL_MAP1_NORMAL: + case GL_MAP1_TEXTURE_COORD_1: + case GL_MAP1_TEXTURE_COORD_2: + case GL_MAP1_TEXTURE_COORD_3: + case GL_MAP1_TEXTURE_COORD_4: + case GL_MAP1_VERTEX_3: + case GL_MAP1_VERTEX_4: + case GL_MAP2_COLOR_4: + case GL_MAP2_INDEX: + case GL_MAP2_NORMAL: + case GL_MAP2_TEXTURE_COORD_1: + case GL_MAP2_TEXTURE_COORD_2: + case GL_MAP2_TEXTURE_COORD_3: + case GL_MAP2_TEXTURE_COORD_4: + case GL_MAP2_VERTEX_3: + case GL_MAP2_VERTEX_4: + case GL_NORMALIZE: + case GL_POINT_SMOOTH: + case GL_POLYGON_SMOOTH: + case GL_POLYGON_STIPPLE: + case GL_POLYGON_OFFSET_POINT: + case GL_POLYGON_OFFSET_LINE: + case GL_POLYGON_OFFSET_FILL: + case GL_RESCALE_NORMAL_EXT: return; + + case GL_SCISSOR_TEST: + /* FIXME: Hook up the software scissor */ +#if 0 + r128ctx->Scissor = state; +#endif + break; + + case GL_SHARED_TEXTURE_PALETTE_EXT: + case GL_STENCIL_TEST: return; + + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + /* This is handled in r128UpdateTex[01]State() */ + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + break; + + case GL_TEXTURE_3D: + case GL_TEXTURE_GEN_Q: + case GL_TEXTURE_GEN_R: + case GL_TEXTURE_GEN_S: + case GL_TEXTURE_GEN_T: return; + + /* Client state */ + case GL_VERTEX_ARRAY: + case GL_NORMAL_ARRAY: + case GL_COLOR_ARRAY: + case GL_INDEX_ARRAY: + case GL_TEXTURE_COORD_ARRAY: + case GL_EDGE_FLAG_ARRAY: return; + + default: return; + } + + if (r128ctx->regs.tex_cntl_c != t) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.tex_cntl_c = t; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ENGINESTATE; + } + if (r128ctx->regs.pm4_vc_fpu_setup != f) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.pm4_vc_fpu_setup = f; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_SETUPSTATE; + } + +} + +static void r128DDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + GLubyte c[4]; + CARD32 col; + floatTOint fog; + GLenum mode; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) { + fprintf(stderr, "r128DDFogfv(%p, 0x%x)\n", ctx, pname); + } + + switch (pname) { + case GL_FOG_MODE: + mode = (GLenum)(GLint)*param; + if (r128ctx->FogMode != mode) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->FogMode = mode; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_FOGTABLE; + } + break; + + case GL_FOG_DENSITY: + fog.f = *param; + if (r128ctx->regs.fog_3d_table_density != fog.i) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.fog_3d_table_density = fog.i; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_FOGSTATE; + } + break; + + case GL_FOG_START: + fog.f = *param; + if (r128ctx->regs.fog_3d_table_start != fog.i) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.fog_3d_table_start = fog.i; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_FOGSTATE; + } + break; + + case GL_FOG_END: + fog.f = *param; + if (r128ctx->regs.fog_3d_table_end != fog.i) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.fog_3d_table_end = fog.i; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_FOGSTATE; + } + break; + + case GL_FOG_COLOR: + FLOAT_RGBA_TO_UBYTE_RGBA(c, ctx->Fog.Color); + col = r128PackColor(32, c[0], c[1], c[2], c[3]); + if (r128ctx->regs.fog_color_c != col) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.fog_color_c = col; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_FOGSTATE; + } + break; + + default: + return; + } +} + +static void r128DDScissor(GLcontext *ctx, + GLint x, GLint y, GLsizei w, GLsizei h) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + r128ctx->ScissorRect.x1 = x; + r128ctx->ScissorRect.y1 = r128ctx->driDrawable->h - (y + h); + r128ctx->ScissorRect.x2 = x + w; + r128ctx->ScissorRect.y2 = r128ctx->driDrawable->h - y; +} + +/* Initialize the driver's state functions */ +void r128DDInitStateFuncs(GLcontext *ctx) +{ + ctx->Driver.UpdateState = r128DDUpdateState; + + ctx->Driver.ClearIndex = NULL; + ctx->Driver.ClearColor = r128DDClearColor; + ctx->Driver.Index = NULL; + ctx->Driver.Color = r128DDColor; + ctx->Driver.SetDrawBuffer = r128DDSetDrawBuffer; + ctx->Driver.SetReadBuffer = r128DDSetReadBuffer; + + ctx->Driver.IndexMask = NULL; + ctx->Driver.ColorMask = r128DDColorMask; + ctx->Driver.LogicOp = NULL; + ctx->Driver.Dither = r128DDDither; + + ctx->Driver.NearFar = NULL; + + ctx->Driver.RenderStart = r128DDUpdateHWState; + ctx->Driver.RenderFinish = NULL; + ctx->Driver.RasterSetup = NULL; + + ctx->Driver.RenderVBClippedTab = NULL; + ctx->Driver.RenderVBCulledTab = NULL; + ctx->Driver.RenderVBRawTab = NULL; + + ctx->Driver.ReducedPrimitiveChange = r128DDReducedPrimitiveChange; + ctx->Driver.MultipassFunc = NULL; + + ctx->Driver.AlphaFunc = r128DDAlphaFunc; + ctx->Driver.BlendEquation = NULL; + ctx->Driver.BlendFunc = r128DDBlendFunc; + ctx->Driver.BlendFuncSeparate = r128DDBlendFuncSeparate; + ctx->Driver.ClearDepth = r128DDClearDepth; + ctx->Driver.CullFace = r128DDCullFace; + ctx->Driver.FrontFace = r128DDFrontFace; + ctx->Driver.DepthFunc = r128DDDepthFunc; + ctx->Driver.DepthMask = r128DDDepthMask; + ctx->Driver.DepthRange = NULL; + ctx->Driver.Enable = r128DDEnable; + ctx->Driver.Fogfv = r128DDFogfv; + ctx->Driver.Hint = NULL; + ctx->Driver.Lightfv = NULL; + ctx->Driver.LightModelfv = NULL; + ctx->Driver.PolygonMode = NULL; + ctx->Driver.Scissor = r128DDScissor; + ctx->Driver.ShadeModel = NULL; + ctx->Driver.ClearStencil = NULL; + ctx->Driver.StencilFunc = NULL; + ctx->Driver.StencilMask = NULL; + ctx->Driver.StencilOp = NULL; + ctx->Driver.Viewport = NULL; +} + +/* Initialize the context's hardware state */ +void r128DDInitState(r128ContextPtr r128ctx) +{ + int dst_bpp, depth_bpp, pitch, i; + CARD32 depthClear; + + pitch = r128ctx->r128Screen->fbStride / r128ctx->r128Screen->bpp; + + switch (r128ctx->r128Screen->pixel_code) { + case 8: dst_bpp = R128_GMC_DST_8BPP_CI; break; + case 15: dst_bpp = R128_GMC_DST_15BPP; break; + case 16: dst_bpp = R128_GMC_DST_16BPP; break; + case 24: dst_bpp = R128_GMC_DST_24BPP; break; + case 32: dst_bpp = R128_GMC_DST_32BPP; break; + default: + fprintf(stderr, "Error: Unsupported pixel depth %d... exiting\n", + r128ctx->r128Screen->pixel_code); + exit(-1); + } + + /* FIXME: Figure out how to use 16bpp depth buffer in 32bpp mode */ + switch (r128ctx->glCtx->Visual->DepthBits) { + case 16: depthClear = 0x0000ffff; depth_bpp = R128_Z_PIX_WIDTH_16; break; + case 24: depthClear = 0x00ffffff; depth_bpp = R128_Z_PIX_WIDTH_24; break; + case 32: depthClear = 0xffffffff; depth_bpp = R128_Z_PIX_WIDTH_32; break; + default: + fprintf(stderr, "Error: Unsupported depth %d... exiting\n", + r128ctx->r128Screen->bpp); + exit(-1); + break; + } + + r128ctx->dirty = R128_ALL_DIRTY; + r128ctx->dirty_context = R128_CTX_ALL_DIRTY; + + r128ctx->RenderIndex = R128_FALLBACK_BIT; + r128ctx->PointsFunc = NULL; + r128ctx->LineFunc = NULL; + r128ctx->TriangleFunc = NULL; + r128ctx->QuadFunc = NULL; + + r128ctx->IndirectTriangles = 0; + r128ctx->Fallback = 0; + + if (r128ctx->glCtx->Visual->DBflag) { + r128ctx->drawX = r128ctx->r128Screen->backX; + r128ctx->drawY = r128ctx->r128Screen->backY; + r128ctx->readX = r128ctx->r128Screen->backX; + r128ctx->readY = r128ctx->r128Screen->backY; + } else { + r128ctx->drawX = r128ctx->r128Screen->fbX; + r128ctx->drawY = r128ctx->r128Screen->fbY; + r128ctx->readX = r128ctx->r128Screen->fbX; + r128ctx->readY = r128ctx->r128Screen->fbY; + } + + r128ctx->ClearColor = 0x00000000; + r128ctx->ClearDepth = depthClear; + + r128ctx->regs.scale_3d_cntl = + R128_SCALE_DITHER_TABLE | + R128_TEX_CACHE_SIZE_FULL | + R128_DITHER_INIT_RESET | + R128_SCALE_3D_TEXMAP_SHADE | + R128_SCALE_PIX_REPLICATE | + /* R128_TEX_CACHE_SPLIT | */ + R128_ALPHA_COMB_ADD_CLAMP | + R128_FOG_TABLE | + R128_ALPHA_BLEND_SRC_ONE | + R128_ALPHA_BLEND_DST_ZERO | + R128_ALPHA_TEST_ALWAYS | + R128_COMPOSITE_SHADOW_CMP_EQUAL | + R128_TEX_MAP_ALPHA_IN_TEXTURE | + R128_TEX_CACHE_LINE_SIZE_8QW; + + r128ctx->regs.dst_pitch_offset_c = pitch << R128_PITCH_SHIFT; + + r128ctx->regs.dp_gui_master_cntl = + R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_DST_CLIPPING | + R128_GMC_BRUSH_SOLID_COLOR | + dst_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_GMC_BYTE_MSB_TO_LSB | + R128_GMC_CONVERSION_TEMP_6500 | + R128_ROP3_S | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_3D_FCN_EN | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_AUX_CLIP_DIS | + R128_GMC_WR_MSK_DIS; + + r128ctx->regs.sc_top_left_c = 0x00000000; + r128ctx->regs.sc_bottom_right_c = 0x1fff1fff; + + r128ctx->regs.aux_sc_cntl = 0x00000000; + + r128ctx->regs.aux1_sc_left = 0x00000000; + r128ctx->regs.aux1_sc_right = 0x00001fff; + r128ctx->regs.aux1_sc_top = 0x00000000; + r128ctx->regs.aux1_sc_bottom = 0x00001fff; + + r128ctx->regs.aux2_sc_left = 0x00000000; + r128ctx->regs.aux2_sc_right = 0x00001fff; + r128ctx->regs.aux2_sc_top = 0x00000000; + r128ctx->regs.aux2_sc_bottom = 0x00001fff; + + r128ctx->regs.aux3_sc_left = 0x00000000; + r128ctx->regs.aux3_sc_right = 0x00001fff; + r128ctx->regs.aux3_sc_top = 0x00000000; + r128ctx->regs.aux3_sc_bottom = 0x00001fff; + + r128ctx->regs.z_offset_c = (r128ctx->r128Screen->depthX * + (r128ctx->r128Screen->bpp/8) + + r128ctx->r128Screen->depthY * + r128ctx->r128Screen->fbStride); + r128ctx->regs.z_pitch_c = pitch; + + r128ctx->regs.z_sten_cntl_c = + depth_bpp | + R128_Z_TEST_LESS | + R128_STENCIL_TEST_ALWAYS | + R128_STENCIL_S_FAIL_KEEP | + R128_STENCIL_ZPASS_KEEP | + R128_STENCIL_ZFAIL_KEEP; + + r128ctx->regs.tex_cntl_c = + R128_Z_WRITE_ENABLE | + R128_SHADE_ENABLE | + R128_DITHER_ENABLE | + R128_ALPHA_IN_TEX_COMPLETE_A | + R128_LIGHT_DIS | + R128_ALPHA_LIGHT_DIS | + R128_TEX_CACHE_FLUSH | + (0x0f << R128_LOD_BIAS_SHIFT); + + r128ctx->regs.misc_3d_state_cntl_reg = + R128_MISC_SCALE_3D_TEXMAP_SHADE | + R128_MISC_SCALE_PIX_REPLICATE | + R128_ALPHA_COMB_ADD_CLAMP | + R128_FOG_TABLE | + R128_ALPHA_BLEND_SRC_ONE | + R128_ALPHA_BLEND_DST_ZERO | + R128_ALPHA_TEST_ALWAYS; + + r128ctx->regs.texture_clr_cmp_clr_c = 0x00000000; + r128ctx->regs.texture_clr_cmp_msk_c = 0xffffffff; + + r128ctx->regs.prim_tex_cntl_c = + R128_MIN_BLEND_NEAREST | + R128_MAG_BLEND_NEAREST | + R128_MIP_MAP_DISABLE | + R128_TEX_CLAMP_S_WRAP | + R128_TEX_CLAMP_T_WRAP; + + r128ctx->regs.prim_texture_combine_cntl_c = + R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA; + + r128ctx->regs.tex_size_pitch_c = + (0 << R128_TEX_PITCH_SHIFT) | + (0 << R128_TEX_SIZE_SHIFT) | + (0 << R128_TEX_HEIGHT_SHIFT) | + (0 << R128_TEX_MIN_SIZE_SHIFT) | + (0 << R128_SEC_TEX_PITCH_SHIFT) | + (0 << R128_SEC_TEX_SIZE_SHIFT) | + (0 << R128_SEC_TEX_HEIGHT_SHIFT) | + (0 << R128_SEC_TEX_MIN_SIZE_SHIFT); + + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] = 0x00000000; + + r128ctx->regs.sec_tex_cntl_c = + R128_SEC_SELECT_PRIM_ST; + + r128ctx->regs.sec_tex_combine_cntl_c = + R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA; + + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] = 0x00000000; + + r128ctx->regs.constant_color_c = 0x00ffffff; + r128ctx->regs.prim_texture_border_color_c = 0x00ffffff; + r128ctx->regs.sec_texture_border_color_c = 0x00ffffff; + r128ctx->regs.sten_ref_mask_c = 0xffff0000; + r128ctx->regs.plane_3d_mask_c = 0xffffffff; + + r128ctx->regs.setup_cntl = + R128_COLOR_GOURAUD | + R128_PRIM_TYPE_TRI | +#if 1 + /* FIXME: Let r128 multiply? */ + R128_TEXTURE_ST_MULT_W | +#else + /* FIXME: Or, pre multiply? */ + R128_TEXTURE_ST_DIRECT | +#endif + R128_STARTING_VERTEX_1 | + R128_ENDING_VERTEX_3 | + R128_SU_POLY_LINE_NOT_LAST | + R128_SUB_PIX_4BITS; + + r128ctx->regs.pm4_vc_fpu_setup = + R128_FRONT_DIR_CCW | + R128_BACKFACE_SOLID | + R128_FRONTFACE_SOLID | + R128_FPU_COLOR_GOURAUD | + R128_FPU_SUB_PIX_4BITS | + R128_FPU_MODE_3D | + R128_TRAP_BITS_DISABLE | + R128_XFACTOR_2 | + R128_YFACTOR_2 | + R128_FLAT_SHADE_VERTEX_OGL | + R128_FPU_ROUND_TRUNCATE | + R128_WM_SEL_8DW; + + r128ctx->FogMode = GL_EXP; + r128ctx->regs.fog_color_c = 0x00808080; + r128ctx->regs.fog_3d_table_start = 0x00000000; + r128ctx->regs.fog_3d_table_end = 0xffffffff; + r128ctx->regs.fog_3d_table_density = 0x00000000; + + r128ctx->regs.window_xy_offset = 0x00000000; + + r128ctx->regs.dp_write_mask = 0xffffffff; + + r128ctx->regs.pc_gui_ctlstat = R128_PC_FLUSH_GUI; + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALL_DIRTY; +} + +/* Upload the fog table for the current fog mode */ +static void r128UploadFogTable(r128ContextPtr r128ctx) +{ + int i; + + R128CCE0(R128_CCE_PACKET0, R128_FOG_TABLE_INDEX, 0); + R128CCE(0x00000000); + + R128CCE0(R128_CCE_PACKET0_ONE_REG_WR, R128_FOG_TABLE_DATA, 255); + + switch (r128ctx->FogMode) { + case GL_LINEAR: + for (i = 0; i < 256; i++) { + R128CCE(255 - i); + } + break; + case GL_EXP: + for (i = 0; i < 256; i++) { + R128CCE(255 - FLOAT_TO_UBYTE(exp(i - 255))); + } + break; + case GL_EXP2: + for (i = 0; i < 256; i++) { + R128CCE(255 - FLOAT_TO_UBYTE(exp((i - 255) * (i - 255)))); + } + break; + } +} + +/* Load the current context's state into the hardware */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128LoadContext(r128ContextPtr r128ctx) +{ + int i; + int tex_size_pitch_done = GL_FALSE; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) { + fprintf(stderr, "r128LoadContext(%p)\n", r128ctx->glCtx); + } + +#if 0 + r128ctx->dirty_context = R128_CTX_ALL_DIRTY; +#endif + +#if 1 + /* FIXME: Why do these need to be updated even when they don't change? */ + r128ctx->dirty_context |= (R128_CTX_MISC | + R128_CTX_ENGINESTATE | + R128_CTX_ALPHASTATE); +#endif + +#if 1 + /* FIXME: Is this _really_ needed? */ + if (r128ctx->dirty_context) + if (!R128CCE_USE_RING_BUFFER(r128ctx->r128Screen->CCEMode)) + R128CCE_WAIT_FOR_IDLE(r128ctx); +#endif + + if (r128ctx->dirty_context & R128_CTX_MISC) { + R128CCE1(R128_CCE_PACKET1, R128_SCALE_3D_CNTL, R128_DP_WRITE_MASK); + R128CCE(r128ctx->regs.scale_3d_cntl); + R128CCE(r128ctx->regs.dp_write_mask); + + R128CCE0(R128_CCE_PACKET0, R128_DST_PITCH_OFFSET_C, 1); + R128CCE(r128ctx->regs.dst_pitch_offset_c); + R128CCE(r128ctx->regs.dp_gui_master_cntl); + + R128CCE0(R128_CCE_PACKET0, R128_TEXTURE_CLR_CMP_CLR_C, 1); + R128CCE(r128ctx->regs.texture_clr_cmp_clr_c); + R128CCE(r128ctx->regs.texture_clr_cmp_msk_c); + + R128CCE0(R128_CCE_PACKET0, R128_STEN_REF_MASK_C, 1); + R128CCE(r128ctx->regs.sten_ref_mask_c); + R128CCE(r128ctx->regs.plane_3d_mask_c); + } + + if (r128ctx->dirty_context & R128_CTX_ENGINESTATE) { + R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); + R128CCE(r128ctx->regs.tex_cntl_c); + } + + if (r128ctx->dirty_context & R128_CTX_TEX0STATE) { + R128CCE0(R128_CCE_PACKET0, R128_PRIM_TEX_CNTL_C, 2+R128_TEX_MAXLEVELS); + R128CCE(r128ctx->regs.prim_tex_cntl_c); + R128CCE(r128ctx->regs.prim_texture_combine_cntl_c); + R128CCE(r128ctx->regs.tex_size_pitch_c); + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + R128CCE(r128ctx->regs.prim_tex_offset[i]); + + R128CCE0(R128_CCE_PACKET0, R128_PRIM_TEXTURE_BORDER_COLOR_C, 0); + R128CCE(r128ctx->regs.prim_texture_border_color_c); + + tex_size_pitch_done = GL_TRUE; + } + + if (r128ctx->dirty_context & R128_CTX_TEX1STATE) { + if (!tex_size_pitch_done) { + R128CCE0(R128_CCE_PACKET0, R128_TEX_SIZE_PITCH_C, 0); + R128CCE(r128ctx->regs.tex_size_pitch_c); + } + + R128CCE0(R128_CCE_PACKET0, R128_SEC_TEX_CNTL_C, 1+R128_TEX_MAXLEVELS); + R128CCE(r128ctx->regs.sec_tex_cntl_c); + R128CCE(r128ctx->regs.sec_tex_combine_cntl_c); + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + R128CCE(r128ctx->regs.sec_tex_offset[i]); + + R128CCE0(R128_CCE_PACKET0, R128_SEC_TEXTURE_BORDER_COLOR_C, 0); + R128CCE(r128ctx->regs.sec_texture_border_color_c); + } + + if (r128ctx->dirty_context & R128_CTX_TEXENVSTATE) { + R128CCE0(R128_CCE_PACKET0, R128_CONSTANT_COLOR_C, 0); + R128CCE(r128ctx->regs.constant_color_c); + } + + if (r128ctx->dirty_context & R128_CTX_FOGSTATE) { + R128CCE0(R128_CCE_PACKET0, R128_FOG_3D_TABLE_START, 1); + R128CCE(r128ctx->regs.fog_3d_table_start); + R128CCE(r128ctx->regs.fog_3d_table_end); + + R128CCE1(R128_CCE_PACKET1, + R128_FOG_COLOR_C, R128_FOG_3D_TABLE_DENSITY); + R128CCE(r128ctx->regs.fog_color_c); + R128CCE(r128ctx->regs.fog_3d_table_density); + } + + if (r128ctx->dirty_context & R128_CTX_FOGTABLE) { + r128UploadFogTable(r128ctx); + } + + if (r128ctx->dirty_context & R128_CTX_ZSTENSTATE) { + R128CCE0(R128_CCE_PACKET0, R128_Z_STEN_CNTL_C, 0); + R128CCE(r128ctx->regs.z_sten_cntl_c); + } + + if (r128ctx->dirty_context & R128_CTX_SCISSORS) { + R128CCE0(R128_CCE_PACKET0, R128_SC_TOP_LEFT_C, 1); + R128CCE(r128ctx->regs.sc_top_left_c); + R128CCE(r128ctx->regs.sc_bottom_right_c); + } + + if (r128ctx->dirty_context & (R128_CTX_ALPHASTATE | + R128_CTX_FOGSTATE)) { + R128CCE0(R128_CCE_PACKET0, R128_MISC_3D_STATE_CNTL_REG, 0); + R128CCE(r128ctx->regs.misc_3d_state_cntl_reg); + } + + if (r128ctx->dirty_context & R128_CTX_SETUPSTATE) { + R128CCE1(R128_CCE_PACKET1, R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP); + R128CCE(r128ctx->regs.setup_cntl); + R128CCE(r128ctx->regs.pm4_vc_fpu_setup); + } + + if (r128ctx->dirty_context & R128_CTX_WIN_Z_POS) { + R128CCE0(R128_CCE_PACKET0, R128_WINDOW_XY_OFFSET, 0); + R128CCE(r128ctx->regs.window_xy_offset); + + R128CCE0(R128_CCE_PACKET0, R128_Z_OFFSET_C, 1); + R128CCE(r128ctx->regs.z_offset_c); + R128CCE(r128ctx->regs.z_pitch_c); + } + +#if 0 + if (r128ctx->dirty_context & R128_CTX_FLUSH_PIX_CACHE) { + R128CCE0(R128_CCE_PACKET0, R128_PC_GUI_CTLSTAT, 0); + R128CCE(r128ctx->regs.pc_gui_ctlstat); + } +#endif + + R128CCE_SUBMIT_PACKETS(); + + /* Turn off the texture cache flushing */ + r128ctx->regs.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; + + /* Turn off the pixel cache flushing */ + r128ctx->regs.pc_gui_ctlstat &= ~R128_PC_FLUSH_ALL; + + r128ctx->dirty_context = R128_CTX_CLEAN; +} + +/* Set the hardware clip rects for drawing to the current color buffer */ +/* NOTE: This function is only called while holding the hardware lock */ +void r128SetClipRects(r128ContextPtr r128ctx, + XF86DRIClipRectPtr pc, int nc) +{ + if (!pc) return; + + /* Clear any previous auxiliary scissors */ + r128ctx->regs.aux_sc_cntl = 0x00000000; + + switch (nc) { + case 3: + R128CCE0(R128_CCE_PACKET0, R128_AUX3_SC_LEFT, 3); + R128CCE(pc[2].x1 + r128ctx->drawX); + R128CCE(pc[2].x2-1 + r128ctx->drawX); + R128CCE(pc[2].y1 + r128ctx->drawY); + R128CCE(pc[2].y2-1 + r128ctx->drawY); + + r128ctx->regs.aux_sc_cntl |= R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR; + + case 2: + R128CCE0(R128_CCE_PACKET0, R128_AUX2_SC_LEFT, 3); + R128CCE(pc[1].x1 + r128ctx->drawX); + R128CCE(pc[1].x2-1 + r128ctx->drawX); + R128CCE(pc[1].y1 + r128ctx->drawY); + R128CCE(pc[1].y2-1 + r128ctx->drawY); + + r128ctx->regs.aux_sc_cntl |= R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR; + + case 1: + R128CCE0(R128_CCE_PACKET0, R128_AUX1_SC_LEFT, 3); + R128CCE(pc[0].x1 + r128ctx->drawX); + R128CCE(pc[0].x2-1 + r128ctx->drawX); + R128CCE(pc[0].y1 + r128ctx->drawY); + R128CCE(pc[0].y2-1 + r128ctx->drawY); + + r128ctx->regs.aux_sc_cntl |= R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR; + break; + + default: + return; + } + + R128CCE0(R128_CCE_PACKET0, R128_AUX_SC_CNTL, 0); + R128CCE(r128ctx->regs.aux_sc_cntl); + + R128CCE_SUBMIT_PACKETS(); +} + +/* Update the driver's notion of the window position */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateWindowPosition(r128ContextPtr r128ctx) +{ + int x = r128ctx->driDrawable->x + r128ctx->drawX; + int y = r128ctx->driDrawable->y + r128ctx->drawY; + +#if 0 + /* FIXME: Is this _really_ needed? */ + R128CCE_FLUSH_VB(r128ctx); +#endif + r128ctx->regs.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) | + (x << R128_WINDOW_X_SHIFT)); + + /* Recalculate the Z buffer offset since we might be drawing to the + back buffer and window_xy_offset affects both color buffer and + depth drawing */ + r128ctx->regs.z_offset_c = ((r128ctx->r128Screen->depthX - + r128ctx->drawX) * + (r128ctx->r128Screen->bpp/8) + + (r128ctx->r128Screen->depthY - + r128ctx->drawY) * + r128ctx->r128Screen->fbStride); + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_WIN_Z_POS; +} + +/* Update the hardware state */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateHWStateLocked(r128ContextPtr r128ctx) +{ + if (r128ctx->dirty & R128_REQUIRE_QUIESCENCE) + R128CCE_WAIT_FOR_IDLE(r128ctx); + + /* Update any state that might have changed recently */ + + /* Update the clip rects */ + if (r128ctx->dirty & R128_UPDATE_WINPOS) + r128UpdateWindowPosition(r128ctx); + + /* Update texture state and then upload the images */ + /* Note: Texture images can only be updated after the state has been set */ + if (r128ctx->dirty & R128_UPDATE_TEXSTATE) + r128UpdateTextureState(r128ctx); + if (r128ctx->dirty & R128_UPDATE_TEX0IMAGES) + r128UploadTexImages(r128ctx, r128ctx->CurrentTexObj[0]); + if (r128ctx->dirty & R128_UPDATE_TEX1IMAGES) + r128UploadTexImages(r128ctx, r128ctx->CurrentTexObj[1]); + + /* Load the state into the hardware */ + /* Note: This must be done after all other state has been set */ + if (r128ctx->dirty & R128_UPDATE_CONTEXT) + r128LoadContext(r128ctx); + + r128ctx->dirty = R128_CLEAN; +} + +/* Update the hardware state */ +void r128UpdateHWState(r128ContextPtr r128ctx) +{ + LOCK_HARDWARE(r128ctx); + r128UpdateHWStateLocked(r128ctx); + UNLOCK_HARDWARE(r128ctx); +} + +/* Update the driver's state */ +/* NOTE: This function is only called while holding the hardware lock */ +void r128UpdateState(r128ContextPtr r128ctx, int winMoved) +{ + R128SAREAPrivPtr sarea = r128ctx->r128Screen->SAREA; + int i; + + if (sarea->ctxOwner != r128ctx->driContext->hHWContext) { + sarea->ctxOwner = r128ctx->driContext->hHWContext; + r128ctx->dirty_context = R128_CTX_ALL_DIRTY; + r128LoadContext(r128ctx); + } + + for (i = 0; i < r128ctx->r128Screen->NRTexHeaps; i++) + r128AgeTextures(r128ctx, i); + + if (winMoved) r128ctx->dirty |= R128_UPDATE_WINPOS; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_state.h b/xc/lib/GL/mesa/src/drv/r128/r128_state.h new file mode 100644 index 000000000..f847452f0 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_state.h @@ -0,0 +1,50 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_STATE_H_ +#define _R128_STATE_H_ + +#ifdef GLX_DIRECT_RENDERING + +extern void r128DDInitState(r128ContextPtr r128ctx); +extern void r128DDInitStateFuncs(GLcontext *ctx); + +extern void r128UpdateState(r128ContextPtr r128ctx, int winMoved); +extern void r128UpdateHWState(r128ContextPtr r128ctx); + +extern void r128SetClipRects(r128ContextPtr r128ctx, + XF86DRIClipRectPtr pc, int nc); + +#endif +#endif /* _R128_STATE_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_swap.c b/xc/lib/GL/mesa/src/drv/r128/r128_swap.c new file mode 100644 index 000000000..6b347023d --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_swap.c @@ -0,0 +1,125 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_state.h" +#include "r128_vb.h" +#include "r128_swap.h" + +/* Copy the back color buffer to the front color buffer */ +void r128SwapBuffers(r128ContextPtr r128ctx) +{ + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; + int nc; + XF86DRIClipRectPtr c; + int dst_bpp; + CARD32 swapAge; + + if (r128ctx->SWonly) { + /* FIXME: Provide software fallback for this case?? */ + } + + switch (r128ctx->r128Screen->bpp) { + case 8: + dst_bpp = R128_GMC_DST_8BPP_CI; + break; + case 16: + if (r128ctx->r128Screen->depth == 15) dst_bpp = R128_GMC_DST_15BPP; + else dst_bpp = R128_GMC_DST_16BPP; + break; + case 24: + dst_bpp = R128_GMC_DST_24BPP; + break; + case 32: + default: + dst_bpp = R128_GMC_DST_32BPP; + break; + } + + LOCK_HARDWARE(r128ctx); + + /* Flush any outstanding vertex buffers */ + R128CCE_FLUSH_VB(r128ctx); + + /* Throttle the frame rate -- only allow one pending swap buffers + request at a time */ + while (r128ctx->lastSwapAge > (swapAge = INREG(R128_SWAP_AGE_REG))); + + /* Init the clip rects here in case they changed during the + LOCK_HARDWARE macro */ + c = dPriv->pClipRects; + nc = dPriv->numClipRects; + + /* Cycle through the clip rects */ + while (nc--) { + int fx = c[nc].x1; + int fy = c[nc].y1; + int fw = c[nc].x2 - fx; + int fh = c[nc].y2 - fy; + int bx = fx + r128ctx->r128Screen->backX; + int by = fy + r128ctx->r128Screen->backY; + + fx += r128ctx->r128Screen->fbX; + fy += r128ctx->r128Screen->fbY; + + R128CCE3(R128_CCE_PACKET3_CNTL_BITBLT_MULTI, 3); + R128CCE(R128_GMC_BRUSH_NONE + | R128_GMC_SRC_DATATYPE_COLOR + | R128_DP_SRC_SOURCE_MEMORY + | dst_bpp + | R128_ROP3_S); + R128CCE((bx << 16) | by); + R128CCE((fx << 16) | fy); + R128CCE((fw << 16) | fh); + } + + ++swapAge; + R128CCE0(R128_CCE_PACKET0, R128_SWAP_AGE_REG, 0); + R128CCE(swapAge); + r128ctx->lastSwapAge = swapAge; + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALL_DIRTY; + + R128CCE_SUBMIT_PACKETS(); + + UNLOCK_HARDWARE(r128ctx); +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_swap.h b/xc/lib/GL/mesa/src/drv/r128/r128_swap.h new file mode 100644 index 000000000..32851041c --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_swap.h @@ -0,0 +1,43 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_SWAP_H_ +#define _R128_SWAP_H_ + +#ifdef GLX_DIRECT_RENDERING + +extern void r128SwapBuffers(r128ContextPtr r128ctx); + +#endif +#endif /* _R128_SWAP_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tex.c b/xc/lib/GL/mesa/src/drv/r128/r128_tex.c new file mode 100644 index 000000000..d75345404 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tex.c @@ -0,0 +1,1851 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Gareth Hughes <gareth@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_state.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_vb.h" +#include "r128_tex.h" + +#include "mmath.h" +#include "simple_list.h" + +static void r128SetTexWrap(r128TexObjPtr t, GLenum srwap, GLenum twrap); +static void r128SetTexFilter(r128TexObjPtr t, GLenum minf, GLenum magf); +static void r128SetTexBorderColor(r128TexObjPtr t, GLubyte c[4]); + +/* Allocate and initialize hardware state associated with texture `t' */ +/* NOTE: This function is only called while holding the hardware lock */ +static r128TexObjPtr r128CreateTexObj(r128ContextPtr r128ctx, + struct gl_texture_object *tObj) +{ + r128TexObjPtr t; + struct gl_texture_image *image; + int log2Pitch, log2Height, log2Size, log2MinSize; + int totalSize; + int i; + + image = tObj->Image[0]; + if (!image) return NULL; /* ERROR!!! */ + + t = (r128TexObjPtr)calloc(1,sizeof(*t)); + if (!t) return NULL; /* ERROR!!! */ + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) + fprintf(stderr, "r128CreateTexObj(%p)\n", tObj); + + switch (image->Format) { + case GL_RGBA: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + if (r128ctx->r128Screen->bpp == 32) { + t->texelBytes = 4; + t->textureFormat = R128_DATATYPE_ARGB8888; + } else { + t->texelBytes = 2; + t->textureFormat = R128_DATATYPE_ARGB4444; + } + break; + + case GL_RGB: + if (r128ctx->r128Screen->bpp == 32) { + t->texelBytes = 4; + t->textureFormat = R128_DATATYPE_ARGB8888; + } else { + t->texelBytes = 2; + t->textureFormat = R128_DATATYPE_RGB565; + } + break; + + case GL_LUMINANCE: + if (r128ctx->r128Screen->bpp == 32) { + t->texelBytes = 4; + t->textureFormat = R128_DATATYPE_ARGB8888; + } else { + t->texelBytes = 2; + /* Use this to get true greys */ + t->textureFormat = R128_DATATYPE_ARGB1555; + } + break; + + case GL_COLOR_INDEX: + t->texelBytes = 1; + t->textureFormat = R128_DATATYPE_CI8; + break; + + default: + /* ERROR!!! */ + fprintf(stderr, "r128CreateTexObj: bad image->Format\n"); + free(t); + return NULL; + } + + /* Calculate dimensions in log domain */ + for (i = 1, log2Height = 0; i < image->Height; i *= 2) log2Height++; + for (i = 1, log2Pitch = 0; i < image->Width; i *= 2) log2Pitch++; + if (image->Width > image->Height) log2Size = log2Pitch; + else log2Size = log2Height; + + t->dirty_images = 0; + + /* Calculate mipmap offsets and dimensions */ + totalSize = 0; + for (i = 0; i <= log2Size && tObj->Image[i]; i++) { + t->image[i].offset = totalSize; + t->image[i].width = tObj->Image[i]->Width; + t->image[i].height = tObj->Image[i]->Height; + t->dirty_images |= 1 << i; + totalSize += (tObj->Image[i]->Height * + tObj->Image[i]->Width * + t->texelBytes); + + /* Offsets must be 32-byte aligned for host data blits */ + totalSize = (totalSize + 31) & ~31; + } + log2MinSize = log2Size - i + 1; + + t->totalSize = totalSize; + t->internFormat = image->IntFormat; + + t->bound = 0; + t->heap = 0; /* This is set in r128UploadTexImages */ + t->tObj = tObj; + + t->memBlock = NULL; + t->bufAddr = NULL; + + t->regs.tex_cntl = t->textureFormat; + t->regs.size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) | + (log2Size << R128_TEX_SIZE_SHIFT) | + (log2Height << R128_TEX_HEIGHT_SHIFT) | + (log2MinSize << R128_TEX_MIN_SIZE_SHIFT)); + t->regs.border_color = 0x00000000; + + if (log2MinSize == log2Size || + log2MinSize != 0) + t->regs.tex_cntl |= R128_MIP_MAP_DISABLE; + + r128SetTexWrap(t, tObj->WrapS, tObj->WrapT); + r128SetTexFilter(t, tObj->MinFilter, tObj->MagFilter); + r128SetTexBorderColor(t, tObj->BorderColor); + + tObj->DriverData = t; + + make_empty_list(t); + + return t; +} + +/* Destroy hardware state associated with texture `t' */ +/* NOTE: This function can be called while holding the hardware lock and + while not holding the lock*/ +void r128DestroyTexObj(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + if (!t) return; + + if (t->memBlock) { + mmFreeMem(t->memBlock); + t->memBlock = NULL; + } + + if (t->tObj) t->tObj->DriverData = NULL; + if (t->bound) r128ctx->CurrentTexObj[t->bound-1] = NULL; + + remove_from_list(t); + free(t); +} + +/* Keep track of swapped out texture objects */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128SwapOutTexObj(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + if (t->memBlock) { + mmFreeMem(t->memBlock); + t->memBlock = NULL; + } + + t->dirty_images = ~0; + move_to_tail(&r128ctx->SwappedOut, t); +} + +/* Print out debugging information about texture LRU */ +void r128PrintLocalLRU(r128ContextPtr r128ctx, int heap) +{ + r128TexObjPtr t; + int sz = 1 << (r128ctx->r128Screen->log2TexGran[heap]); + + foreach(t, &r128ctx->TexObjList[heap]) { + if (!t->tObj) { + fprintf(stderr, "Placeholder %d at 0x%x sz 0x%x\n", + t->memBlock->ofs / sz, + t->memBlock->ofs, + t->memBlock->size); + } else { + fprintf(stderr, "Texture (bound %d) at 0x%x sz 0x%x\n", + t->bound, + t->memBlock->ofs, + t->memBlock->size); + } + } +} + +void r128PrintGlobalLRU(r128ContextPtr r128ctx, int heap) +{ + R128TexRegion *list = r128ctx->r128Screen->SAREA->texList[heap]; + int i, j; + + for (i = 0, j = R128_NR_TEX_REGIONS ; i < R128_NR_TEX_REGIONS ; i++) { + fprintf(stderr, "list[%d] age %d next %d prev %d\n", + j, list[j].age, list[j].next, list[j].prev); + j = list[j].next; + if (j == R128_NR_TEX_REGIONS) break; + } + + if (j != R128_NR_TEX_REGIONS) { + fprintf(stderr, "Loop detected in global LRU\n"); + } +} + +/* Reset the global texture LRU */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128ResetGlobalLRU(r128ContextPtr r128ctx, int heap) +{ + R128TexRegion *list = r128ctx->r128Screen->SAREA->texList[heap]; + int log2sz = 1 << r128ctx->r128Screen->log2TexGran[heap]; + int i; + + /* + * (Re)initialize the global circular LRU list. The last element in + * the array (R128_NR_TEX_REGIONS) is the sentinal. Keeping it at + * the end of the array allows it to be addressed rationally when + * looking up objects at a particular location in texture memory. + */ + + for (i = 0; (i+1) * log2sz <= r128ctx->r128Screen->texSize[heap]; i++) { + list[i].prev = i-1; + list[i].next = i+1; + list[i].age = 0; + } + + i--; + list[0].prev = R128_NR_TEX_REGIONS; + list[i].prev = i-1; + list[i].next = R128_NR_TEX_REGIONS; + list[R128_NR_TEX_REGIONS].prev = i; + list[R128_NR_TEX_REGIONS].next = 0; + r128ctx->r128Screen->SAREA->texAge[heap] = 0; +} + +/* Update the local and glock texture LRUs */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateTexLRU(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + int heap = t->heap; + R128TexRegion *list = r128ctx->r128Screen->SAREA->texList[heap]; + int log2sz = r128ctx->r128Screen->log2TexGran[heap]; + + int start = t->memBlock->ofs >> log2sz; + int end = (t->memBlock->ofs + t->memBlock->size-1) >> log2sz; + int i; + + r128ctx->lastTexAge[heap] = ++r128ctx->r128Screen->SAREA->texAge[heap]; + + /* Update our local LRU */ + move_to_head(&r128ctx->TexObjList[heap], t); + + /* Update the global LRU */ + for (i = start ; i <= end ; i++) { + list[i].in_use = 1; + list[i].age = r128ctx->lastTexAge[heap]; + + /* remove_from_list(i) */ + list[(CARD32)list[i].next].prev = list[i].prev; + list[(CARD32)list[i].prev].next = list[i].next; + + /* insert_at_head(list, i) */ + list[i].prev = R128_NR_TEX_REGIONS; + list[i].next = list[R128_NR_TEX_REGIONS].next; + list[(CARD32)list[R128_NR_TEX_REGIONS].next].prev = i; + list[R128_NR_TEX_REGIONS].next = i; + } +} + +/* Update our notion of what textures have been changed since we last + held the lock. This pertains to both our local textures and the + textures belonging to other clients. Keep track of other client's + textures by pushing a placeholder texture onto the LRU list -- these + are denoted by (tObj == NULL). */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128TexturesGone(r128ContextPtr r128ctx, int heap, + int offset, int size, int in_use) +{ + r128TexObjPtr t, tmp; + + foreach_s (t, tmp, &r128ctx->TexObjList[heap]) { + if (t->memBlock->ofs >= offset + size || + t->memBlock->ofs + t->memBlock->size <= offset) + continue; + + /* It overlaps - kick it out. Need to hold onto the currently + bound objects, however. */ + if (t->bound) r128SwapOutTexObj(r128ctx, t); + else r128DestroyTexObj(r128ctx, t); + } + + if (in_use) { + t = (r128TexObjPtr) calloc(1,sizeof(*t)); + if (!t) return; + + t->memBlock = mmAllocMem(r128ctx->texHeap[heap], size, 0, offset); + insert_at_head(&r128ctx->TexObjList[heap], t); + } +} + +/* Update our client's shared texture state. If another client has + modified a region in which we have textures, then we need to figure + out which of our textures has been removed, and update our global + LRU. */ +void r128AgeTextures(r128ContextPtr r128ctx, int heap) +{ + R128SAREAPrivPtr sarea = r128ctx->r128Screen->SAREA; + + if (sarea->texAge[heap] != r128ctx->lastTexAge[heap]) { + int log2sz = 1 << r128ctx->r128Screen->log2TexGran[heap]; + int nr = 0; + int idx; + + for (idx = sarea->texList[heap][R128_NR_TEX_REGIONS].prev; + idx != R128_NR_TEX_REGIONS && nr < R128_NR_TEX_REGIONS; + idx = sarea->texList[heap][idx].prev, nr++) { + + /* If switching texturing schemes, then the SAREA might not + have been properly cleared, so we need to reset the + global texture LRU. */ + if (idx * log2sz > r128ctx->r128Screen->texSize[heap]) { + nr = R128_NR_TEX_REGIONS; + break; + } + + if (sarea->texList[heap][idx].age > r128ctx->lastTexAge[heap]) + r128TexturesGone(r128ctx, heap, idx * log2sz, log2sz, + sarea->texList[heap][idx].in_use); + } + + if (nr == R128_NR_TEX_REGIONS) { + r128TexturesGone(r128ctx, heap, + 0, r128ctx->r128Screen->texSize[heap], 0); + r128ResetGlobalLRU(r128ctx, heap); + } + + r128ctx->dirty |= R128_UPDATE_TEX0IMAGES; + r128ctx->dirty |= R128_UPDATE_TEX1IMAGES; + r128ctx->lastTexAge[heap] = sarea->texAge[heap]; + } +} + +/* Convert a block of Mesa-formatted texture to an 8bpp hardware format */ +static void r128ConvertTexture8bpp(r128ContextPtr r128ctx, + struct gl_texture_image *image, + int x, int y, int width, int height, + int pitch) +{ + CARD8 *src; + CARD32 pix; + int i, j; + + switch (image->Format) { + case GL_RGB: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3; + for (j = width >> 2; j; j--) { + pix = ((R128PACKCOLOR332( src[0], src[1], src[2]) ) | + (R128PACKCOLOR332( src[3], src[4], src[5]) << 8) | + (R128PACKCOLOR332( src[6], src[7], src[8]) << 16) | + (R128PACKCOLOR332( src[9], src[10], src[11]) << 24)); + R128CCE(pix); + src += 12; + } + } + break; + + case GL_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + case GL_COLOR_INDEX: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x); + for (j = width >> 2; j; j--) { + pix = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); + R128CCE(pix); + src += 4; + } + } + break; + + default: + fprintf(stderr, "r128ConvertTexture8bpp: unsupported format 0x%x\n", + image->Format); + } +} + +/* Convert a block of Mesa-formatted texture to a 16bpp hardware format */ +static void r128ConvertTexture16bpp(r128ContextPtr r128ctx, + struct gl_texture_image *image, + int x, int y, int width, int height, + int pitch) +{ + CARD8 *src; + CARD32 pix; + int i, j; + + switch (image->Format) { + case GL_RGB: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3; + for (j = width >> 1; j; j--) { + pix = ((R128PACKCOLOR565(src[0], src[1], src[2]) ) | + (R128PACKCOLOR565(src[3], src[4], src[5]) << 16)); + R128CCE(pix); + src += 6; + } + } + break; + + case GL_RGBA: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 4; + for (j = width >> 1; j; j--) { + pix = + ((R128PACKCOLOR4444(src[0], src[1], src[2], src[3]) ) | + (R128PACKCOLOR4444(src[4], src[5], src[6], src[7])<<16)); + R128CCE(pix); + src += 8; + } + } + break; + + case GL_ALPHA: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x); + for (j = width >> 1; j; j--) { + pix = ((R128PACKCOLOR4444(0xff, 0xff, 0xff, src[0]) ) | + (R128PACKCOLOR4444(0xff, 0xff, 0xff, src[1]) << 16)); + R128CCE(pix); + src += 2; + } + } + break; + + case GL_LUMINANCE: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x); + for (j = width >> 1; j; j--) { + pix = ((R128PACKCOLOR1555(src[0], src[0], src[0], 0xff) ) | + (R128PACKCOLOR1555(src[1], src[1], src[1], 0xff)<<16)); + R128CCE(pix); + src += 2; + } + } + break; + + case GL_LUMINANCE_ALPHA: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 2; + for (j = width >> 1; j; j--) { + pix = + ((R128PACKCOLOR4444(src[0], src[0], src[0], src[1]) ) | + (R128PACKCOLOR4444(src[2], src[2], src[2], src[3])<<16)); + R128CCE(pix); + src += 4; + } + } + break; + + case GL_INTENSITY: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x); + for (j = width >> 1; j; j--) { + pix = + ((R128PACKCOLOR4444(src[0], src[0], src[0], src[0]) ) | + (R128PACKCOLOR4444(src[1], src[1], src[1], src[1])<<16)); + R128CCE(pix); + src += 2; + } + } + break; + + default: + fprintf(stderr, "r128ConvertTexture16bpp: unsupported format 0x%x\n", + image->Format); + } +} + +/* Convert a block of Mesa-formatted texture to a 32bpp hardware format */ +static void r128ConvertTexture32bpp(r128ContextPtr r128ctx, + struct gl_texture_image *image, + int x, int y, int width, int height, + int pitch) +{ + CARD8 *src; + CARD32 pix; + int i, j; + + switch (image->Format) { + case GL_RGB: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3; + for (j = width; j; j--) { + pix = R128PACKCOLOR8888(src[0], src[1], src[2], 0xff); + R128CCE(pix); + src += 3; + } + } + break; + + case GL_RGBA: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 4; + for (j = width; j; j--) { + pix = R128PACKCOLOR8888(src[0], src[1], src[2], src[3]); + R128CCE(pix); + src += 4; + } + } + break; + + case GL_ALPHA: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x); + for (j = width; j; j--) { + pix = R128PACKCOLOR8888(0xff, 0xff, 0xff, src[0]); + R128CCE(pix); + src += 1; + } + } + break; + + case GL_LUMINANCE: + for (i = 0 ; i < height ; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x); + for (j = width; j; j--) { + pix = R128PACKCOLOR8888(src[0], src[0], src[0], 0xff); + R128CCE(pix); + src += 1; + } + } + break; + + case GL_LUMINANCE_ALPHA: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 2; + for (j = width; j; j-- ) { + pix = R128PACKCOLOR8888(src[0], src[0], src[0], src[1]); + R128CCE(pix); + src += 2; + } + } + break; + + case GL_INTENSITY: + for (i = 0; i < height; i++) { + src = (CARD8 *)image->Data + ((y + i) * pitch + x); + for (j = width; j; j--) { + pix = R128PACKCOLOR8888(src[0], src[0], src[0], src[0]); + R128CCE(pix); + src += 1; + } + } + break; + + default: + fprintf(stderr, "r128ConvertTexture32bpp: unsupported format 0x%x\n", + image->Format); + } +} + +/* Upload the texture image associated with texture `t' at level `level' + at the address relative to `start'. */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UploadSubImage(r128ContextPtr r128ctx, + r128TexObjPtr t, int level, + int x, int y, int width, int height) +{ + struct gl_texture_image *image; + int texelsPerDword = 0; + int imageWidth, imageHeight; + int remaining, rows; + int format, pitch, dwords; + CARD32 offset; + + /* Ensure we have a valid texture to upload */ + if (level < 0 || level > R128_TEX_MAXLEVELS) return; + if (!(image = t->tObj->Image[level])) return; + + /* FIXME: support RGB888 (i.e., 24bpp) textures? */ + switch (t->texelBytes) { + case 1: texelsPerDword = 4; break; + case 2: texelsPerDword = 2; break; + case 4: texelsPerDword = 1; break; + } + + imageWidth = image->Width; + imageHeight = image->Height; + + format = t->textureFormat >> 16; + + /* The texel upload routines have a minimum width, so force the size + if needed */ + if (imageWidth < texelsPerDword) { + int factor; + + factor = texelsPerDword / imageWidth; + imageWidth = texelsPerDword; + imageHeight /= factor; + if (imageHeight == 0) { + /* In this case, the texel converter will actually walk a + texel or two off the end of the image, but normal malloc + alignment should prevent it from ever causing a fault. */ + imageHeight = 1; + } + } + + /* We can't upload to a pitch less than 8 texels so we will need to + linearly upload all modified rows for textures smaller than this. + This makes the x/y/width/height different for the blitter and the + texture walker. */ + if (imageWidth >= 8) { + /* The texture walker and the blitter look identical */ + pitch = imageWidth >> 3; + } else { + int factor; + int y2; + int start, end; + + start = (y * imageWidth) & ~7; + end = (y + height) * imageWidth; + + if (end - start < 8) { + /* Handle the case where the total number of texels uploaded + is < 8 */ + x = 0; + y = start / 8; + width = end - start; + height = 1; + } else { + /* Upload some number of full 8 texel blit rows */ + factor = 8 / imageWidth; + + y2 = y + height - 1; + y /= factor; + y2 /= factor; + + x = 0; + width = 8; + height = y2 - y + 1; + } + + /* Fixed pitch of 8 */ + pitch = 1; + } + + dwords = width * height / texelsPerDword; + offset = (CARD32)(t->bufAddr + t->image[level].offset); + + /* Fix offset for AGP textures */ + if (t->heap == R128_AGP_TEX_HEAP) + offset += R128_AGP_TEX_OFFSET + r128ctx->r128Screen->agpTexOffset; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) { + fprintf(stderr, "r128UploadSubImage: %d,%d of %d,%d at %d,%d\n", + width, height, image->Width, image->Height, x, y); + fprintf(stderr, " blit ofs: 0x%08x pitch: 0x%x dwords: %d " + "level: %d format: %x\n", + (int)offset, pitch, dwords, level, format); + } + + /* Subdivide the texture if required */ + if (dwords < R128_CCE_PACKET_MAX_DWORDS) { + rows = height; + } else { + rows = (R128_CCE_PACKET_MAX_DWORDS * texelsPerDword) / (2 * width); + } + + /* Flush the pixel cache, and mark the contents as Read Invalid */ + R128CCE0(R128_CCE_PACKET0, R128_PC_GUI_CTLSTAT, 0); + R128CCE(r128ctx->regs.pc_gui_ctlstat | + R128_PC_RI_GUI | + R128_PC_FLUSH_GUI); + R128CCE_SUBMIT_PACKETS(); + + /* Build the CCE host data blit header */ + R128CCE3(R128_CCE_PACKET3_CNTL_HOSTDATA_BLT, 0); + + /* DP_GUI_MASTER_CNTL */ + R128CCE(R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_NONE | + (format << 8) | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_S | + R128_DP_SRC_SOURCE_HOST_DATA | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_AUX_CLIP_DIS | + R128_GMC_WR_MSK_DIS ); + + /* DST_OFFSET_PITCH - fixed at the moment until we get better ring + control */ + R128CCE((pitch << 21) | (offset>>5)); + + /* FRGD_COLOR, BKGD_COLOR */ + R128CCE(0xffffffff); + R128CCE(0xffffffff); + + for (remaining = height; remaining > 0; remaining -= rows, y += rows) { + height = (remaining >= rows) ? rows : remaining; + dwords = width * height / texelsPerDword; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) { + fprintf(stderr, " blitting: %d,%d at %d,%d - %d dwords\n", + width, height, x, y, dwords); + } + + r128ctx->CCEbuf[0] &= ~R128_CCE_PACKET_COUNT_MASK; + r128ctx->CCEbuf[0] |= (dwords + 6) << 16; + + /* Blit coords, size */ + R128CCE((y << 16) | x); + R128CCE((height << 16) | width); + R128CCE(dwords); + + /* Actually do the texture conversion */ + switch (t->texelBytes) { + case 1: + r128ConvertTexture8bpp(r128ctx, image, + x, y, width, height, width); + break; + case 2: + r128ConvertTexture16bpp(r128ctx, image, + x, y, width, height, width); + break; + case 4: + r128ConvertTexture32bpp(r128ctx, + image, x, y, width, height, width); + break; + } + + /* Flush the pixel cache */ + R128CCE0(R128_CCE_PACKET0, R128_PC_GUI_CTLSTAT, 0 ); + R128CCE(r128ctx->regs.pc_gui_ctlstat | R128_PC_FLUSH_GUI); + + /* Save the partial blit header */ + R128CCE_SUBMIT_PACKETS(); + r128ctx->CCEcount = 5; + } + + /* Clean up CCE ring buffer */ + r128ctx->CCEcount = 0; +} + +/* Upload the texture images associated with texture `t'. This might + require removing our own and/or other client's texture objects to + make room for these images. */ +/* NOTE: This function is only called while holding the hardware lock */ +int r128UploadTexImages(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + int i; + int minLevel; + int maxLevel; + int heap; + + if (!t) return 0; + + /* Choose the heap appropriately */ + heap = t->heap = R128_LOCAL_TEX_HEAP; + if (!r128ctx->r128Screen->IsPCI && + t->totalSize > r128ctx->r128Screen->texSize[heap]) + heap = t->heap = R128_AGP_TEX_HEAP; + + /* Do we need to eject LRU texture objects? */ + if (!t->memBlock) { + /* Allocate a memory block on a 4k boundary (1<<12 == 4096) */ + t->memBlock = mmAllocMem(r128ctx->texHeap[heap], t->totalSize, 12, 0); + + /* Try AGP before kicking anything out of local mem */ + if (!t->memBlock && heap == R128_LOCAL_TEX_HEAP) { + t->memBlock = mmAllocMem(r128ctx->texHeap[R128_AGP_TEX_HEAP], + t->totalSize, 12, 0); + + if (t->memBlock) heap = t->heap = R128_AGP_TEX_HEAP; + } + + /* Kick out textures until the requested texture fits */ + while (!t->memBlock) { + if (r128ctx->TexObjList[heap].prev->bound) { + fprintf(stderr, + "r128UploadTexImages: ran into bound texture\n"); + return -1; + } + if (r128ctx->TexObjList[heap].prev == + &(r128ctx->TexObjList[heap])) { + if (r128ctx->r128Screen->IsPCI) { + fprintf(stderr, "r128UploadTexImages: upload texture " + "failure on local texture heaps, sz=%d\n", + t->totalSize); + return -1; + } else if (heap == R128_LOCAL_TEX_HEAP) { + heap = t->heap = R128_AGP_TEX_HEAP; + continue; + } else { + fprintf(stderr, "r128UploadTexImages: upload texture " + "failure on both local and AGP texture heaps, " + "sz=%d\n", + t->totalSize); + return -1; + } + } + + r128DestroyTexObj(r128ctx, r128ctx->TexObjList[heap].prev); + + t->memBlock = mmAllocMem(r128ctx->texHeap[heap], + t->totalSize, 12, 0); + } + + /* Set the base offset of the texture image */ + t->bufAddr = (unsigned char *)r128ctx->r128Screen->texOffset[heap]; + t->bufAddr += t->memBlock->ofs; + + maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT); + minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> + R128_TEX_MIN_SIZE_SHIFT); + + /* Update the hardware's texture image addresses */ + switch (t->bound) { + case 1: + /* Set texture offsets */ + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] = (CARD32)t->bufAddr; + } else { + for (i = maxLevel; i >= minLevel; i--) + r128ctx->regs.prim_tex_offset[i] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } + /* Fix AGP texture offsets */ + if (heap == R128_AGP_TEX_HEAP) + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] += + R128_AGP_TEX_OFFSET + + r128ctx->r128Screen->agpTexOffset; + /* Force loading the new state into the hardware */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX0STATE; + break; + + case 2: + /* Set texture offsets */ + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] = (CARD32)t->bufAddr; + } else { + for (i = maxLevel; i >= minLevel; i--) + r128ctx->regs.sec_tex_offset[i] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } + /* Fix AGP texture offsets */ + if (heap == R128_AGP_TEX_HEAP) + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] += + R128_AGP_TEX_OFFSET + + r128ctx->r128Screen->agpTexOffset; + /* Force loading the new state into the hardware */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX1STATE; + break; + + default: + return -1; + } + } + + /* Let the world know we've used this memory recently */ + r128UpdateTexLRU(r128ctx, t); + + /* Upload any images that are new */ + if (t->dirty_images) { + int num_levels = (((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT) - + ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> + R128_TEX_MIN_SIZE_SHIFT)); + + for (i = 0; i <= num_levels; i++) { + if (t->dirty_images & (1<<i)) { + r128UploadSubImage(r128ctx, t, i, 0, 0, + t->image[i].width, t->image[i].height); + } + } + + r128ctx->regs.tex_cntl_c |= R128_TEX_CACHE_FLUSH; + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ENGINESTATE; + } + + t->dirty_images = 0; + return 0; +} + +/* Update the hardware state for texture unit 0 */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateTex0State(r128ContextPtr r128ctx) +{ + GLcontext *ctx = r128ctx->glCtx; + r128TexObjPtr t; + struct gl_texture_object *tObj; + int i; + CARD32 tex_size_pitch, tex_combine_cntl; + + /* Only update the hardware texture state if the texture is current, + complete and enabled. */ + if (!(tObj = ctx->Texture.Unit[0].Current)) return; + if ((tObj != ctx->Texture.Unit[0].CurrentD[2]) && + (tObj != ctx->Texture.Unit[0].CurrentD[1])) return; + if (!tObj->Complete) return; + + /* If neither tex0 nor tex1 is enabled, then disable tex0. However, + if tex1 is enabled but tex0 is disabled, then we need to enable + tex0 and have it to copy the input (see how tex_combine_cntl is + setup below). */ + if (!(ctx->Texture.Enabled & (ENABLE_TEX0 | ENABLE_TEX1))) { + r128ctx->regs.tex_cntl_c &= ~R128_TEXMAP_ENABLE; + return; + } + + /* If this is the first time the texture has been used, then create + a new texture object for it. */ + t = tObj->DriverData; + if (!t) t = r128CreateTexObj(r128ctx, tObj); + if (!t) return; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) + fprintf(stderr, "r128UpdateTex0State(%p, 0x%08x)\n", + tObj, (int)t->dirty_images); + + /* Force any texture images to be loaded into the hardware */ + if (t->dirty_images) r128ctx->dirty |= R128_UPDATE_TEX0IMAGES; + + /* Bind texture to texture 0 unit */ + r128ctx->CurrentTexObj[0] = t; + t->bound = 1; + + if (t->memBlock) r128UpdateTexLRU(r128ctx, t); + + /* Set the texture environment state */ + switch (ctx->Texture.Unit[0].EnvMode) { + case GL_REPLACE: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGB: + case GL_LUMINANCE: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_BLEND: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + switch (r128ctx->regs.constant_color_c & + R128_CONSTANT_COLOR_MASK) { + case R128_CONSTANT_COLOR_ZERO: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_NTEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case R128_CONSTANT_COLOR_ONE: + default: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + r128ctx->Fallback |= R128_FALLBACK_TEXTURE; + break; + } + break; + case GL_RGB: + case GL_LUMINANCE: + switch (r128ctx->regs.constant_color_c & + R128_CONSTANT_COLOR_MASK) { + case R128_CONSTANT_COLOR_ZERO: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_NTEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case R128_CONSTANT_COLOR_ONE: + default: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + r128ctx->Fallback |= R128_FALLBACK_TEXTURE; + break; + } + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_INTENSITY: + switch (r128ctx->regs.constant_color_c & + R128_CONSTANT_COLOR_MASK) { + case R128_CONSTANT_COLOR_ZERO: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_NTEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_NTEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case R128_CONSTANT_COLOR_ONE: + default: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + r128ctx->Fallback |= R128_FALLBACK_TEXTURE; + break; + } + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_MODULATE: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGB: + case GL_LUMINANCE: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_DECAL: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + tex_combine_cntl = (R128_COMB_BLEND_TEXTURE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGB: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + /* Undefined behaviour - just copy the input */ + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_ADD: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + tex_combine_cntl = (R128_COMB_ADD | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGB: + case GL_LUMINANCE: + tex_combine_cntl = (R128_COMB_ADD | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + default: + return; + } + + /* If tex0 is disabled, then make sure it just copies the input */ + if (!(ctx->Texture.Enabled & ENABLE_TEX0)) + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + + /* Enable tex0 */ + r128ctx->regs.tex_cntl_c |= R128_TEXMAP_ENABLE; + + tex_size_pitch = r128ctx->regs.tex_size_pitch_c; + tex_size_pitch &= ~R128_TEX_SIZE_PITCH_MASK; + tex_size_pitch |= t->regs.size_pitch << R128_TEX_SIZE_PITCH_SHIFT; + + /* Set the primary texture state in r128ctx->regs */ + r128ctx->regs.prim_tex_cntl_c = t->regs.tex_cntl; + r128ctx->regs.prim_texture_combine_cntl_c = tex_combine_cntl; + r128ctx->regs.tex_size_pitch_c = tex_size_pitch; + r128ctx->regs.prim_texture_border_color_c = t->regs.border_color; + + /* Set texture offsets */ + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] = (CARD32)t->bufAddr; + } else { + int maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT); + int minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> + R128_TEX_MIN_SIZE_SHIFT); + for (i = maxLevel; i >= minLevel; i--) + r128ctx->regs.prim_tex_offset[i] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } + /* Fix AGP texture offsets */ + if (t->heap == R128_AGP_TEX_HEAP) + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] += + R128_AGP_TEX_OFFSET + r128ctx->r128Screen->agpTexOffset; + + /* Force loading the new state into the hardware */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX0STATE | R128_CTX_ENGINESTATE; +} + +/* Update the hardware state for texture unit 1 */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateTex1State(r128ContextPtr r128ctx) +{ + GLcontext *ctx = r128ctx->glCtx; + r128TexObjPtr t; + struct gl_texture_object *tObj; + int i; + CARD32 tex_size_pitch, tex_combine_cntl, tex_cntl; + + /* Only update the hardware texture state if the texture is current, + complete and enabled. */ + if (!(tObj = ctx->Texture.Unit[1].Current)) return; + if ((tObj != ctx->Texture.Unit[1].CurrentD[2]) && + (tObj != ctx->Texture.Unit[1].CurrentD[1])) return; + if (!tObj->Complete) return; + + /* If tex1 is not enabled, then disable it */ + if (!(ctx->Texture.Enabled & ENABLE_TEX1)) { + r128ctx->regs.tex_cntl_c &= ~R128_SEC_TEXMAP_ENABLE; + return; + } + + /* If this is the first time the texture has been used, then create + a new texture object for it. */ + t = tObj->DriverData; + if (!t) t = r128CreateTexObj(r128ctx, tObj); + if (!t) return; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) + fprintf(stderr, "r128UpdateTex1State(%p, 0x%08x)\n", + tObj, (int)t->dirty_images); + + /* Force any texture images to be loaded into the hardware */ + if (t->dirty_images) r128ctx->dirty |= R128_UPDATE_TEX1IMAGES; + + /* Bind texture to texture 1 unit */ + r128ctx->CurrentTexObj[1] = t; + t->bound = 2; + + if (t->memBlock) r128UpdateTexLRU(r128ctx, t); + + /* Set the texture environment state */ + switch (ctx->Texture.Unit[1].EnvMode) { + case GL_REPLACE: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGB: + case GL_LUMINANCE: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_BLEND: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + switch ( r128ctx->regs.constant_color_c & R128_CONSTANT_COLOR_MASK ) { + case R128_CONSTANT_COLOR_ZERO: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_NTEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case R128_CONSTANT_COLOR_ONE: + default: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + r128ctx->Fallback |= R128_FALLBACK_TEXTURE; + break; + } + break; + case GL_RGB: + case GL_LUMINANCE: + switch (r128ctx->regs.constant_color_c & + R128_CONSTANT_COLOR_MASK) { + case R128_CONSTANT_COLOR_ZERO: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_NTEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA ); + break; + case R128_CONSTANT_COLOR_ONE: + default: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA ); + r128ctx->Fallback |= R128_FALLBACK_TEXTURE; + break; + } + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_INTENSITY: + switch (r128ctx->regs.constant_color_c & + R128_CONSTANT_COLOR_MASK) { + case R128_CONSTANT_COLOR_ZERO: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_NTEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_NTEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case R128_CONSTANT_COLOR_ONE: + default: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + r128ctx->Fallback |= R128_FALLBACK_TEXTURE; + break; + } + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_MODULATE: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGB: + case GL_LUMINANCE: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_DECAL: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + tex_combine_cntl = (R128_COMB_BLEND_TEXTURE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGB: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + /* Undefined behaviour - just copy the input */ + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_ADD: + switch (tObj->Image[0]->Format) { + case GL_RGBA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + tex_combine_cntl = (R128_COMB_ADD | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGB: + case GL_LUMINANCE: + tex_combine_cntl = (R128_COMB_ADD | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_ALPHA: + tex_combine_cntl = (R128_COMB_COPY_INP | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + default: + return; + } + + /* Enable tex1 */ + r128ctx->regs.tex_cntl_c |= R128_SEC_TEXMAP_ENABLE; + + tex_size_pitch = r128ctx->regs.tex_size_pitch_c; + tex_size_pitch &= ~R128_SEC_TEX_SIZE_PITCH_MASK; + tex_size_pitch |= t->regs.size_pitch << R128_SEC_TEX_SIZE_PITCH_SHIFT; + + tex_cntl = t->regs.tex_cntl | R128_SEC_SELECT_SEC_ST; + + /* Set the secondary texture state in r128ctx->regs */ + r128ctx->regs.sec_tex_cntl_c = tex_cntl; + r128ctx->regs.sec_tex_combine_cntl_c = tex_combine_cntl; + r128ctx->regs.tex_size_pitch_c = tex_size_pitch; + r128ctx->regs.sec_texture_border_color_c = t->regs.border_color; + + /* Set texture offsets */ + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] = (CARD32)t->bufAddr; + } else { + int maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT); + int minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> + R128_TEX_MIN_SIZE_SHIFT); + for (i = maxLevel; i >= minLevel; i--) + r128ctx->regs.sec_tex_offset[i] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } + /* Fix AGP texture offsets */ + if (t->heap == R128_AGP_TEX_HEAP) + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] += + R128_AGP_TEX_OFFSET + r128ctx->r128Screen->agpTexOffset; + + /* Force loading the new state into the hardware */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX1STATE | R128_CTX_ENGINESTATE; +} + +/* Update the hardware texture state */ +/* NOTE: This function is only called while holding the hardware lock */ +void r128UpdateTextureState(r128ContextPtr r128ctx) +{ + /* Clear the GL_BLEND texturing fallback */ + r128ctx->Fallback &= ~R128_FALLBACK_TEXTURE; + + /* Unbind any currently bound textures */ + if (r128ctx->CurrentTexObj[0]) r128ctx->CurrentTexObj[0]->bound = 0; + if (r128ctx->CurrentTexObj[1]) r128ctx->CurrentTexObj[1]->bound = 0; + r128ctx->CurrentTexObj[0] = NULL; + r128ctx->CurrentTexObj[1] = NULL; + + /* Update the texture unit 0/1 state */ + r128UpdateTex0State(r128ctx); + r128UpdateTex1State(r128ctx); +} + +/* Set the texture wrap mode */ +static void r128SetTexWrap(r128TexObjPtr t, GLenum swrap, GLenum twrap) +{ + t->regs.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK); + + switch (swrap) { + case GL_CLAMP: t->regs.tex_cntl |= R128_TEX_CLAMP_S_CLAMP; break; + case GL_REPEAT: t->regs.tex_cntl |= R128_TEX_CLAMP_S_WRAP; break; + default: /* ERROR!! */ return; + } + + switch (twrap) { + case GL_CLAMP: t->regs.tex_cntl |= R128_TEX_CLAMP_T_CLAMP; break; + case GL_REPEAT: t->regs.tex_cntl |= R128_TEX_CLAMP_T_WRAP; break; + default: /* ERROR!! */ return; + } +} + +/* Set the texture filter mode */ +static void r128SetTexFilter(r128TexObjPtr t, GLenum minf, GLenum magf) +{ + t->regs.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK); + + switch (minf) { + case GL_NEAREST: + t->regs.tex_cntl |= R128_MIN_BLEND_NEAREST; + break; + case GL_LINEAR: + t->regs.tex_cntl |= R128_MIN_BLEND_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + t->regs.tex_cntl |= R128_MIN_BLEND_MIPNEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + t->regs.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + t->regs.tex_cntl |= R128_MIN_BLEND_MIPLINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + t->regs.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR; + break; + default: /* ERROR!! */ return; + } + + switch (magf) { + case GL_NEAREST: + t->regs.tex_cntl |= R128_MAG_BLEND_NEAREST; + break; + case GL_LINEAR: + t->regs.tex_cntl |= R128_MAG_BLEND_LINEAR; + break; + } +} + +/* Set the texture border color */ +static void r128SetTexBorderColor(r128TexObjPtr t, GLubyte c[4]) +{ + t->regs.border_color = r128PackColor(32, c[0], c[1], c[2], c[3]); +} + +/* Set the texture environment state */ +static void r128DDTexEnv(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + struct gl_texture_unit *texUnit; + GLubyte c[4]; + CARD32 col; + + /* FIXME: Add texture LOD bias extension */ + + switch (pname) { + case GL_TEXTURE_ENV_MODE: + /* TexEnv modes are handled in UpdateTextureState */ + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + break; + case GL_TEXTURE_ENV_COLOR: + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + FLOAT_RGBA_TO_UBYTE_RGBA(texUnit->EnvColor, c); + col = r128PackColor(32, c[0], c[1], c[2], c[3]); + if (r128ctx->regs.constant_color_c != col) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + r128ctx->regs.constant_color_c = col; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEXENVSTATE; + } + break; + default: + return; + } +} + +/* Upload a new texture image */ +static void r128DDTexImage(GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, GLint level, + GLint internalFormat, + const struct gl_texture_image *image) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) + fprintf(stderr, "r128DDTexImage(%p, level %d)\n", tObj, level); + + if ((target != GL_TEXTURE_2D) && (target != GL_TEXTURE_1D)) return; + if (level >= R128_TEX_MAXLEVELS) return; + + t = (r128TexObjPtr)tObj->DriverData; + if (t) { + if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + + /* Destroy the old texture, and upload a new one. The actual + uploading of the texture image occurs in the UploadSubImage + function. */ + r128DestroyTexObj(r128ctx, t); + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + } +} + +/* Upload a new texture sub-image */ +static void r128DDTexSubImage(GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLint internalFormat, + const struct gl_texture_image *image) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t; + + if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) + fprintf(stderr, "r128DDTexSubImage(%p, level %d) " + "size: %d,%d of %d,%d\n", + tObj, level, width, height, image->Width, image->Height); + + if ((target != GL_TEXTURE_2D) && (target != GL_TEXTURE_1D)) return; + if (level >= R128_TEX_MAXLEVELS) return; + + t = (r128TexObjPtr)tObj->DriverData; + if (t) { + if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + + LOCK_HARDWARE(r128ctx); + r128UploadSubImage(r128ctx, t, level, + xoffset, yoffset, width, height); + UNLOCK_HARDWARE(r128ctx); + + /* Update the context state */ + r128ctx->regs.tex_cntl_c |= R128_TEX_CACHE_FLUSH; + + r128ctx->dirty |= (R128_UPDATE_CONTEXT | + R128_UPDATE_TEXSTATE); + r128ctx->dirty_context |= (R128_CTX_ENGINESTATE | + R128_CTX_TEX0STATE | + R128_CTX_TEX1STATE); + } +} + +/* Set the texture parameter state */ +static void r128DDTexParameter(GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, + GLenum pname, const GLfloat *params) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData; + + if (!t) return; + if ((target != GL_TEXTURE_2D) && (target != GL_TEXTURE_1D)) return; + + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + r128SetTexFilter(t, tObj->MinFilter, tObj->MagFilter); + break; + + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + r128SetTexWrap(t, tObj->WrapS, tObj->WrapT); + break; + + case GL_TEXTURE_BORDER_COLOR: + if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + r128SetTexBorderColor(t, tObj->BorderColor); + break; + + default: + return; + } + + r128ctx->dirty |= R128_UPDATE_TEXSTATE; +} + +/* Bind a texture to the currently active texture unit */ +static void r128DDBindTexture(GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + R128CCE_FLUSH_VB_LOCK(r128ctx); + + /* Unbind the old texture */ + if (r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit]) { + r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit]->bound = 0; + r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit] = NULL; + } + + /* The actualy binding occurs in the Tex[01]UpdateState function */ + r128ctx->dirty |= R128_UPDATE_TEXSTATE; +} + +/* Remove texture from AGP/local texture memory */ +static void r128DDDeleteTexture(GLcontext *ctx, + struct gl_texture_object *tObj) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData; + + if (t) { + if (t->bound) { + R128CCE_FLUSH_VB_LOCK(r128ctx); + + r128ctx->CurrentTexObj[t->bound-1] = 0; + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + } + + r128DestroyTexObj(r128ctx, t); + tObj->DriverData = NULL; + } +} + +/* Determine if a texture is currently residing in either AGP/local + texture memory */ +static GLboolean r128DDIsTextureResident(GLcontext *ctx, + struct gl_texture_object *tObj) +{ + r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData; + + return t && t->memBlock; +} + +/* Initialize the driver's texture functions */ +void r128DDInitTextureFuncs(GLcontext *ctx) +{ + ctx->Driver.TexEnv = r128DDTexEnv; + ctx->Driver.TexImage = r128DDTexImage; + ctx->Driver.TexSubImage = r128DDTexSubImage; + ctx->Driver.TexParameter = r128DDTexParameter; + ctx->Driver.BindTexture = r128DDBindTexture; + ctx->Driver.DeleteTexture = r128DDDeleteTexture; + ctx->Driver.UpdateTexturePalette = NULL; + ctx->Driver.ActiveTexture = NULL; + ctx->Driver.IsTextureResident = r128DDIsTextureResident; + ctx->Driver.PrioritizeTexture = NULL; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tex.h b/xc/lib/GL/mesa/src/drv/r128/r128_tex.h new file mode 100644 index 000000000..20893110c --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tex.h @@ -0,0 +1,82 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Gareth Hughes <gareth@precisioninsight.com> + * + */ + +#ifndef _R128_TEX_H_ +#define _R128_TEX_H_ + +#ifdef GLX_DIRECT_RENDERING + +extern void r128AgeTextures(r128ContextPtr r128ctx, int heap); +extern int r128UploadTexImages(r128ContextPtr r128ctx, r128TexObjPtr t); +extern void r128UpdateTextureState(r128ContextPtr r128ctx); +extern void r128DestroyTexObj(r128ContextPtr r128ctx, r128TexObjPtr t); + +extern void r128DDInitTextureFuncs(GLcontext *ctx); + +#define R128PACKCOLOR332(r, g, b) \ + (((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6)) + +#define R128PACKCOLOR1555(r, g, b, a) \ + ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ + ((a) ? 0x8000 : 0)) + +#define R128PACKCOLOR565(r, g, b) \ + ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) + +#define R128PACKCOLOR888(r, g, b) \ + (((r) << 16) | ((g) << 8) | (b)) + +#define R128PACKCOLOR8888(r, g, b, a) \ + (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +#define R128PACKCOLOR4444(r, g, b, a) \ + ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) + +static __inline__ CARD32 r128PackColor(GLuint depth, + GLubyte r, GLubyte g, + GLubyte b, GLubyte a) +{ + switch (depth) { + case 8: return R128PACKCOLOR332(r, g, b); + case 15: return R128PACKCOLOR1555(r, g, b, a); + case 16: return R128PACKCOLOR565(r, g, b); + case 24: return R128PACKCOLOR888(r, g, b); + case 32: return R128PACKCOLOR8888(r, g, b, a); + default: return 0; + } +} + +#endif +#endif /* _R128_TEX_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_texobj.h b/xc/lib/GL/mesa/src/drv/r128/r128_texobj.h new file mode 100644 index 000000000..588b768ed --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_texobj.h @@ -0,0 +1,87 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Gareth Hughes <gareth@precisioninsight.com> + * + */ + +#ifndef _R128_TEXOBJ_H_ +#define _R128_TEXOBJ_H_ + +#include "mm.h" + +#define R128_TEX_MAXLEVELS 11 + +/* Setup registers for each texture */ +typedef struct { + CARD32 tex_cntl; + CARD32 size_pitch; + CARD32 border_color; +} r128TextureRegs; + +/* Individual texture image information */ +typedef struct { + int offset; /* Offset into locally shared texture space (i.e., + relative to bufAddr (below) */ + int width; /* Width of texture image */ + int height; /* Height of texture image */ +} r128TexImage; + +typedef struct r128_tex_obj r128TexObj, *r128TexObjPtr; + +/* Texture object in locally shared texture space */ +struct r128_tex_obj { + r128TexObjPtr next, prev; + + struct gl_texture_object *tObj; /* Mesa texture object */ + + PMemBlock memBlock; /* Memory block containing texture */ + unsigned char *bufAddr; /* Offset to start of locally + shared texture block */ + + CARD32 dirty_images; /* Flags for whether or not + images need to be uploaded to + local or AGP texture space */ + int bound; /* Texture unit currently bound to */ + int heap; /* Texture heap currently stored in */ + r128TexImage image[R128_TEX_MAXLEVELS]; /* Image data for all + mipmap levels */ + int totalSize; /* Total size of the texture + including all mipmap levels */ + int internFormat; /* Internal GL format used to store + texture on card */ + int textureFormat; /* Actual hardware format */ + int texelBytes; /* Number of bytes per texel */ + + r128TextureRegs regs; /* Setup regs for texture */ +}; + +#endif /* _R128_TEXOBJ_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tris.c b/xc/lib/GL/mesa/src/drv/r128/r128_tris.c new file mode 100644 index 000000000..1c1b45daf --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tris.c @@ -0,0 +1,548 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_vb.h" +#include "r128_tris.h" +#include "r128_state.h" + +static triangle_func tri_tab[0x40]; /* only 0x20 actually used */ +static quad_func quad_tab[0x40]; /* only 0x20 actually used */ +static line_func line_tab[0x40]; /* less than 0x20 used */ +static points_func points_tab[0x40]; /* less than 0x20 used */ + +/* Draw a triangle from the vertices in the vertex buffer */ +void r128DrawTriangleVB(r128ContextPtr r128ctx, + r128_vertex *v0, + r128_vertex *v1, + r128_vertex *v2) +{ + r128_vertex *vbptr; + + if (r128ctx->disableVB) { + r128DrawTriangle(r128ctx, v0, v1, v2); + return; + } + + R128CCE_ALLOC_VB_SPACE(r128ctx, vbptr, 3); + + *vbptr++ = *v0; + *vbptr++ = *v1; + *vbptr++ = *v2; +} + +/* Draw a triangle */ +void r128DrawTriangle(r128ContextPtr r128ctx, + r128_vertex *v0, + r128_vertex *v1, + r128_vertex *v2) +{ + LOCK_HARDWARE(r128ctx); + BEGIN_CLIP_LOOP(r128ctx); + +#if USE_RHW2 + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 34); +#else + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 31); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCE_SEND_VERTEX(v0); + R128CCE_SEND_VERTEX(v1); + R128CCE_SEND_VERTEX(v2); + + R128CCE_SUBMIT_PACKETS(); + + END_CLIP_LOOP(r128ctx); + UNLOCK_HARDWARE(r128ctx); +} + +/* Draw a line from the vertices in the vertex buffer */ +void r128DrawLineVB(r128ContextPtr r128ctx, + r128_vertex *v0, r128_vertex *v1, + float width) +{ + float dx, dy, ix, iy; + r128_vertex *vbptr; + + /* FIXME: Use r128's line primitive for width 1 lines */ + if (r128ctx->disableVB) { + r128DrawLine(r128ctx, v0, v1, width); + return; + } + + R128CCE_ALLOC_VB_SPACE(r128ctx, vbptr, 3); + + dx = v0->x - v1->x; + dy = v0->y - v1->y; + + ix = width * 0.5; iy = 0; + if (dx*dx > dy*dy) { + iy = ix; ix = 0; + } + + *vbptr = *v0; vbptr->x = v0->x - ix; vbptr->y = v0->y - iy; + *++vbptr = *v1; vbptr->x = v1->x + ix; vbptr->y = v1->y + iy; + *++vbptr = *v0; vbptr->x = v0->x + ix; vbptr->y = v0->y + iy; + *++vbptr = *v0; vbptr->x = v0->x - ix; vbptr->y = v0->y - iy; + *++vbptr = *v1; vbptr->x = v1->x - ix; vbptr->y = v1->y - iy; + *++vbptr = *v1; vbptr->x = v1->x + ix; vbptr->y = v1->y + iy; +} + +/* Draw a line */ +void r128DrawLine(r128ContextPtr r128ctx, + r128_vertex *v0, r128_vertex *v1, + float width) +{ + LOCK_HARDWARE(r128ctx); + if (width != 1) { + float dx, dy, ix, iy; + + dx = v0->x - v1->x; + dy = v0->y - v1->y; + + ix = width * 0.5; iy = 0; + if (dx*dx > dy*dy) { + iy = ix; ix = 0; + } + + BEGIN_CLIP_LOOP(r128ctx); + +#if USE_RHW2 + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 67); +#else + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 61); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (6 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCEF(v0->x - ix); + R128CCEF(v0->y - iy); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v1->x + ix); + R128CCEF(v1->y + iy); + R128CCEF(v1->z); + R128CCEF(v1->rhw); + R128CCE(*(int *)&v1->dif_argb); + R128CCE(*(int *)&v1->spec_frgb); + R128CCEF(v1->tu0); + R128CCEF(v1->tv0); + R128CCEF(v1->tu1); + R128CCEF(v1->tv1); +#if USE_RHW2 + R128CCEF(v1->rhw2); +#endif + + R128CCEF(v0->x + ix); + R128CCEF(v0->y + iy); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v0->x - ix); + R128CCEF(v0->y - iy); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v1->x - ix); + R128CCEF(v1->y - iy); + R128CCEF(v1->z); + R128CCEF(v1->rhw); + R128CCE(*(int *)&v1->dif_argb); + R128CCE(*(int *)&v1->spec_frgb); + R128CCEF(v1->tu0); + R128CCEF(v1->tv0); + R128CCEF(v1->tu1); + R128CCEF(v1->tv1); +#if USE_RHW2 + R128CCEF(v1->rhw2); +#endif + + R128CCEF(v1->x + ix); + R128CCEF(v1->y + iy); + R128CCEF(v1->z); + R128CCEF(v1->rhw); + R128CCE(*(int *)&v1->dif_argb); + R128CCE(*(int *)&v1->spec_frgb); + R128CCEF(v1->tu0); + R128CCEF(v1->tv0); + R128CCEF(v1->tu1); + R128CCEF(v1->tv1); +#if USE_RHW2 + R128CCEF(v1->rhw2); +#endif + + R128CCE_SUBMIT_PACKETS(); + + END_CLIP_LOOP(r128ctx); + } else { + BEGIN_CLIP_LOOP(r128ctx); + +#if USE_RHW2 + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 23); +#else + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 21); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_LINE | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (2 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCE_SEND_VERTEX(v0); + R128CCE_SEND_VERTEX(v1); + + R128CCE_SUBMIT_PACKETS(); + + END_CLIP_LOOP(r128ctx); + } + UNLOCK_HARDWARE(r128ctx); +} + +/* Draw a point from the vertices in the vertex buffer */ +void r128DrawPointVB(r128ContextPtr r128ctx, + r128_vertex *v0, float size) +{ + r128_vertex *vbptr; + + /* FIXME: Use r128's point primitive for diameter 1 points */ + if (r128ctx->disableVB) { + r128DrawPoint(r128ctx, v0, size); + return; + } + + R128CCE_ALLOC_VB_SPACE(r128ctx, vbptr, 3); + + *vbptr = *v0; vbptr->x = v0->x - size; vbptr->y = v0->y - size; + *++vbptr = *v0; vbptr->x = v0->x + size; vbptr->y = v0->y - size; + *++vbptr = *v0; vbptr->x = v0->x + size; vbptr->y = v0->y + size; + *++vbptr = *v0; vbptr->x = v0->x + size; vbptr->y = v0->y + size; + *++vbptr = *v0; vbptr->x = v0->x - size; vbptr->y = v0->y + size; + *++vbptr = *v0; vbptr->x = v0->x - size; vbptr->y = v0->y - size; +} + +/* Draw a point */ +void r128DrawPoint(r128ContextPtr r128ctx, + r128_vertex *v0, float size) +{ + LOCK_HARDWARE(r128ctx); + if (size != 0.5) { + BEGIN_CLIP_LOOP(r128ctx); + +#if USE_RHW2 + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 67); +#else + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 61); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (6 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCEF(v0->x - size); + R128CCEF(v0->y - size); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v0->x + size); + R128CCEF(v0->y - size); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v0->x + size); + R128CCEF(v0->y + size); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v0->x + size); + R128CCEF(v0->y + size); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v0->x - size); + R128CCEF(v0->y + size); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v0->x - size); + R128CCEF(v0->y - size); + R128CCEF(v0->z); + R128CCEF(v0->rhw); + R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->spec_frgb); + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCE_SUBMIT_PACKETS(); + + END_CLIP_LOOP(r128ctx); + } else { + BEGIN_CLIP_LOOP(r128ctx); + +#if USE_RHW2 + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 12); +#else + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 11); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_POINT | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (1 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCE_SEND_VERTEX(v0); + + R128CCE_SUBMIT_PACKETS(); + + END_CLIP_LOOP(r128ctx); + } + UNLOCK_HARDWARE(r128ctx); +} + +#define R128_COLOR(to, from) \ +do { \ + (to)[0] = (from)[2]; \ + (to)[1] = (from)[1]; \ + (to)[2] = (from)[0]; \ + (to)[3] = (from)[3]; \ +} while (0) + +#define IND (0) +#define TAG(x) x +#include "r128_tritmp.h" + +#define IND (R128_FLAT_BIT) +#define TAG(x) x##_flat +#include "r128_tritmp.h" + +#define IND (R128_OFFSET_BIT) +#define TAG(x) x##_offset +#include "r128_tritmp.h" + +#define IND (R128_OFFSET_BIT | R128_FLAT_BIT) +#define TAG(x) x##_offset_flat +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT) +#define TAG(x) x##_twoside +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT | R128_FLAT_BIT) +#define TAG(x) x##_twoside_flat +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT | R128_OFFSET_BIT) +#define TAG(x) x##_twoside_offset +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT | R128_OFFSET_BIT | R128_FLAT_BIT) +#define TAG(x) x##_twoside_offset_flat +#include "r128_tritmp.h" + +/* Initialize the table of points, line and triangle drawing functions */ +void r128TriangleFuncsInit(void) +{ + init(); + init_flat(); + init_offset(); + init_offset_flat(); + init_twoside(); + init_twoside_flat(); + init_twoside_offset(); + init_twoside_offset_flat(); +} + +/* Setup the Point, Line, Triangle and Quad functions based on the + current rendering state. Wherever possible, use the hardware to + render the primitive. Otherwise, fallback to software rendering. */ +void r128ChooseRenderState(GLcontext *ctx) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + GLuint flags = ctx->TriangleCaps; + + if (r128ctx->Fallback) return; + + if (r128ctx->SWonly) { + r128ctx->IndirectTriangles = DD_SW_RASTERIZE; + r128ctx->PointsFunc = NULL; + r128ctx->LineFunc = NULL; + r128ctx->TriangleFunc = NULL; + r128ctx->QuadFunc = NULL; + return; + } else { + r128ctx->IndirectTriangles = 0; + } + + if (flags) { + CARD32 index = 0; + CARD32 shared = 0; + CARD32 fallback = R128_FALLBACK_BIT; + + if (r128ctx->SWfallbackDisable) fallback = 0; /* No fallbacks */ + if (r128ctx->SWonly) shared = fallback; /* Everything's a fallback */ + + if (flags & DD_FLATSHADE) shared |= R128_FLAT_BIT; + if (flags & DD_MULTIDRAW) shared |= fallback; + if (flags & DD_SELECT) shared |= R128_FALLBACK_BIT; + if (flags & DD_FEEDBACK) shared |= R128_FALLBACK_BIT; + + /* Setup PointFunc */ + index = shared; + if (flags & DD_POINT_SMOOTH) index |= fallback; + if (flags & DD_POINT_ATTEN) index |= fallback; + + r128ctx->RenderIndex = index; + r128ctx->PointsFunc = points_tab[index]; + if (index & R128_FALLBACK_BIT) + r128ctx->IndirectTriangles |= DD_POINT_SW_RASTERIZE; + + /* Setup LineFunc */ + index = shared; + if (flags & DD_LINE_SMOOTH) index |= fallback; + if (flags & DD_LINE_STIPPLE) index |= fallback; + + r128ctx->RenderIndex |= index; + r128ctx->LineFunc = line_tab[index]; + if (index & R128_FALLBACK_BIT) + r128ctx->IndirectTriangles |= DD_LINE_SW_RASTERIZE; + + /* Setup TriangleFunc and QuadFunc */ + index = shared; + if (flags & DD_TRI_SMOOTH) index |= fallback; + if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT; + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT; + if (flags & DD_TRI_UNFILLED) index |= fallback; + if (flags & DD_TRI_STIPPLE) index |= fallback; + + r128ctx->RenderIndex |= index; + r128ctx->TriangleFunc = tri_tab[index]; + r128ctx->QuadFunc = quad_tab[index]; + if (index & R128_FALLBACK_BIT) + r128ctx->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | + DD_QUAD_SW_RASTERIZE); + } else if (r128ctx->RenderIndex) { + r128ctx->RenderIndex = 0; + r128ctx->PointsFunc = points_tab[0]; + r128ctx->LineFunc = line_tab[0]; + r128ctx->TriangleFunc = tri_tab[0]; + r128ctx->QuadFunc = quad_tab[0]; + } +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tris.h b/xc/lib/GL/mesa/src/drv/r128/r128_tris.h new file mode 100644 index 000000000..0980f2791 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tris.h @@ -0,0 +1,76 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_TRIS_H_ +#define _R128_TRIS_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include "r128_vb.h" + +#define R128_ANTIALIAS_BIT 0x00 /* ignored for now, no fallback */ +#define R128_FLAT_BIT 0x01 +#define R128_OFFSET_BIT 0x02 +#define R128_TWOSIDE_BIT 0x04 +#define R128_NODRAW_BIT 0x08 +#define R128_FALLBACK_BIT 0x10 +#define R128_FEEDBACK_BIT 0x20 +#define R128_SELECT_BIT 0x40 +#define R128_POINT_PARAM_BIT 0x80 /* not needed? */ + +extern void r128DrawTriangleVB(r128ContextPtr r128ctx, + r128_vertex *v0, + r128_vertex *v1, + r128_vertex *v2); +extern void r128DrawLineVB(r128ContextPtr r128ctx, + r128_vertex *tmp0, r128_vertex *tmp1, + float width); +extern void r128DrawPointVB(r128ContextPtr r128ctx, + r128_vertex *tmp, float size); + +extern void r128DrawTriangle(r128ContextPtr r128ctx, + r128_vertex *v0, + r128_vertex *v1, + r128_vertex *v2); +extern void r128DrawLine(r128ContextPtr r128ctx, + r128_vertex *tmp0, r128_vertex *tmp1, + float width); +extern void r128DrawPoint(r128ContextPtr r128ctx, + r128_vertex *tmp, float size); + +extern void r128ChooseRenderState(GLcontext *ctx); +extern void r128TriangleFuncsInit(void); + +#endif +#endif /* _R128_TRIS_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h b/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h new file mode 100644 index 000000000..833bd832a --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h @@ -0,0 +1,327 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#if !defined(TAG) || !defined(IND) + this is an error +#endif + +/* Draw a single triangle. Note that the device-dependent vertex data + might need to be changed based on the render state. */ +static void TAG(triangle)(GLcontext *ctx, + GLuint e0, GLuint e1, GLuint e2, + GLuint pv) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + struct vertex_buffer *VB = ctx->VB; + r128VertexPtr r128verts = R128_DRIVER_DATA(VB)->verts; + const r128_vertex *v0 = &r128verts[e0].v; + const r128_vertex *v1 = &r128verts[e1].v; + const r128_vertex *v2 = &r128verts[e2].v; + +#if (IND & R128_OFFSET_BIT) + GLfloat offset; +#endif + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + int c0 = *(int *)&r128verts[pv].v.dif_argb; + int c1 = c0; + int c2 = c0; +#endif + +#if (IND & R128_OFFSET_BIT) + switch (ctx->Visual->DepthBits) { + case 16: offset = ctx->Polygon.OffsetUnits / 65536.0; break; + case 24: offset = ctx->Polygon.OffsetUnits / 16777216.0; break; + case 32: offset = ctx->Polygon.OffsetUnits / 4294967296.0; break; + default: offset = ctx->Polygon.OffsetUnits / 65536.0; break; + } +#endif + +#if (IND & (R128_TWOSIDE_BIT | R128_OFFSET_BIT)) + { + GLfloat ex = v0->x - v2->x; + GLfloat ey = v0->y - v2->y; + GLfloat fx = v1->x - v2->x; + GLfloat fy = v1->y - v2->y; + GLfloat c = ex*fy - ey*fx; + +#if (IND & R128_TWOSIDE_BIT) + { + GLuint facing = (c > 0.0) ^ ctx->Polygon.FrontBit; + GLubyte (*vbcolor)[4] = VB->Color[facing]->data; + if (IND & R128_FLAT_BIT) { + R128_COLOR((char *)&c0, vbcolor[pv]); + c2 = c1 = c0; + } else { + R128_COLOR((char *)&c0, vbcolor[e0]); + R128_COLOR((char *)&c1, vbcolor[e1]); + R128_COLOR((char *)&c2, vbcolor[e2]); + } + } +#endif + +#if (IND & R128_OFFSET_BIT) + { + if (c * c > 1e-16) { + GLfloat factor = ctx->Polygon.OffsetFactor; + GLfloat ez = v0->z - v2->z; + GLfloat fz = v1->z - v2->z; + GLfloat a = ey*fz - ez*fy; + GLfloat b = ez*fx - ex*fz; + GLfloat ic = 1.0 / c; + GLfloat ac = a * ic; + GLfloat bc = b * ic; + if (ac < 0.0f) ac = -ac; + if (bc < 0.0f) bc = -bc; + offset += MAX2(ac, bc) * factor; + } + } +#endif + } +#endif + + LOCK_HARDWARE(r128ctx); + if (r128ctx->regs.tex_cntl_c & (R128_TEXMAP_ENABLE | + R128_SEC_TEXMAP_ENABLE)) { + BEGIN_CLIP_LOOP(r128ctx); + +#if USE_RHW2 + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 34); +#else + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 31); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCEF(v0->x); + R128CCEF(v0->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v0->z + offset); +#else + R128CCEF(v0->z); +#endif + R128CCEF(v0->rhw); + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c0); +#else + R128CCE(*(int *)&v0->dif_argb); +#endif + R128CCE(*(int *)&v0->spec_frgb); + + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); +#endif + + R128CCEF(v1->x); + R128CCEF(v1->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v1->z + offset); +#else + R128CCEF(v1->z); +#endif + R128CCEF(v1->rhw); + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c1); +#else + R128CCE(*(int *)&v1->dif_argb); +#endif + R128CCE(*(int *)&v1->spec_frgb); + + R128CCEF(v1->tu0); + R128CCEF(v1->tv0); + R128CCEF(v1->tu1); + R128CCEF(v1->tv1); +#if USE_RHW2 + R128CCEF(v1->rhw2); +#endif + + R128CCEF(v2->x); + R128CCEF(v2->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v2->z + offset); +#else + R128CCEF(v2->z); +#endif + R128CCEF(v2->rhw); + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c2); +#else + R128CCE(*(int *)&v2->dif_argb); +#endif + R128CCE(*(int *)&v2->spec_frgb); + + R128CCEF(v2->tu0); + R128CCEF(v2->tv0); + R128CCEF(v2->tu1); + R128CCEF(v2->tv1); +#if USE_RHW2 + R128CCEF(v2->rhw2); +#endif + + R128CCE_SUBMIT_PACKETS(); + + END_CLIP_LOOP(r128ctx); + } else { + BEGIN_CLIP_LOOP(r128ctx); + + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 13); + R128CCE(R128_CCE_VC_FRMT_DIFFUSE_ARGB); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCEF(v0->x); + R128CCEF(v0->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v0->z + offset); +#else + R128CCEF(v0->z); +#endif + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c0); +#else + R128CCE(*(int *)&v0->dif_argb); +#endif + + R128CCEF(v1->x); + R128CCEF(v1->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v1->z + offset); +#else + R128CCEF(v1->z); +#endif + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c1); +#else + R128CCE(*(int *)&v1->dif_argb); +#endif + + R128CCEF(v2->x); + R128CCEF(v2->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v2->z + offset); +#else + R128CCEF(v2->z); +#endif + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c2); +#else + R128CCE(*(int *)&v2->dif_argb); +#endif + + R128CCE_SUBMIT_PACKETS(); + + END_CLIP_LOOP(r128ctx); + } + UNLOCK_HARDWARE(r128ctx); +} + +static void TAG(quad)(GLcontext *ctx, + GLuint v0, GLuint v1, GLuint v2, GLuint v3, + GLuint pv) +{ + TAG(triangle)(ctx, v0, v1, v3, pv); + TAG(triangle)(ctx, v1, v2, v3, pv); +} + +#if ((IND & ~R128_FLAT_BIT) == 0) + +/* Draw a single line. Note that the device-dependent vertex data might + need to be changed based on the render state. */ +static void TAG(line)(GLcontext *ctx, + GLuint v0, GLuint v1, + GLuint pv) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128VertexPtr r128verts = R128_DRIVER_DATA(ctx->VB)->verts; + r128_vertex tmp0 = r128verts[v0].v; + r128_vertex tmp1 = r128verts[v1].v; + float width = ctx->Line.Width; + + if (IND & R128_FLAT_BIT) { + *(int *)&tmp1.dif_argb = + *(int *)&tmp0.dif_argb = + *(int *)&r128verts[pv].v.dif_argb; + } + + r128DrawLine(r128ctx, &tmp0, &tmp1, width); +} + +/* Draw a set of points. Note that the device-dependent vertex data + might need to be changed based on the render state. */ +static void TAG(points)(GLcontext *ctx, + GLuint first, GLuint last) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + struct vertex_buffer *VB = ctx->VB; + r128VertexPtr r128verts = R128_DRIVER_DATA(VB)->verts; + GLfloat size = ctx->Point.Size * 0.5; + int i; + + for(i = first; i <= last; i++) { + if(VB->ClipMask[i] == 0) { + r128_vertex *tmp = &r128verts[i].v; + r128DrawPoint(r128ctx, tmp, size); + } + } +} + +#endif + +/* Initialize the table of primitives to render. */ +static void TAG(init)(void) +{ + tri_tab[IND] = TAG(triangle); + quad_tab[IND] = TAG(quad); + +#if ((IND & ~R128_FLAT_BIT) == 0) + line_tab[IND] = TAG(line); + points_tab[IND] = TAG(points); +#endif +} + +#undef IND +#undef TAG diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_vb.c b/xc/lib/GL/mesa/src/drv/r128/r128_vb.c new file mode 100644 index 000000000..f14ec21bd --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_vb.c @@ -0,0 +1,470 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_state.h" +#include "r128_vb.h" + +#include "stages.h" + +#define TEX0 \ +do { \ + v->v.tu0 = tc0[i][0]; \ + v->v.tv0 = tc0[i][1]; \ +} while (0) + +#define TEX1 \ +do { \ + v->v.tu1 = tc1[i][0]; \ + v->v.tv1 = tc1[i][1]; \ +} while (0) + +#define SPC \ +do { \ + GLubyte *spec = &(VB->Spec[0][i][0]); \ + v->v.spec_frgb.r = spec[0]; \ + v->v.spec_frgb.g = spec[1]; \ + v->v.spec_frgb.b = spec[2]; \ +} while (0) + +#define FOG \ +do { \ + GLubyte *spec = &(VB->Spec[0][i][0]); \ + v->v.spec_frgb.a = spec[3]; \ +} while (0) + +#define COL \ +do { \ + GLubyte *col = &(VB->Color[0]->data[i][0]); \ + v->v.dif_argb.a = col[3]; \ + v->v.dif_argb.r = col[0]; \ + v->v.dif_argb.g = col[1]; \ + v->v.dif_argb.b = col[2]; \ +} while (0) + +#if 1 +/* FIXME: These are handled by the Rage 128 */ +#define TEX0_4 +#define TEX1_4 +#else +#define TEX0_4 \ +do { \ + if (VB->TexCoordPtr[0]->size == 4) { \ + GLfloat (*tc)[4] = VB->TexCoordPtr[0]->data; \ + v = &(R128_DRIVER_DATA(VB)->verts[start]); \ + for (i = start; i < end; i++, v++) { \ + float oow = 1.0 / tc[i][3]; \ + v->v.rhw *= tc[i][3]; \ + v->v.tu0 *= oow; \ + v->v.tv0 *= oow; \ + } \ + } \ +} while (0) + +#if USE_RHW2 +#define TEX1_4 \ +do { \ + if (VB->TexCoordPtr[1]->size == 4) { \ + GLfloat (*tc)[4] = VB->TexCoordPtr[1]->data; \ + v = &(R128_DRIVER_DATA(VB)->verts[start]); \ + for (i = start; i < end; i++, v++) { \ + float oow = 1.0 / tc[i][3]; \ + v->v.rhw2 *= tc[i][3]; \ + v->v.tu1 *= oow; \ + v->v.tv1 *= oow; \ + } \ + } \ +} while (0) +#else +#define TEX1_4 +#endif +#endif + +#if USE_RHW2 +#define COORD \ +do { \ + GLfloat *win = VB->Win.data[i]; \ + v->v.x = win[0]; \ + v->v.y = r128height - win[1]; \ + v->v.z = scale * win[2]; \ + v->v.rhw = v->v.rhw2 = win[3]; \ +} while (0) +#else +#define COORD \ +do { \ + GLfloat *win = VB->Win.data[i]; \ + v->v.x = win[0]; \ + v->v.y = r128height - win[1]; \ + v->v.z = scale * win[2]; \ + v->v.rhw = win[3]; \ +} while (0) +#endif + +#define NOP + +/* Setup the r128 vertex buffer entries */ +#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,tex1_4,spec,fog) \ +static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ +{ \ + r128ContextPtr r128ctx = R128_CONTEXT(VB->ctx); \ + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; \ + r128VertexPtr v; \ + GLfloat (*tc0)[4]; \ + GLfloat (*tc1)[4]; \ + GLfloat r128height = dPriv->h; \ + GLfloat scale; \ + int i; \ + \ + (void) r128height; (void) r128ctx; \ + \ + gl_import_client_data(VB, VB->ctx->RenderFlags, \ + (VB->ClipOrMask \ + ? VEC_WRITABLE | VEC_GOOD_STRIDE \ + : VEC_GOOD_STRIDE)); \ + \ + switch (VB->ctx->Visual->DepthBits) { \ + case 16: scale = 1.0 / 65536.0; break; \ + case 24: scale = 1.0 / 16777216.0; break; \ + case 32: scale = 1.0 / 4294967296.0; break; \ + default: scale = 1.0 / 65536.0; break; \ + } \ + \ + tc0 = VB->TexCoordPtr[0]->data; \ + tc1 = VB->TexCoordPtr[1]->data; \ + \ + v = &(R128_DRIVER_DATA(VB)->verts[start]); \ + \ + if (VB->ClipOrMask == 0) \ + for (i = start; i < end; i++, v++) { \ + win; \ + col; \ + spec; \ + fog; \ + tex0; \ + tex1; \ + } \ + else \ + for (i = start; i < end; i++, v++) { \ + if (VB->ClipMask[i] == 0) { \ + win; \ + spec; \ + fog; \ + tex0; \ + tex1; \ + } \ + col; \ + } \ + tex0_4; \ + tex1_4; \ +} + + +SETUPFUNC(rs_wt0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_wt1, COORD, NOP, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wt0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wft0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_wft1, COORD, NOP, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wft0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wg, COORD, COL, NOP, NOP, NOP, NOP, NOP, NOP) +SETUPFUNC(rs_wgs, COORD, COL, NOP, NOP, NOP, NOP, SPC, NOP) +SETUPFUNC(rs_wgt0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_wgt1, COORD, COL, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wgt0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wgst0, COORD, COL, TEX0, NOP, TEX0_4, NOP, SPC, NOP) +SETUPFUNC(rs_wgst1, COORD, COL, NOP, TEX1, NOP, TEX1_4, SPC, NOP) +SETUPFUNC(rs_wgst0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, NOP) +SETUPFUNC(rs_wgf, COORD, COL, NOP, NOP, NOP, NOP, NOP, FOG) +SETUPFUNC(rs_wgfs, COORD, COL, NOP, NOP, NOP, NOP, SPC, FOG) +SETUPFUNC(rs_wgft0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_wgft1, COORD, COL, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wgft0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wgfst0, COORD, COL, TEX0, NOP, TEX0_4, NOP, SPC, FOG) +SETUPFUNC(rs_wgfst1 , COORD, COL, NOP, TEX1, NOP, TEX1_4, SPC, FOG) +SETUPFUNC(rs_wgfst0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, FOG) + +SETUPFUNC(rs_t0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_t1, NOP, NOP, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_t0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_f, NOP, NOP, NOP, NOP, NOP, NOP, NOP, FOG) +SETUPFUNC(rs_ft0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_ft1, NOP, NOP, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_ft0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_g, NOP, COL, NOP, NOP, NOP, NOP, NOP, NOP) +SETUPFUNC(rs_gs, NOP, COL, NOP, NOP, NOP, NOP, SPC, NOP) +SETUPFUNC(rs_gt0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_gt1, NOP, COL, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_gt0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_gst0, NOP, COL, TEX0, NOP, TEX0_4, NOP, SPC, NOP) +SETUPFUNC(rs_gst1, NOP, COL, NOP, TEX1, NOP, TEX1_4, SPC, NOP) +SETUPFUNC(rs_gst0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, NOP) +SETUPFUNC(rs_gf, NOP, COL, NOP, NOP, NOP, NOP, NOP, FOG) +SETUPFUNC(rs_gfs, NOP, COL, NOP, NOP, NOP, NOP, SPC, FOG) +SETUPFUNC(rs_gft0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_gft1, NOP, COL, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_gft0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_gfst0, NOP, COL, TEX0, NOP, TEX0_4, NOP, SPC, FOG) +SETUPFUNC(rs_gfst1, NOP, COL, NOP, TEX1, NOP, TEX1_4, SPC, FOG) +SETUPFUNC(rs_gfst0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, FOG) + +static void rs_invalid(struct vertex_buffer *VB, GLuint start, GLuint end) +{ + fprintf(stderr, "r128RasterSetup(): invalid setup function\n"); +} + +typedef void (*setupFunc)(struct vertex_buffer *, GLuint, GLuint); +static setupFunc setup_func[0x80]; + +/* Initialize the table of vertex buffer setup functions */ +void r128SetupInit(void) +{ + int i; + + for (i = 0; i < 0x80; i++) setup_func[i] = rs_invalid; + + /* Funcs to build vertices from scratch */ + setup_func[R128_WIN_BIT|R128_TEX0_BIT] = rs_wt0; + setup_func[R128_WIN_BIT|R128_TEX1_BIT] = rs_wt1; + setup_func[R128_WIN_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wt0t1; + setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_wft0; + setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX1_BIT] = rs_wft1; + setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wft0t1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT] = rs_wg; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT] = rs_wgs; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX0_BIT] = rs_wgt0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX1_BIT] = rs_wgt1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgt0t1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_wgst0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_wgst1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgst0t1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT] = rs_wgf; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT] = rs_wgfs; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_wgft0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX1_BIT] = rs_wgft1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgft0t1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_wgfst0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_wgfst1; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgfst0t1; + + /* Funcs to repair vertices */ + setup_func[R128_TEX0_BIT] = rs_t0; + setup_func[R128_TEX1_BIT] = rs_t1; + setup_func[R128_TEX0_BIT|R128_TEX1_BIT] = rs_t0t1; + setup_func[R128_FOG_BIT] = rs_f; + setup_func[R128_FOG_BIT|R128_TEX0_BIT] = rs_ft0; + setup_func[R128_FOG_BIT|R128_TEX1_BIT] = rs_ft1; + setup_func[R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_ft0t1; + setup_func[R128_RGBA_BIT] = rs_g; + setup_func[R128_RGBA_BIT|R128_SPEC_BIT] = rs_gs; + setup_func[R128_RGBA_BIT|R128_TEX0_BIT] = rs_gt0; + setup_func[R128_RGBA_BIT|R128_TEX1_BIT] = rs_gt1; + setup_func[R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gt0t1; + setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_gst0; + setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_gst1; + setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gst0t1; + setup_func[R128_RGBA_BIT|R128_FOG_BIT] = rs_gf; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT] = rs_gfs; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_gft0; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX1_BIT] = rs_gft1; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gft0t1; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_gfst0; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_gfst1; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gfst0t1; +} + +/* Initialize the vertex buffer setup functions based on the current + rendering state */ +void r128ChooseRasterSetupFunc(GLcontext *ctx) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + int funcIndex = R128_WIN_BIT | R128_RGBA_BIT; + + if (ctx->Texture.Enabled & 0xf) { + if (ctx->Texture.Unit[0].EnvMode == GL_REPLACE) + funcIndex &= ~R128_RGBA_BIT; + funcIndex |= R128_TEX0_BIT; + } + + if (ctx->Texture.Enabled & 0xf0) + funcIndex |= R128_TEX1_BIT; + + /* FIXME: Verify this works properly */ + if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) + funcIndex |= R128_SPEC_BIT; + + if (ctx->FogMode == FOG_FRAGMENT) + funcIndex |= R128_FOG_BIT; + + r128ctx->SetupIndex = funcIndex; + ctx->Driver.RasterSetup = setup_func[funcIndex]; +} + +/* Check to see if any updates of the vertex buffer entries are needed */ +void r128CheckPartialRasterSetup(GLcontext *ctx, + struct gl_pipeline_stage *s) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + int tmp = r128ctx->SetupDone; + + s->type = 0; + r128ctx->SetupDone = GL_FALSE; + + if ((ctx->Array.Summary & VERT_OBJ_ANY) == 0) return; + if (ctx->IndirectTriangles) return; + + r128ctx->SetupDone = tmp; +} + +/* Update the vertex buffer entries, if necessary */ +void r128PartialRasterSetup(struct vertex_buffer *VB) +{ + r128ContextPtr r128ctx = R128_CONTEXT(VB->ctx); + int new = VB->pipeline->new_outputs; + int available = VB->pipeline->outputs; + int index = 0; + + if (new & VERT_WIN) { + new = available; + index |= R128_WIN_BIT | R128_FOG_BIT; + } + + if (new & VERT_RGBA) index |= R128_RGBA_BIT | R128_SPEC_BIT; + if (new & VERT_TEX0_ANY) index |= R128_TEX0_BIT; + if (new & VERT_TEX1_ANY) index |= R128_TEX1_BIT; +#if 0 + /* FIXME */ + if (new & VERT_FOG_COORD) index |= R128_FOG_BIT; +#endif + + r128ctx->SetupDone &= ~index; + index &= r128ctx->SetupIndex; + r128ctx->SetupDone |= index; + + if (index) setup_func[index & ~R128_ALPHA_BIT](VB, VB->Start, VB->Count); +} + +/* Perform the raster setup for the fast path, if using CVA */ +void r128DoRasterSetup(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + + if (VB->Type == VB_CVA_PRECALC) r128PartialRasterSetup(VB); + else if (ctx->Driver.RasterSetup) ctx->Driver.RasterSetup(VB, + VB->CopyStart, + VB->Count); +} + +/* Resize an existing vertex buffer */ +void r128ResizeVB(struct vertex_buffer *VB, GLuint size) +{ + r128VertexBufferPtr r128vb = R128_DRIVER_DATA(VB); + + while (r128vb->size < size) + r128vb->size *= 2; + + free(r128vb->vert_store); + r128vb->vert_store = malloc(sizeof(r128Vertex) * r128vb->size + 31); + if (!r128vb->vert_store) { + fprintf(stderr, "Cannot allocate vertex store! Exiting...\n"); + exit(1); + } + + r128vb->verts = (r128VertexPtr)(((CARD32)r128vb->vert_store + 31) & ~31); + + gl_vector1ui_free(&r128vb->clipped_elements); + gl_vector1ui_alloc(&r128vb->clipped_elements, + VEC_WRITABLE, r128vb->size, 32); + if (!r128vb->clipped_elements.start) { + fprintf(stderr, "Cannot allocate clipped elements! Exiting...\n"); + exit(1); + } + + free(VB->ClipMask); + VB->ClipMask = (GLubyte *)malloc(sizeof(GLubyte) * r128vb->size); + if (!VB->ClipMask) { + fprintf(stderr, "Cannot allocate clipmask! Exiting...\n"); + exit(1); + } +} + +/* Create a new device-dependent vertex buffer */ +void r128DDRegisterVB(struct vertex_buffer *VB) +{ + r128VertexBufferPtr r128vb; + + r128vb = (r128VertexBufferPtr)calloc(1, sizeof(*r128vb)); + + r128vb->size = VB->Size * 2; + r128vb->vert_store = malloc(sizeof(r128Vertex) * r128vb->size + 31); + if (!r128vb->vert_store) { + fprintf(stderr, "Cannot allocate vertex store! Exiting...\n"); + exit(1); + } + + r128vb->verts = (r128VertexPtr)(((CARD32)r128vb->vert_store + 31) & ~31); + + gl_vector1ui_alloc(&r128vb->clipped_elements, + VEC_WRITABLE, r128vb->size, 32); + if (!r128vb->clipped_elements.start) { + fprintf(stderr, "Cannot allocate clipped elements! Exiting...\n"); + exit(1); + } + + free(VB->ClipMask); + VB->ClipMask = (GLubyte *)malloc(sizeof(GLubyte) * r128vb->size); + if (!VB->ClipMask) { + fprintf(stderr, "Cannot allocate clipmask! Exiting...\n"); + exit(1); + } + + VB->driver_data = r128vb; +} + +/* Destroy a device-dependent vertex buffer */ +void r128DDUnregisterVB(struct vertex_buffer *VB) +{ + r128VertexBufferPtr r128vb = R128_DRIVER_DATA(VB); + + if (r128vb) { + if (r128vb->vert_store) free(r128vb->vert_store); + gl_vector1ui_free(&r128vb->clipped_elements); + free(r128vb); + VB->driver_data = 0; + } +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_vb.h b/xc/lib/GL/mesa/src/drv/r128/r128_vb.h new file mode 100644 index 000000000..4f7c11d7f --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_vb.h @@ -0,0 +1,150 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_VB_H_ +#define _R128_VB_H_ + +#ifdef GLX_DIRECT_RENDERING + +#define USE_RHW2 0 + +/* FIXME: This is endian-specific */ +typedef struct { + GLubyte b; + GLubyte g; + GLubyte r; + GLubyte a; +} r128Color; + +typedef struct { + GLfloat x, y, z; /* Coordinates in screen space */ + GLfloat rhw; /* Reciprocal homogeneous w */ + r128Color dif_argb; /* Diffuse color */ + r128Color spec_frgb; /* Specular color (alpha is fog) */ + GLfloat tu0, tv0; /* Texture 0 coordinates */ + GLfloat tu1, tv1; /* Texture 1 coordinates */ +#if USE_RHW2 + GLfloat rhw2; /* Reciprocal homogeneous w */ +#endif +} r128_vertex; + +#if USE_RHW2 +/* Format of vertices in r128_vertex struct */ +#define R128_FULL_VERTEX_FORMAT \ + R128_CCE_VC_FRMT_RHW | \ + R128_CCE_VC_FRMT_DIFFUSE_ARGB | \ + R128_CCE_VC_FRMT_SPEC_FRGB | \ + R128_CCE_VC_FRMT_S_T | \ + R128_CCE_VC_FRMT_S2_T2 | \ + R128_CCE_VC_FRMT_RHW2 + +/* Send a single vertex to the ring buffer */ +#define R128CCE_SEND_VERTEX(v) \ + do { \ + R128CCEF((v)->x); \ + R128CCEF((v)->y); \ + R128CCEF((v)->z); \ + R128CCEF((v)->rhw); \ + R128CCE(*(int *)&(v)->dif_argb); \ + R128CCE(*(int *)&(v)->spec_frgb); \ + R128CCEF((v)->tu0); \ + R128CCEF((v)->tv0); \ + R128CCEF((v)->tu1); \ + R128CCEF((v)->tv1); \ + R128CCEF((v)->rhw2); \ + } while (0) + +#else /* !USE_RHW2 */ + +/* Format of vertices in r128_vertex struct */ +#define R128_FULL_VERTEX_FORMAT \ + R128_CCE_VC_FRMT_RHW | \ + R128_CCE_VC_FRMT_DIFFUSE_ARGB | \ + R128_CCE_VC_FRMT_SPEC_FRGB | \ + R128_CCE_VC_FRMT_S_T | \ + R128_CCE_VC_FRMT_S2_T2 + +/* Send a single vertex to the ring buffer */ +#define R128CCE_SEND_VERTEX(v) \ + do { \ + R128CCEF((v)->x); \ + R128CCEF((v)->y); \ + R128CCEF((v)->z); \ + R128CCEF((v)->rhw); \ + R128CCE(*(int *)&(v)->dif_argb); \ + R128CCE(*(int *)&(v)->spec_frgb); \ + R128CCEF((v)->tu0); \ + R128CCEF((v)->tv0); \ + R128CCEF((v)->tu1); \ + R128CCEF((v)->tv1); \ + } while (0) +#endif + +/* FIXME: We currently only have assembly for 16-stride vertices */ +typedef union { + r128_vertex v; + float f[16]; +} r128Vertex, *r128VertexPtr; + +/* Vertex buffer for use when on the fast path */ +typedef struct { + GLuint size; /* Number of vertices in store */ + void *vert_store; /* Storage for vertex buffer */ + r128VertexPtr verts; /* Aligned start of verts in storage */ + int last_vert; /* Index of last vertex used */ + GLvector1ui clipped_elements; /* List of clipped elements */ +} *r128VertexBufferPtr; + +#define R128_DRIVER_DATA(vb) ((r128VertexBufferPtr)((vb)->driver_data)) + +#define R128_SPEC_BIT 0x01 +#define R128_FOG_BIT 0x02 +#define R128_ALPHA_BIT 0x04 /* GL_BLEND, not used */ +#define R128_TEX1_BIT 0x08 +#define R128_TEX0_BIT 0x10 +#define R128_RGBA_BIT 0x20 +#define R128_WIN_BIT 0x40 + +extern void r128SetupInit(void); +extern void r128ChooseRasterSetupFunc(GLcontext *ctx); +extern void r128CheckPartialRasterSetup(GLcontext *ctx, + struct gl_pipeline_stage *s); +extern void r128PartialRasterSetup(struct vertex_buffer *VB); +extern void r128DoRasterSetup(struct vertex_buffer *VB); +extern void r128ResizeVB(struct vertex_buffer *VB, GLuint size); +extern void r128DDRegisterVB(struct vertex_buffer *VB); +extern void r128DDUnregisterVB(struct vertex_buffer *VB); + +#endif +#endif /* _R128_VB_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c b/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c new file mode 100644 index 000000000..60d528813 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c @@ -0,0 +1,257 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifdef GLX_DIRECT_RENDERING + +/* r128 Mesa driver includes */ +#include "r128_init.h" +#include "r128_context.h" +#include "r128_xmesa.h" +#include "r128_state.h" +#include "r128_tex.h" +#include "r128_swap.h" + +/* Mesa src includes */ +#include "context.h" +#include "simple_list.h" +#include "mmath.h" + +#ifndef R128_DEBUG_FLAGS +int R128_DEBUG_FLAGS = (0 +#if 0 + | DEBUG_ALWAYS_SYNC + | DEBUG_VERBOSE_CCE + | DEBUG_VERBOSE_OUTREG + | DEBUG_VERBOSE_MSG + | DEBUG_NO_OUTRING + | DEBUG_NO_OUTREG + | DEBUG_VERBOSE_API + | DEBUG_VERBOSE_2D + | DEBUG_VERBOSE_DRI + | DEBUG_VALIDATE_RING + | DEBUG_VERBOSE_IOCTL +#endif + ); +#endif + +#if DEBUG_LOCKING +char *prevLockFile = NULL; +int prevLockLine = 0; +#endif + +static r128ContextPtr r128Context = NULL; + + +/* Initialize the driver specific screen private data */ +GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) +{ + sPriv->private = (void *)r128CreateScreen(sPriv); + if (!sPriv->private) { + r128DestroyScreen(sPriv); + return GL_FALSE; + } + + return GL_TRUE; +} + +/* Reset the driver specific screen private data */ +void XMesaResetDriver(__DRIscreenPrivate *sPriv) +{ + r128DestroyScreen(sPriv); +} + +/* Create and initialize the Mesa and driver specific visual data */ +GLvisual *XMesaCreateVisual(Display *dpy, + __DRIscreenPrivate *driScrnPriv, + const XVisualInfo *visinfo, + const __GLXvisualConfig *config) +{ + /* Drivers may change the args to _mesa_create_visual() in order to + * setup special visuals. + */ + return _mesa_create_visual(config->rgba, + config->doubleBuffer, + config->stereo, + _mesa_bitcount(visinfo->red_mask), + _mesa_bitcount(visinfo->green_mask), + _mesa_bitcount(visinfo->blue_mask), + config->alphaSize, + 0, /* index bits */ + config->depthSize, + config->stencilSize, + config->accumRedSize, + config->accumGreenSize, + config->accumBlueSize, + config->accumAlphaSize, + 0 /* num samples */); +} + +/* Create and initialize the Mesa and driver specific context data */ +GLboolean XMesaCreateContext(Display *dpy, GLvisual *mesaVis, + __DRIcontextPrivate *driContextPriv) +{ + return r128CreateContext(dpy, mesaVis, driContextPriv); +} + +/* Destroy the Mesa and driver specific context data */ +void XMesaDestroyContext(__DRIcontextPrivate *driContextPriv) +{ + r128ContextPtr r128ctx = (r128ContextPtr)driContextPriv->driverPrivate; + + if (r128ctx == (void *)r128Context) r128Context = NULL; + r128DestroyContext(r128ctx); +} + +/* Create and initialize the Mesa and driver specific pixmap buffer data */ +GLframebuffer *XMesaCreateWindowBuffer(Display *dpy, + __DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + GLvisual *mesaVis) +{ + return gl_create_framebuffer(mesaVis, + GL_FALSE, /* software depth buffer? */ + mesaVis->StencilBits > 0, + mesaVis->AccumRedBits > 0, + mesaVis->AlphaBits > 0 + ); +} + +/* Create and initialize the Mesa and driver specific pixmap buffer data */ +GLframebuffer *XMesaCreatePixmapBuffer( Display *dpy, + __DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + GLvisual *mesaVis) +{ +#if 0 + /* Different drivers may have different combinations of hardware and + * software ancillary buffers. + */ + return gl_create_framebuffer(mesaVis, + GL_FALSE, /* software depth buffer? */ + mesaVis->StencilBits > 0, + mesaVis->AccumRedBits > 0, + mesaVis->AlphaBits > 0); +#else + return NULL; /* not implemented yet */ +#endif +} + +/* Copy the back color buffer to the front color buffer */ +void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv) +{ + /* FIXME: This assumes buffer is currently bound to a context. This + needs to be able to swap buffers when not currently bound. Also, + this needs to swap according to buffer, and NOT according to + context! */ + if (r128Context == NULL) return; + + /* Only swap buffers when a back buffer exists */ + if (R128_MESACTX(r128Context)->Visual->DBflag) { + FLUSH_VB(R128_MESACTX(r128Context), "swap buffers"); + r128SwapBuffers(r128Context); + } +} + +/* Force the context `c' to be the current context and associate with it + buffer `b' */ +GLboolean XMesaMakeCurrent(__DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + if (driContextPriv) { + r128ContextPtr r128ctx = (r128ContextPtr)driContextPriv->driverPrivate; + + if (r128Context && + r128ctx == (void *)r128Context && + driDrawPriv == R128_DRIDRAWABLE(r128Context)) + return GL_TRUE; + + r128Context = r128MakeCurrent(r128Context, r128ctx, driDrawPriv); + + gl_make_current2(R128_MESACTX(r128Context), + driDrawPriv->mesaBuffer, driReadPriv->mesaBuffer); + + if (!R128_MESACTX(r128Context)->Viewport.Width) { + gl_Viewport(R128_MESACTX(r128Context), 0, 0, + driDrawPriv->w, driDrawPriv->h); + } + } else { + gl_make_current(0,0); + r128Context = NULL; + } + + return GL_TRUE; +} + +/* Force the context `c' to be unbound from its buffer */ +GLboolean XMesaUnbindContext(__DRIcontextPrivate *driContextPriv) +{ + return GL_TRUE; +} + +/* Update the hardware state. This is called if another context has + grabbed the hardware lock, which includes the X server. This + function also updates the driver's window state after the X server + moves, resizes or restacks a window -- the change will be reflected + in the drawable position and clip rects. Since the X server grabs + the hardware lock when it changes the window state, this routine will + automatically be called after such a change. */ +/* NOTE: This routine is only called while holding the hardware lock. */ +void XMesaUpdateState(__DRIcontextPrivate *driContextPriv) +{ + r128ContextPtr r128ctx = driContextPriv->driverPrivate; + __DRIscreenPrivate *sPriv = R128_DRISCREEN(r128ctx); + __DRIdrawablePrivate *dPriv = R128_DRIDRAWABLE(r128ctx); + int stamp = dPriv->lastStamp; + + /* The window might have moved, so we might need to get new clip + rects. + + NOTE: This releases and regrabs the hw lock to allow the X server + to respond to the DRI protocol request for new drawable info. + Since the hardware state depends on having the latest drawable + clip rects, all state checking must be done _after_ this call. */ + XMESA_VALIDATE_DRAWABLE_INFO(r128ctx->display, sPriv, dPriv); + + r128UpdateState(r128ctx, (stamp != dPriv->lastStamp)); +} + +/* This function is called by libGL.so as soon as libGL.so is loaded. + * This is where we'd register new extension functions with the dispatcher. + */ +void __driRegisterExtensions(void) +{ +} + +#endif diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.h b/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.h new file mode 100644 index 000000000..ca6fc127b --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.h @@ -0,0 +1,44 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_XMESA_H_ +#define _R128_XMESA_H_ + +#ifdef GLX_DIRECT_RENDERING + +extern void XMesaUpdateState(__DRIcontextPrivate *driContextPriv); +extern void __driRegisterExtensions(void); + +#endif +#endif /* _R128_XMESA_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/tdfx/Imakefile b/xc/lib/GL/mesa/src/drv/tdfx/Imakefile index c159a8e76..4a6a8e0ff 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/Imakefile +++ b/xc/lib/GL/mesa/src/drv/tdfx/Imakefile @@ -79,7 +79,8 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) fxglidew.o fxpipeline.o fxrender.o fxsanity.o fxsetup.o \ fxtexman.o fxtrifuncs.o fxvsetup.o - MESASRCS = ../../accum.c \ + MESASRCS = ../../aatriangle.c \ + ../../accum.c \ ../../alpha.c \ ../../alphabuf.c \ ../../attrib.c \ @@ -109,7 +110,7 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) ../../glthread.c \ ../../hash.c \ ../../image.c \ - ../../imaging.o \ + ../../imaging.c \ ../../light.c \ ../../lines.c \ ../../logic.c \ @@ -120,6 +121,7 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) ../../pb.c \ ../../pipeline.c \ ../../pixel.c \ + ../../pixeltex.c \ ../../points.c \ ../../polygon.c \ ../../quads.c \ @@ -136,6 +138,7 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) ../../texobj.c \ ../../texstate.c \ ../../texture.c \ + ../../texutil.c \ ../../translate.c \ ../../triangle.c \ ../../varray.c \ @@ -152,7 +155,8 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) ../../zoom.c \ ../../X86/common_x86.c - MESAOBJS = ../../accum.o \ + MESAOBJS = ../../aatriangle.o \ + ../../accum.o \ ../../alpha.o \ ../../alphabuf.o \ ../../attrib.o \ @@ -191,6 +195,7 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) ../../pb.o \ ../../pipeline.o \ ../../pixel.o \ + ../../pixeltex.o \ ../../points.o \ ../../polygon.o \ ../../quads.o \ @@ -207,6 +212,7 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) ../../texobj.o \ ../../texstate.o \ ../../texture.o \ + ../../texutil.o \ ../../translate.o \ ../../triangle.o \ ../../varray.o \ @@ -239,8 +245,7 @@ LinkSourceFile(fxvs_tmp.h, ../../../../../../extras/Mesa/src/FX) MMX_OBJS = ../../X86/mmx_blend.o -XCOMM Disabling 3Dnow code for the time being. -#if 0 +#if MesaUse3DNow 3DNOW_SRCS = ../../X86/3dnow.c \ ../../X86/3dnow_norm_raw.S \ ../../X86/3dnow_xform_masked1.S \ @@ -271,10 +276,14 @@ XCOMM Disabling 3Dnow code for the time being. ASMSRCS = $(X86_SRCS) $(MMX_SRCS) $(3DNOW_SRCS) ASMOBJS = $(X86_OBJS) $(MMX_OBJS) $(3DNOW_OBJS) - SRCS = $(DRISRCS) $(DRMSRCS) $(TDFXSRCS) $(MESASRCS) $(ASMSRCS) - OBJS = $(DRIOBJS) $(DRMOBJS) $(TDFXOBJS) $(MESAOBJS) $(ASMOBJS) + SRCS = $(DRISRCS) $(DRMSRCS) $(TDFXSRCS) $(MESASRCS) $(ASMSRCS) + OBJS = $(DRIOBJS) $(DRMOBJS) $(TDFXOBJS) $(MESAOBJS) $(ASMOBJS) + +REQUIREDLIBS = -lglide3x -lm +#if !GlxBuiltInTdfx +REQUIREDLIBS += -L../../../.. -lGL +#endif -REQUIREDLIBS += -lglide3x #if !GlxUseBuiltInDRIDriver #undef DoNormalLib NormalLibGlx diff --git a/xc/programs/Xserver/GL/dri/dri.c b/xc/programs/Xserver/GL/dri/dri.c index 0bff80a6c..c48c156bd 100644 --- a/xc/programs/Xserver/GL/dri/dri.c +++ b/xc/programs/Xserver/GL/dri/dri.c @@ -112,7 +112,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) fd = drmOpen(pDRIInfo->drmDriverName, NULL); if (fd < 0) { /* failed to open DRM */ - pScreen->devPrivates[DRIScreenPrivIndex].ptr = 0; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; return FALSE; } @@ -125,7 +125,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) pDRIPriv = (DRIScreenPrivPtr) xalloc(sizeof(DRIScreenPrivRec)); if (!pDRIPriv) { - pScreen->devPrivates[DRIScreenPrivIndex].ptr = 0; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; return FALSE; } @@ -137,6 +137,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) if (drmSetBusid(pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString) < 0) { pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; drmClose(pDRIPriv->drmFD); return FALSE; } @@ -155,6 +156,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) &pDRIPriv->hSAREA) < 0) { pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; drmClose(pDRIPriv->drmFD); return FALSE; } @@ -168,6 +170,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) { pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; drmClose(pDRIPriv->drmFD); return FALSE; } @@ -182,6 +185,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) &pDRIPriv->hFrameBuffer) < 0) { pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); drmClose(pDRIPriv->drmFD); return FALSE; diff --git a/xc/programs/Xserver/Imakefile b/xc/programs/Xserver/Imakefile index c1e91e6c5..cf9770537 100644 --- a/xc/programs/Xserver/Imakefile +++ b/xc/programs/Xserver/Imakefile @@ -619,7 +619,7 @@ XF86IDRVOBJS = $(XF86SRC)/input/drvConf.o XF86IDRVLIBS = $(XF86IDRIVERLIB) XF86SCANLIB = $(XF86SRC)/scanpci/LibraryTargetName(scanpci) XF86LIBS = $(XF86INIT) $(XF86COMLIB) $(XF86RACLIB) $(XF86PARSLIB) \ - $(XF86OSLIB) $(XF86INT10LIB) + $(XF86OSLIB) $(XF86INT10LIB) $(XF86DDCLIB) #else XF86LIBS = $(XF86INIT) $(XF86COMLIB) $(XF86PARSLIB) $(XF86OSLIB) #endif diff --git a/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml index 895ce09a7..e95ff113a 100644 --- a/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml +++ b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml @@ -3,17 +3,17 @@ ]> <!-- Created: Mon Feb 28 13:00:00 2000 by brian@precisioninsight.com --> -<!-- Revised: Mon Mar 6 20:10:02 2000 by kevin@precisioninsight.com --> +<!-- Revised: Fri May 19 09:41:48 2000 by martin@valinux.com --> <article> - <title>DRI Users Guide + <title>DRI User Guide <author><htmlurl url="http://www.precisioninsight.com/" name="Precision Insight, Inc."> - <date>6 March 2000 + <date>18 May 2000 <ident> - $XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml,v 1.3 2000/03/08 05:38:41 dawes Exp $ + $XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml,v 1.3 2000/04/05 05:38:41 brianp Exp $ </ident> <toc> @@ -25,7 +25,7 @@ <bf>Copyright © 2000 by Precision Insight, Inc., Cedar Park, Texas. All Rights Reserved.</bf> - <p> +<p> <bf>Permission is granted to make and distribute verbatim copies of this document provided the copyright notice and this permission notice are preserved on all copies.</bf> @@ -43,6 +43,8 @@ trademarks of 3Dlabs Inc. Ltd. 3dfx, Voodoo3, Voodoo4, and Voodoo5 are registered trademarks of 3dfx Interactive, Incorporated. + Matrox is a registered trademark of Matrox Electronic Systems Ltd. + ATI Rage is a registered trademark of ATI Technologies, Inc. All other trademarks mentioned are the property of their respective owners. @@ -60,9 +62,13 @@ software downloads. <p> This document does not cover compilation or installation of - XFree86 4.0; - it is assumed that you've already installed a Linux distribution which - includes XFree86 4.0. + XFree86 4.0. + It is assumed that you've already installed a Linux distribution which + includes XFree86 4.0 or that you're an experienced Linux developer + who has compiled the DRI for himself. + DRI download, compilation and installation instructions can be found + at <htmlurl url="http://dri.sourceforge.net/DRIcompile.html" + name="http://dri.sourceforge.net/DRIcompile.html"> <sect>Supported Hardware <p> @@ -71,8 +77,8 @@ Support for Alpha, and perhaps other CPUs, should be available in the future. <p> - XFree86 4.0 includes 3D acceleration for the following - graphics hardware: + XFree86 4.0 (or later versions) includes 3D acceleration for the + following graphics hardware: <itemize> <item>3dfx: @@ -87,6 +93,19 @@ </itemize> There are many configurations of 3dfx cards on the market. Not all have been tested. + <item>Matrox G400 + <item>ATI Rage 128 + <itemize> + <item>Rage Fury AGP + <item>Rage Magnum AGP + <item>XPERT 2000 AGP + <item>XPERT 128 AGP + <item>XPERT 99 AGP + <item>All-in-Wonder 128 AGP + </itemize> + The PCI versions of these cards also have minimal support. + Note that there are also Rage 128 Pro based boards on the + market, and these are not yet supported. <item>3Dlabs Oxygen GMX 2000 (MX/Gamma based) </itemize> @@ -94,8 +113,6 @@ Support for the following hardware is underway: <itemize> <item>Intel i810 - <item>Matrox G400 - <item>ATI Rage 128 <item>3dfx Voodoo4 and Voodoo5 series </itemize> @@ -104,8 +121,10 @@ <p> <itemize> <item>XFree86 4.0 - <item>Linux kernel 2.2.x (later kernels will be supported in + <item>For the 3dfx Voodoo3 driver, Linux kernel 2.2.x (later + kernels will be supported in the near future, and may be required for some chipsets) + <item>For the Matrox G400, Linux kernel 2.3.51, with AGP support </itemize> <p> Mesa 3.3 (beta) is included with XFree86 4.0; there is no need to @@ -119,20 +138,17 @@ <sect1>Kernel module <p> - Before starting the X server you must install the correct kernel - module for your hardware. - <p> - This can be done by executing the following as root: - <verb> - insmod XXX/drivername.o - </verb> - <p> - For example, on 3dfx hardware, the kernel module is called tdfx.o - so you you would type insmod XXX/tdfx.o - - <p> - Verify that the kernel module was installed by checking that - /proc/dri/0 exists. + XFree86 4.0.1 added automatic kernel module loading to the X server. + On Linux, the X server uses modprobe to load kernel modules. + The DRM kernel modules should be in /lib/modules/KERNEL-VERSION/misc/ + for automatic loading to work. +<p> + Optionally, DRM kernel modules can be loaded manually with insmod + prior to starting the X server. +<p> + You can verify that the kernel module was installed with lsmod, + checking the X server startup log, and checking that /proc/dri/0 + exists. <sect1>XF86Config file <p> @@ -199,6 +215,7 @@ <p> Next, the Device section of the XF86Config file must describe your particular hardware. + <p> For example, here's the Device section for a 3dfx Voodoo3 card: <verb> @@ -210,6 +227,27 @@ </verb> <p> + Here's the Device section for a Matrox G400 card: + <verb> + Section "Device" + Identifier "G400" + VendorName "Matrox" + Driver "mga" + VideoRam 32768 + EndSection + </verb> + + <p> + Here's the Device section for an ATI Rage 128 card: + <verb> + Section "Device" + Identifier "Rage128" + VendorName "ATI" + Driver "r128" + EndSection + </verb> + + <p> Finally, the Screen section of the XF86Config file may have to be specially configured as well. For example, Voodoo3 hardware acceleration is only available @@ -227,7 +265,10 @@ EndSubsection EndSection </verb> - + <p> + Replace <em>Voodoo3</em> with <em>G400</em> for Matrox G400. + <p> + Replace <em>Voodoo3</em> with <em>Rage128</em> for ATI Rage 128. <p> If there are errors in the XF86Config file, the X server will log errors to the file /var/log/XFree86.0.log @@ -301,6 +342,25 @@ if means that the libGL.so.1 file is not the right location. Proceed to the trouble shooting section. + <sect1>libOSMesa.so +<p> + OSMesa (Off-Screen Mesa) is an interface and driver for rendering + 3D images into a user-allocated block of memory rather than an + on-screen window. +<p> + libOSMesa.so implements the OSMesa interface and must be linked + with your application if you want to use the OSMesa functions. + You must also link with libGL.so. For example: + <verb> + gcc osdemo.c -L/usr/X11R6/lib -lOSMesa -lGLU -lGL -o osdemo + </verb> +<p> + In stand-alone Mesa this interface was compiled into the monolithic + libGL.so (formerly libMesaGL.so) library. + In XFree86 4.0.1 and later this interface is implemented in a + separate library. +<p> + <sect1>glxinfo <p> glxinfo is a useful program for checking which version of @@ -346,20 +406,25 @@ <enum> <item> <tt/LIBGL_DEBUG/, if defined will cause libGL.so to print error - and diagnostic messages. This can help to solve problems. + and diagnostic messages. + This can help to solve problems. + Setting <tt/LIBGL_DEBUG/ to <tt/verbose/ may provide additional + information. <item> <tt/LIBGL_ALWAYS_INDIRECT/, if defined this will force libGL.so to always use indirect rendering instead of hardware - acceleration. + acceleration. This can be useful to isolate rendering errors. <item> - <tt/LIBGL_DRIVERS_DIR/ can be used to override the default - directory which is searched for 3D drivers. + <tt/LIBGL_DRIVERS_PATH/ can be used to override the default + directories which are searched for 3D drivers. + The value is one or more paths separated by colons. In a typical XFree86 installation, the 3D drivers should be in - /usr/X11R6/lib/modules/dri/. - This environment variable can be used to specify a different - directory. + /usr/X11R6/lib/modules/dri/ and <tt/LIBGL_DRIVERS_PATH/ need + not be defined. Note that this feature is disabled for set-uid programs. + This variable replaces the <tt/LIBGL_DRIVERS_DIR/ env var used + in XFree86 4.0. </enum> <p> Mesa-based drivers (this includes most of the drivers listed @@ -531,6 +596,40 @@ <sect1>3dfx Voodoo3 <p> + <sect2>Configuration +<p> + Your XF86Config file's device section must specify the + <tt>tdfx</tt> device: + <verb> + Section "Device" + Identifier "Voodoo3" + VendorName "3dfx" + Driver "tdfx" + EndSection + </verb> + The Screen section should then reference the Voodoo3 device: + <verb> + Section "Screen" + Identifier "Screen 1" + Device "Voodoo3" + Monitor "High Res Monitor" + DefaultDepth 16 + Subsection "Display" + Depth 16 + Modes "1280x1024" "1024x768" "800x600" "640x480" + ViewPort 0 0 + EndSubsection + EndSection + </verb> + <p> + The kernel module for the Voodoo3 is named <tt>tdfx.o</tt> and + should be installed in /lib/modules/KERNEL-VERSION/misc/. + It will be automatically loaded by the Xserver if needed. + <p> + The DRI 3D driver for the Voodoo3 should be in + <tt>/usr/X11R6/lib/modules/dri/tdfx_dri.so</tt>. + This will be automatically loaded by libGL.so. + <sect2>Troubleshooting <p> <itemize> @@ -539,6 +638,9 @@ bit/pixel screen mode. Use <tt/xdpyinfo/ to verify that all your visuals are depth 16. Edit your XF86Config file if needed. + <item> + The <tt>/dev/3dfx</tt> device is not used for DRI; it's only for + Glide on older 3dfx hardware. </itemize> <sect2>Performance @@ -565,6 +667,9 @@ <p> <itemize> <item> + Glide cannot be used directly; only OpenGL-based programs are + supported on the Voodoo3. + <item> SSystem has problems because of poorly set near and far clipping planes. The office.unc Performer model also suffers from this problem. @@ -573,10 +678,120 @@ <sect1>Intel i810 <p> + Information to be added in the future. + <sect1>Matrox G400 <p> + <sect2>Configuration +<p> + Your XF86Config file's device section must specify the + <tt>mga</tt> device: + <verb> + Section "Device" + Identifier "G400" + VendorName "Matrox" + Driver "mga" + EndSection + </verb> + The Screen section should then reference the G400 mga device: + <verb> + Section "Screen" + Identifier "Screen 1" + Device "G400" + Monitor "High Res Monitor" + DefaultDepth 16 + Subsection "Display" + Depth 16 + Modes "1280x1024" "1024x768" "800x600" "640x480" + ViewPort 0 0 + EndSubsection + EndSection + </verb> + <p> + The kernel module for the G400 is named <tt>mga.o</tt> and + should be installed in /lib/modules/KERNEL-VERSION/misc/. + It will be automatically loaded by the Xserver if needed. + <p> + The DRI 3D driver for the G400 should be in + <tt>/usr/X11R6/lib/modules/dri/mga_dri.so</tt>. + This will be automatically loaded by libGL.so. + + <sect2>Troubleshooting +<p> + <itemize> + <item> + 3D acceleration for the G400 is only supported in the 16 + bit/pixel screen mode at this time. 32bpp will be supported + in the future. + Use <tt/xdpyinfo/ to verify that all your visuals are depth 16. + Edit your XF86Config file if needed. + </itemize> + + <sect2>Performance +<p> + No data at this time. + + <sect2>Known Problems +<p> + No data at this time. + + <sect1>ATI Rage 128 <p> + <sect2>Configuration +<p> + Your XF86Config file's device section must specify the + <tt>r128</tt> device: + <verb> + Section "Device" + Identifier "Rage128" + VendorName "ATI" + Driver "r128" + EndSection + </verb> + The Screen section should then reference the Rage 128 device: + <verb> + Section "Screen" + Identifier "Screen 1" + Device "Rage128" + Monitor "High Res Monitor" + DefaultDepth 16 + Subsection "Display" + Depth 16 + Modes "1280x1024" "1024x768" "800x600" "640x480" + ViewPort 0 0 + EndSubsection + Subsection "Display" + Depth 32 + Modes "1280x1024" "1024x768" "800x600" "640x480" + ViewPort 0 0 + EndSubsection + EndSection + </verb> + <p> + The kernel module for the Rage 128 is named <tt>r128.o</tt> and + should be installed in /lib/modules/KERNEL-VERSION/misc/. + It will be automatically loaded by the Xserver if needed. + <p> + The DRI 3D driver for the Rage 128 should be in + <tt>/usr/X11R6/lib/modules/dri/r128_dri.so</tt>. + This will be automatically loaded by libGL.so. + <p> + You may also set your screen depth to 32 for 32bpp mode. + <p> + + <sect2>Performance +<p> + While PCI Rage 128 based cards are supported, they do not yet + support PCI GART, so they will not perform as well as their + AGP counterparts. + + <sect2>Known Problems +<p> + DGA is not yet supported in the ATI Rage 128 X server. This + feature will be added in a future release. + + <sect1>3DLabs Oxygen GMX 2000 <p> The driver for this hardware was experimental and is no longer being @@ -621,6 +836,50 @@ which will be addressed in the future. + <sect1>libGL.so and dlopen() +<p> + A number of popular OpenGL applications on Linux (such as Quake3, + HereticII, Heavy Gear 2, etc) dynamically open the libGL.so + library at runtime with dlopen(), rather than linking with -lGL + at compile/link time. +<p> + If dynamic loading of libGL.so is not implemented carefully, there + can be a number of serious problems. + Here are the things to be careful of in your application: + <itemize> + <item>Specify the RTLD_GLOBAL flag to dlopen(). + If you don't do this then you'll likely see a runtime error message + complaining that _glapi_Context is undefined when libGL.so + tries to open a hardware-specific driver. + Without this flag, <em>nested</em> opening of dynamic libraries + does not work. + <item>Do not close the library with dlclose() until after + XCloseDisplay() has been called. + When libGL.so initializes itself it registers several callbacks + functions with Xlib. + When XCloseDisplay() is called those callback functions are + called. + If libGL.so has already been unloaded with dlclose() this will + cause a segmentation fault. + <item> + Your application should link with -lpthread. + On Linux, libGL.so uses the pthreads library in order to provide + thread safety. + There is apparently a bug in the dlopen()/dlclose() code which + causes crashes if the library uses pthreads but the parent + application doesn't. + The only known work-around is to link the application with + -lpthread. + </itemize> + + Some applications don't yet incorporate these procedures and + may fail. + For example, changing the graphics settings in some video games + will expose this problem. + The DRI developers are working with game vendors to prevent this + problem in the future. + + <sect1>Bug Database <p> The DRI bug database which includes bugs related to specific @@ -654,6 +913,9 @@ <item>Visit the <htmlurl url="http://dri.sourceforge.net" name="DRI project on SourceForge.net"> for the latest development news about the DRI and 3D drivers. + <item>The <htmlurl url="http://dri.sourceforge.net/DRIcompile.html" + name="DRI Compilation Guide"> explains how to download, compile + and install the DRI for yourself. </itemize> <sect1>Support @@ -664,54 +926,13 @@ <htmlurl url="http://sourceforge.net/mail/?group_id=387" name="SourceForge"> is a forum for people to discuss DRI problems. <item> - XXX IHV support? - <item> - XXX Linux distro support? + In the future there may be IHV and Linux vendor support resources + for the DRI. </itemize> </article> -<!-- -1. Introduction -2. Supported Hardware -3. Prerequisite Software -4. Start-Up -5. Using 3D Acceleration - 5.1 libGL.so - 5.2 glxinfo - 5.3 Environment variables -6. General Trouble Shooting -7. Hardware-Specific Information - 7.1 3dfx - 7.2 Intel i810 - 7.3 Matrox G400 - 7.4 ATI Rage 128 - 7.5 3DLabs Gamma -8. Limitation and Known Bugs - 8.1 OpenGL - 8.2 GLX - 8.3 Signal Handling - 8.4 Scheduling - 8.5 Bug Database -9. Resources - 9.1 Software Resources - GLU - GLUT - Glide3 - Utilities and demos - Sample XF86Config files - 9.2 Documentation - www.XFree86.org - www.opengl.org - www.linux.com - www.precisioninsight.com - sourceforge.net - 9.3 Support - IHVs - RedHat - --> - <!-- Local Variables: --> <!-- fill-column: 72 --> <!-- End: --> diff --git a/xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml new file mode 100644 index 000000000..5d0888342 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml @@ -0,0 +1,501 @@ +<!doctype linuxdoc system> +<!-- Created: Sun Mar 12 13:00:00 2000 by brian@precisioninsight.com --> +<!-- Revised: Fri May 19 09:36:02 2000 by martin@valinux.com --> +<!-- $Id: DRIcomp.sgml,v 1.6.14.1 2000/06/07 16:06:45 brianp Exp $ --> + + <article> + + <title>DRI Compilation Guide + <author> + <htmlurl url="http://www.precisioninsight.com/" + name="Precision Insight, Inc."> + <date>18 May 2000 + + <ident> + $XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DRI.sgml,v 1.3 2000/04/05 05:38:41 brianp Exp $ + </ident> + + <toc> + + <sect>Preamble + + <sect1>Copyright + <p> + <bf>Copyright © 2000 by Precision Insight, Inc., + Cedar Park, Texas. + All Rights Reserved.</bf> + <p> + <bf>Permission is granted to make and distribute verbatim copies + of this document provided the copyright notice and this permission + notice are preserved on all copies.</bf> + + <sect1>Trademarks + <p> + OpenGL is a registered trademark and SGI is a trademark of + Silicon Graphics, Inc. + Unix is a registered trademark of The Open Group. + The `X' device and X Window System are trademarks of The Open Group. + XFree86 is a trademark of The XFree86 Project. + Linux is a registered trademark of Linus Torvalds. + Intel is a registered trademark of Intel Corporation. + 3Dlabs, GLINT, and Oxygen are either registered trademarks or + trademarks of 3Dlabs Inc. Ltd. + 3dfx, Voodoo3, Voodoo4, and Voodoo5 are registered trademarks of + 3dfx Interactive, Incorporated. + Matrox is a registered trademark of Matrox Electronic Systems Ltd. + ATI Rage is a registered trademark of ATI Technologies, Inc. + All other trademarks mentioned are the property of their + respective owners. + + + <sect>Introduction + <p> + This document describes how to download, compile and install the + DRI project. + This information is intended for experienced Linux developers. + Beginners are probably better off installing precompiled packages. + <p> + Edits, corrections and updates to this document may be mailed + to brian@precisioninsight.com. + + + <sect>Prerequisites + <p> + You'll need the following: + <itemize> + <item>At least 400MB of free disk space. More is needed if you want + to build with debugging information or keep several build trees. + <item>A fast system. Using a PIII-550 it takes about 1/2 hour to + build everthing. + <item>GCC compiler and related tools. + <item>ssh (secure shell) for registed developer downloading of the + DRI source tree + </itemize> + + <p> + For 3dfx Voodoo3 hardware, you'll also need: + <itemize> + <item>Glide3x headers and runtime library if you want to use the + 3dfx driver. + These can be obtained from + <htmlurl url="http://linux.3dfx.com/open_source/glide_kit.htm" + name="linux.3dfx.com">. + <item>Linux kernel 2.2.x. + The DRI developers have been using stock RedHat 6.1 systems + (kernel 2.2.12-20). + Later kernel versions will be supported in the future. + </itemize> + + <p> + For Matrox G400 hardware, you'll also need: + <itemize> + <item>Linux kernel 2.3.51. Other kernel versions may work but + this one is known to work. + </itemize> + + <p> + For ATI Rage hardware, you'll also need: + <itemize> + <item>Linux kernel 2.3.51. Other kernel versions may work but + this one is known to work. + </itemize> + + + <sect>Kernel preparation + <p> + You may have to upgrade your Linux kernel in order to use the DRI. + This is because you need a kernel version which supports AGP. + Building a new Linux kernel can be difficult for beginners but + there are resouces on the Internet to help. + This document assumes experience with configuring, building and + installing Linux kernels. + <p> + Linux kernels can be downloaded from + <htmlurl url="http://www.kernel.org/pub/linux/kernel/" + name="www.kernel.org"> + <p> + Download the needed kernel and put it in /usr/src. + Create a directory for the source and unpack it. + For example: + <verb> + cd /usr/src + rm -f linux + mkdir linux-2.3.51 + ln -s linux-2.3.51 linux + bzcat linux-2.3.51.tar.bz2 | tar xf - + </verb> + <p> + Now configure your kernel. + You might, for example, use <tt>make menuconfig</tt> and do the + following: + + <itemize> + <item>Go to <em>Code maturity level options</em> + <item>Enable <em>Prompt for development and/or incomplete + code/drivers</em> + <item>hit ESC + <item>Go to <em>Character devices</em> + <item>Disable <em>Direct Rendering Manager (XFree86 DRI support)</em> + since we'll use the DRI module from the XFree86/DRI tree. + <item>Go to <em>/dev/agpgart (AGP Support) (EXPERIMENTAL) (NEW)</em> + <item>Hit SPACE twice + <item>Enable all chipsets' support for AGP + </itemize> + + <p>It's recommended that you turn on MTRRs under <em>Processor type + and Features</em>, but not required. + + <p> + Configure the rest of the kernel as required for your system + (i.e. ethernet, scsi, etc) + <p> + Exit, saving your kernel configuration. + <p> + Edit your /etc/lilo.conf file. + Make sure you have an image entry as follows (or similar): + <verb> + image=/boot/vmlinuz + label=linux.2.3.51 + read-only + root=/dev/hda1 + </verb> + <p> + The important part is that you have /boot/vmlinuz without a + trailing version number. + If this is the first entry in your /etc/lilo.conf AND you + haven't set a default, then this will be your default kernel. + + <p> + Now compile the new kernel: + + <verb> + cd /usr/src/linux-2.3.51 + make dep ; make bzImage + make modules ; make modules_install + make install + </verb> + Note that the final part, make install, will automatically run + lilo for you. + <p> + Now reboot to use this new kernel. + + + <sect>Downloading the XFree86/DRI CVS Sources + <p> + The DRI project is hosted by VA Linux Systems' + <htmlurl url="http://sourceforge.net/project/?group_id=387" + name="SourceForge">. + The DRI source code, which is a subset of the XFree86 source tree, + is kept in a CVS repository there. + <p> + The DRI CVS sources may be accessed either anonymously or as a + registered SourceForge user. + It's recommended that you become a registered SourceForge user so + that you may submit non-annonymous bug reports and can participate + in the mailing lists. + + <sect1>Anonymous CVS download: + <p> + <enum> + <item>Create a directory to store the CVS files: + <p> + <verb> + cd ~ + mkdir DRI-CVS + </verb> + You could put your CVS directory in a different place but we'll + use <tt>~/DRI-CVS/</tt> here. + <p> + <item>Check out the CVS sources: + <p> + <verb> + cd ~/DRI-CVS + cvs -d:pserver:anonymous@cvs.dri.sourceforge.net:/cvsroot/dri login + (hit ENTER when prompted for a password) + cvs -z3 -d:pserver:anonymous@cvs.dri.sourceforge.net:/cvsroot/dri co xc + </verb> + <p> + The -z3 flag causes compression to be used in order to reduce + the download time. + </enum> + + + <sect1>Registered CVS download: + <p> + <enum> + <item>Create a directory to store the CVS files: + <p> + <verb> + cd ~ + mkdir DRI-CVS + </verb> + You could put your CVS directory in a different place but we'll + use <tt>~/DRI-CVS/</tt> here. + <p> + <item>Set the CVS_RSH environment variable: + <p> + <verb> + setenv CVS_RSH ssh // if using csh or tcsh + export CVS_RSH=ssh // if using sh or bash + </verb> + <item>Check out the CVS sources: + <p> + <verb> + cd ~/DRI-CVS + cvs -z3 -dYOURID@cvs.dri.sourceforge.net:/cvsroot/dri co xc + </verb> + Replace <tt>YOURID</tt> with your CVS login name. + You'll be prompted to enter your sourceforge password. + <p> + The -z3 flag causes compression to be used in order to reduce + the download time. + </enum> + + + <sect>Updating your CVS sources + <p> + In the future you'll want to occasionally update your local copy of + the DRI source code to get the latest changes. + This can be done with: + <verb> + cd ~/DRI-CVS + cvs -z3 update -dA xc + </verb> + The -d flag causes any new subdirectories to be created and -A causes + most recent trunc sources to be fetched, not branch sources. + + + <sect>Compiling the XFree86/DRI tree + <sect1>Make a build tree + <p> + Rather than placing object files and library files right in the + source tree, they're instead put into a parallel <em>build</em> tree. + The build tree is made with the <tt>lndir</tt> command: + <verb> + cd ~/DRI-CVS + ln -s xc XFree40 + mkdir build + cd build + lndir -silent -ignorelinks ../XFree40 + </verb> + <p> + The build tree will be populated with symbolic links which point + back into the CVS source tree. + <p> + Advanced users may have several build trees for compiling and + testing with different options. + + <sect1>Edit the host.def file + <p> + The <tt>~/DRI-CVS/build/xc/config/cf/host.def</tt> file is used + to configure the XFree86 build process. + You can change it to customize your build options or make adjustments + for your particular system configuration + <p> + The default <tt>host.def</tt> file will look something like this: + <verb> + #define DefaultCCOptions -Wall + #define DefaultGcc2i386Opt -O2 + #define LibraryCDebugFlags -O2 + #define BuildServersOnly YES + #define XF86CardDrivers vga tdfx mga r128 + #define LinuxDistribution LinuxRedHat + #define DefaultCCOptions -ansi GccWarningOptions -pipe + #define BuildXF86DRI YES + #define HasGlide3 YES + /* Optionally turn these on for debugging */ + /* #define GlxBuiltInTdfx YES */ + /* #define GlxBuiltInMga YES */ + /* #define GlxBuiltInR128 YES */ + /* #define DoLoadableServer NO */ + #define SharedLibFont NO + </verb> + The <tt>ProjectRoot</tt> variable specifies where the XFree86 files + will be installed. + You probably don't want to use <tt>/usr/X11R6/</tt> because that + would overwrite your default X files. + The following is recommended: + <verb> + #define ProjectRoot /usr/XF86-main + </verb> + <p> + Especially note the <em>XF86CardDrivers</em> line to be sure your + driver is listed. + <p> + If you have 3dfx hardware be sure that the Glide 3x headers are + installed in <tt>/usr/include/glide3/</tt> and that the Glide 3x + library is installed at <tt>/usr/lib/libglide3x.so</tt>. + <p> + If you do not have 3dfx hardware comment out the <tt>HasGlide3</tt> + line in <tt>host.def</tt>. + <p> + + <sect1>Compile + <p> + To compile the complete DRI tree: + <verb> + cd ~/DRI-CVS/build/xc/ + make World >& World.LOG + </verb> + Or if you want to watch the compilation progress: + <verb> + cd ~/DRI-CVS/build/xc/ + make World >& World.LOG & + tail -f World.LOG + </verb> + With the default compilation flags it's normal to get a lot of + warnings during compilation. + <p> + Building will take some time so you may want to go check your + email or visit slashdot. + + <sect1>Check for compilation errors + <p> + Using your text editor, examine <tt>World.LOG</tt> for errors + by searching for the pattern <tt>***</tt>. + <p> + Verify that the DRI kernel module(s) for your system were built: + <verb> + cd ~/DRI-CVS/build/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel + ls + </verb> + <p> + For the 3dfx Voodoo, you should see <em>tdfx.o</em>. + For the Matrox G400, you should see <em>mga.o</em>. + For the ATI Rage 128, you should see <em>r128.o</em>. + <p> + If the DRI kernel module(s) failed to build you should verify + that you're using the right version of the Linux kernel. + The most recent kernels are not always supported. + <p> + If your build machine is running a different version of the kernel + than your target machine (i.e. 2.2.12-20 vs. 2.3.99-pre6), make will + select the wrong kernel headers. This can be fixed by explicitly + setting the value of <tt>TREE</tt>. + If the path to your kernel source is + <tt>/bigdisk/linux-2.3.99-pre6</tt>, + <verb> + cd ~/DRI-CVS/build/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel + make TREE=/bigdisk/linux-2.3.99-pre6 + </verb> + or alternatively, edit Makefile to include this change. + <p> + After fixing the errors, do <tt>make World</tt> again. + Later, you might just compile parts of the source tree but it's + important that the whole tree will build first. + + + <sect>Installing + <p> + After the DRI tree has been compiled you can install the XFree86 + headers, libraries, programs, etc for testing. + + <sect1>X Installation + <p> + As mentioned above, the install directory is specified by the + <tt>ProjectRoot</tt> variable in the <tt>host.def</tt> file. + Create that directory now if it doesn't already exist: + <verb> + mkdir /usr/XF86-main + </verb> + <p> + You'll have to change to root since the install process puts + several files in <tt>/etc/X11/</tt> and sets the setuid flag on + the X server executable. + <verb> + cd ~/DRI-CVS/build/xc + su + make install + </verb> + Edit your <tt>/etc/ld.so.conf</tt> file and put + <tt>/usr/XF86-main/lib</tt> as the first line. + Continue with: + <verb> + ldconfig + exit + </verb> + <p> + Look in <tt>/usr/XF86-main</tt> to be sure the files installed + there. + <P> + Strictly speaking, installing the DRI tree isn't required. + It's possible to run and test the X server directly from the + build directory but it's a bit error prone. + + <sect1>Update Locale Information + <p> + To update your X locale information do the following: + <verb> + cd ~/DRI-CVS/build/xc/nls + xmkmf -a + make + make install + </verb> + This will prevent a locale error message from being printed + when you run Xlib programs. + + <sect>X Server Configuration + <p> + If your X server is currently running you'll have to stop it + and return to a virtual terminal. + <p> + First, setup your XF86Config file. + It should load the GLX and DRI modules and specify the driver to + use for your hardware. + See the <htmlurl url="http://dri.sourceforge.net/DRIuserguide.html" + name="DRI User Guide"> for detailed information. + <p> + You may want to make a backup copy of your existing + <tt>/etc/X11/XF86Config</tt> file first. + <p> + It's very important that you set the <tt>ModulePath</tt> option to + point to your installation directory: + <verb> + ModulePath "/usr/XF86-main/lib/modules" + </verb> + <p> + Double check with this: + <verb> + grep ModulePath /etc/X11/XF86Config + </verb> + <p> + Next, your <tt>~/.xinitrc</tt> file controls which clients will be + launched when your X server starts. + You might put the following in yours: + <verb> + xset b off + xsetroot -solid "#004070" + xmodmap -e "clear mod4" + xrdb -merge ~/.Xdefaults + xterm -geometry +0+0 & + xterm -geometry +512+0 & + fvwm + </verb> + <p> + + <sect>X Server Start-up + <p> + The X server can be started with: + <p> + <verb> + xinit -- /usr/XF86-main/bin/XFree86 + </verb> + <p> + Automatic loading of DRM kernel modules was added to the X server + in XFree86 4.0.1. + This feature, and manual loading of kernel modules, is documented + in the DRI user guide. + <p> + At this point your X server should be up and running with + hardware-accelerated direct rendering. + Please read the + <htmlurl url="http://dri.sourceforge.net/DRIuserguide.html" + name="DRI User Guide"> for trouble shooting information. + + + </article> + + + <!-- Local Variables: --> + <!-- fill-column: 72 --> + <!-- End: --> diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/Imakefile b/xc/programs/Xserver/hw/xfree86/drivers/glint/Imakefile index c8624e19f..d72589c49 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/Imakefile +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/Imakefile @@ -14,10 +14,12 @@ DRIINCLUDES=-I$(SERVERSRC)/GL/dri -I$(LIBSRC)/GL/dri SRCS = glint_driver.c pm2_dac.c pm2ramdac.c pm2_accel.c pm_dac.c IBMramdac.c \ pm_accel.c tx_dac.c tx_accel.c pm2v_dac.c pm2vramdac.c pm2_video.c \ - TIramdac.c dualmx_dac.c dualmx_accel.c glint_shadow.c $(DRISRC) + TIramdac.c dualmx_dac.c dualmx_accel.c glint_shadow.c $(DRISRC) \ + glint_dga.c OBJS = glint_driver.o pm2_dac.o pm2ramdac.o pm2_accel.o pm_dac.o IBMramdac.o \ pm_accel.o tx_dac.o tx_accel.o pm2v_dac.o pm2vramdac.o pm2_video.o \ - TIramdac.o dualmx_dac.o dualmx_accel.o glint_shadow.o $(DRIOBJ) + TIramdac.o dualmx_dac.o dualmx_accel.o glint_shadow.o $(DRIOBJ) \ + glint_dga.o #if defined(XF86DriverSDK) INCLUDES = -I. -I../../include diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_accel.c index a6d34a4bf..974ee3b4f 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_accel.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_accel.c @@ -105,7 +105,6 @@ DualMXInitializeEngine(ScrnInfoPtr pScrn) GLINTPtr pGlint = GLINTPTR(pScrn); pGlint->rasterizerMode = RMMultiGLINT; - pGlint->pprod |= FBRM_ScanlineInt2; /* Initialize the Accelerator Engine to defaults */ @@ -120,8 +119,10 @@ DualMXInitializeEngine(ScrnInfoPtr pScrn) /* Make sure the rest of the register writes go to both MX's */ GLINT_SLOW_WRITE_REG(3, BroadcastMask); + GLINT_SLOW_WRITE_REG(pGlint->rasterizerMode, RasterizerMode); GLINT_SLOW_WRITE_REG(UNIT_DISABLE, ScissorMode); - GLINT_SLOW_WRITE_REG(pGlint->pprod, LBReadMode); + GLINT_SLOW_WRITE_REG(pGlint->pprod | LBRM_ScanlineInt2, LBReadMode); + pGlint->pprod |= FBRM_ScanlineInt2; GLINT_SLOW_WRITE_REG(pGlint->pprod, FBReadMode); GLINT_SLOW_WRITE_REG(0, dXSub); GLINT_SLOW_WRITE_REG(UNIT_DISABLE, LBWriteMode); @@ -149,7 +150,6 @@ DualMXInitializeEngine(ScrnInfoPtr pScrn) GLINT_SLOW_WRITE_REG(0x400, FilterMode); GLINT_SLOW_WRITE_REG(0xffffffff, FBHardwareWriteMask); GLINT_SLOW_WRITE_REG(0xffffffff, FBSoftwareWriteMask); - GLINT_SLOW_WRITE_REG(pGlint->rasterizerMode, RasterizerMode); GLINT_SLOW_WRITE_REG(UNIT_DISABLE, GLINTDepth); GLINT_SLOW_WRITE_REG(UNIT_DISABLE, FBSourceOffset); GLINT_SLOW_WRITE_REG(UNIT_DISABLE, FBPixelOffset); @@ -172,6 +172,7 @@ DualMXInitializeEngine(ScrnInfoPtr pScrn) GLINT_SLOW_WRITE_REG(0x0, PixelSize); break; } + pGlint->ROP = 0xFF; pGlint->ClippingOn = FALSE; pGlint->startxsub = 0; @@ -212,32 +213,34 @@ DualMXAccelInit(ScreenPtr pScreen) infoPtr->SetClippingRectangle = DualMXSetClippingRectangle; infoPtr->DisableClipping = DualMXDisableClipping; infoPtr->ClippingFlags = HARDWARE_CLIP_MONO_8x8_FILL | +#if 0 HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY | +#endif HARDWARE_CLIP_SOLID_FILL; infoPtr->SolidFillFlags = 0; infoPtr->SetupForSolidFill = DualMXSetupForFillRectSolid; infoPtr->SubsequentSolidFillRect = DualMXSubsequentFillRectSolid; - /* - * The following optimized routines are copied from tx_accel.c, - * but haven't been ported to a dual MX board. - */ -#ifdef NOT_DONE infoPtr->SolidLineFlags = 0; infoPtr->PolySegmentThinSolidFlags = 0; infoPtr->PolylinesThinSolidFlags = 0; infoPtr->SetupForSolidLine = DualMXSetupForSolidLine; infoPtr->SubsequentSolidHorVertLine = DualMXSubsequentHorVertLine; - infoPtr->SubsequentSolidBresenhamLine = + if (!(pScrn->overlayFlags & OVERLAY_8_32_PLANAR)) + { + infoPtr->SubsequentSolidBresenhamLine = DualMXSubsequentSolidBresenhamLine; + } infoPtr->PolySegmentThinSolid = DualMXPolySegmentThinSolidWrapper; infoPtr->PolylinesThinSolid = DualMXPolylinesThinSolidWrapper; +#if 0 infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | ONLY_LEFT_TO_RIGHT_BITBLT; infoPtr->SetupForScreenToScreenCopy = DualMXSetupForScreenToScreenCopy; infoPtr->SubsequentScreenToScreenCopy = DualMXSubsequentScreenToScreenCopy; +#endif infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_PROGRAMMED_ORIGIN | HARDWARE_PATTERN_SCREEN_ORIGIN | @@ -246,6 +249,7 @@ DualMXAccelInit(ScreenPtr pScreen) infoPtr->SubsequentMono8x8PatternFillRect = DualMXSubsequentMono8x8PatternFillRect; +#if 0 if (!pGlint->UsePCIRetry) { infoPtr->ScanlineCPUToScreenColorExpandFillFlags = TRANSPARENCY_ONLY | @@ -285,6 +289,7 @@ DualMXAccelInit(ScreenPtr pScreen) infoPtr->SubsequentCPUToScreenColorExpandFill = DualMXSubsequentCPUToScreenColorExpandFill; } +#endif infoPtr->ColorExpandRange = MAX_FIFO_ENTRIES; @@ -299,7 +304,6 @@ DualMXAccelInit(ScreenPtr pScreen) pScrn->bitsPerPixel / 8); xf86InitFBManager(pScreen, &AvailFBArea); -#endif /* NOT_DONE */ return (XAAInit(pScreen, infoPtr)); } @@ -312,11 +316,6 @@ static void DualMXLoadCoord( ){ GLINTPtr pGlint = GLINTPTR(pScrn); - /* - * Optimization from tx_accel.c where these values are cached on the - * host doesn't appear to work. We definitely need to reload at least - * the StartXDom value. I'll play it safe and reload them all. - */ GLINT_WRITE_REG(w<<16, StartXSub); GLINT_WRITE_REG(x<<16,StartXDom); GLINT_WRITE_REG(y<<16,StartY); @@ -686,14 +685,15 @@ DualMXSubsequentMono8x8PatternFillRect( if (pGlint->FrameBufferReadMode != -1) { if (pGlint->ROP == GXcopy) { GLINT_WRITE_REG(pGlint->BackGroundColor, FBBlockColor); - GLINT_WRITE_REG(PrimitiveTrapezoid | FastFillEnable,Render); + span = 0; } else { GLINT_WRITE_REG(pGlint->BackGroundColor, PatternRamData0); - GLINT_WRITE_REG(2<<1|2<<4|patternx<<7|patterny<<12|ASM_InvertPattern | + span = SpanOperation; + } + GLINT_WRITE_REG(2<<1|2<<4|patternx<<7|patterny<<12|ASM_InvertPattern | UNIT_ENABLE, AreaStippleMode); - GLINT_WRITE_REG(AreaStippleEnable | SpanOperation | FastFillEnable | + GLINT_WRITE_REG(AreaStippleEnable | span | FastFillEnable | PrimitiveTrapezoid, Render); - } } if (pGlint->ROP == GXcopy) { diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_dac.c b/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_dac.c index a17ab1c8b..0a7728ded 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_dac.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/dualmx_dac.c @@ -454,8 +454,7 @@ DualMXInit(ScrnInfoPtr pScrn, DisplayModePtr mode) pReg->glintRegs[VTGVSyncStart >> 3] = temp2; pReg->glintRegs[VTGVBlankEnd >> 3] = mode->CrtcVTotal - mode->CrtcVDisplay; - pReg->glintRegs[VTGPolarity >> 3] = (((mode->Flags & V_PHSYNC) ? 0:2)<<2) | - ((mode->Flags & V_PVSYNC) ? 0 : 2) | (0xb0); + pReg->glintRegs[VTGPolarity >> 3] = 0xba; pReg->glintRegs[VClkCtl >> 3] = 0; pReg->glintRegs[VTGVGateStart >> 3] = pReg->glintRegs[VTGVBlankEnd>>3] - 1; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint.h b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint.h index a84f7219a..9ef168854 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint.h @@ -105,6 +105,10 @@ typedef struct { unsigned char * IOBaseVGA; unsigned char * FbBase; long FbMapSize; + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; Bool DoubleBuffer; Bool NoAccel; Bool FBDev; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dga.c b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dga.c new file mode 100644 index 000000000..f3aa7ebe5 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dga.c @@ -0,0 +1,294 @@ +/* + * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ +/* $XFree86: $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xaa.h" +#include "xaalocal.h" +#include "glint.h" +#include "glint_regs.h" +#include "dgaproc.h" + +static Bool GLINT_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, + int *, int *, int *); +static Bool GLINT_SetMode(ScrnInfoPtr, DGAModePtr); +static void GLINT_Sync(ScrnInfoPtr); +static int GLINT_GetViewport(ScrnInfoPtr); +static void GLINT_SetViewport(ScrnInfoPtr, int, int, int); +static void GLINT_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void GLINT_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +static void GLINT_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); + +static +DGAFunctionRec GLINTDGAFuncs = { + GLINT_OpenFramebuffer, + NULL, + GLINT_SetMode, + GLINT_SetViewport, + GLINT_GetViewport, + GLINT_Sync, + GLINT_FillRect, + NULL, +#if 0 + GLINT_BlitRect, + GLINT_BlitTransRect +#else + NULL +#endif +}; + +Bool +GLINTDGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + GLINTPtr pGlint = GLINTPTR(pScrn); + DGAModePtr modes = NULL, newmodes = NULL, currentMode; + DisplayModePtr pMode, firstMode; + int Bpp = pScrn->bitsPerPixel >> 3; + int num = 0; + Bool oneMore; + + pMode = firstMode = pScrn->modes; + + while(pMode) { + + if(0 /*pScrn->displayWidth != pMode->HDisplay*/) { + newmodes = xrealloc(modes, (num + 2) * sizeof(DGAModeRec)); + oneMore = TRUE; + } else { + newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec)); + oneMore = FALSE; + } + + if(!newmodes) { + xfree(modes); + return FALSE; + } + modes = newmodes; + +SECOND_PASS: + + currentMode = modes + num; + num++; + + currentMode->mode = pMode; + currentMode->flags = DGA_CONCURRENT_ACCESS /*| DGA_PIXMAP_AVAILABLE*/; + if(!pGlint->NoAccel) + currentMode->flags |= DGA_FILL_RECT /*| DGA_BLIT_RECT*/; + if(pMode->Flags & V_DBLSCAN) + currentMode->flags |= DGA_DOUBLESCAN; + if(pMode->Flags & V_INTERLACE) + currentMode->flags |= DGA_INTERLACED; + currentMode->byteOrder = pScrn->imageByteOrder; + currentMode->depth = pScrn->depth; + currentMode->bitsPerPixel = pScrn->bitsPerPixel; + currentMode->red_mask = pScrn->mask.red; + currentMode->green_mask = pScrn->mask.green; + currentMode->blue_mask = pScrn->mask.blue; + currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor; + currentMode->viewportWidth = pMode->HDisplay; + currentMode->viewportHeight = pMode->VDisplay; + currentMode->xViewportStep = 1; + currentMode->yViewportStep = 1; + currentMode->viewportFlags = DGA_FLIP_RETRACE; + currentMode->offset = 0; + currentMode->address = pGlint->FbBase; + + if(oneMore) { /* first one is narrow width */ + currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L; + currentMode->imageWidth = pMode->HDisplay; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + oneMore = FALSE; + goto SECOND_PASS; + } else { + currentMode->bytesPerScanline = + ((pScrn->displayWidth * Bpp) + 3) & ~3L; + currentMode->imageWidth = pScrn->displayWidth; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + } + + pMode = pMode->next; + if(pMode == firstMode) + break; + } + + pGlint->numDGAModes = num; + pGlint->DGAModes = modes; + + return DGAInit(pScreen, &GLINTDGAFuncs, modes, num); +} + + +static Bool +GLINT_SetMode( + ScrnInfoPtr pScrn, + DGAModePtr pMode +){ + static int OldDisplayWidth[MAXSCREENS]; + int index = pScrn->pScreen->myNum; + GLINTPtr pGlint = GLINTPTR(pScrn); + + if(!pMode) { /* restore the original mode */ + /* put the ScreenParameters back */ + + pScrn->displayWidth = OldDisplayWidth[index]; + + GLINTSwitchMode(index, pScrn->currentMode, 0); + pGlint->DGAactive = FALSE; + } else { + if(!pGlint->DGAactive) { /* save the old parameters */ + OldDisplayWidth[index] = pScrn->displayWidth; + + pGlint->DGAactive = TRUE; + } + + pScrn->displayWidth = pMode->bytesPerScanline / + (pMode->bitsPerPixel >> 3); + + GLINTSwitchMode(index, pMode->mode, 0); + } + + return TRUE; +} + +static int +GLINT_GetViewport( + ScrnInfoPtr pScrn +){ + GLINTPtr pGlint = GLINTPTR(pScrn); + + return pGlint->DGAViewportStatus; +} + +static void +GLINT_SetViewport( + ScrnInfoPtr pScrn, + int x, int y, + int flags +){ + GLINTPtr pGlint = GLINTPTR(pScrn); + + GLINTAdjustFrame(pScrn->pScreen->myNum, x, y, flags); + pGlint->DGAViewportStatus = 0; /* GLINTAdjustFrame loops until finished */ +} + +static void +GLINT_FillRect ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color +){ + GLINTPtr pGlint = GLINTPTR(pScrn); + + if(pGlint->AccelInfoRec) { + (*pGlint->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); + (*pGlint->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + SET_SYNC_FLAG(pGlint->AccelInfoRec); + } +} + +static void +GLINT_Sync( + ScrnInfoPtr pScrn +){ + GLINTPtr pGlint = GLINTPTR(pScrn); + + if(pGlint->AccelInfoRec) { + (*pGlint->AccelInfoRec->Sync)(pScrn); + } +} + +static void +GLINT_BlitRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + GLINTPtr pGlint = GLINTPTR(pScrn); + + if(pGlint->AccelInfoRec) { + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + (*pGlint->AccelInfoRec->SetupForScreenToScreenCopy)( + pScrn, xdir, ydir, GXcopy, ~0, -1); + (*pGlint->AccelInfoRec->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + SET_SYNC_FLAG(pGlint->AccelInfoRec); + } +} + + +static void +GLINT_BlitTransRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + /* this one should be separate since the XAA function would + prohibit usage of ~0 as the key */ +} + + +static Bool +GLINT_OpenFramebuffer( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + GLINTPtr pGlint = GLINTPTR(pScrn); + + *name = NULL; /* no special device */ + *mem = (unsigned char*)pGlint->FbAddress; + *size = pGlint->FbMapSize; + *offset = 0; + *flags = DGA_NEED_ROOT; + + return TRUE; +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c index 0913cada0..9aa55de42 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c @@ -40,11 +40,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86PciInfo.h" #include "xf86Pci.h" -#define PSZ 8 -#include "cfb.h" -#undef PSZ -#include "cfb16.h" -#include "cfb32.h" +#include "fb.h" #include "miline.h" @@ -61,18 +57,7 @@ static void GLINTDestroyContext(ScreenPtr pScreen, drmContext hwContext, DRIContextType contextStore); static int -GLINTDRIControlInitSingleMX(int drmSubFD, int irq) -{ - - int retcode; - - /* Perhaps add flag to for single mx here? */ - if ((retcode = drmCtlInstHandler(drmSubFD, irq))) return 1; - return 0; -} - -static int -GLINTDRIControlInitDualMX(int drmSubFD, int irq) +GLINTDRIControlInit(int drmSubFD, int irq) { int retcode; @@ -105,7 +90,7 @@ GLINTInitVisualConfigs(ScreenPtr pScreen) case 32: /* if(pGlint->Overlay): differentiate overlays when we support either alpha buffer or 3D rendering in Overlay */ - numConfigs = 5; + numConfigs = 4; if (!(pConfigs = (__GLXvisualConfig *)xnfcalloc( sizeof(__GLXvisualConfig), @@ -260,6 +245,7 @@ GLINTInitVisualConfigs(ScreenPtr pScreen) pConfigs[3].transparentIndex = 0; pGlintConfigs[3].index = 3; +#if 0 /* config 4: db=TRUE, depth=16, stencil=8, conformant (a lie) */ pConfigs[4].vid = -1; pConfigs[4].class = -1; @@ -291,6 +277,7 @@ GLINTInitVisualConfigs(ScreenPtr pScreen) pConfigs[4].transparentAlpha = 0; pConfigs[4].transparentIndex = 0; pGlintConfigs[4].index = 4; +#endif break; } @@ -424,6 +411,7 @@ GLINTDRIScreenInit(ScreenPtr pScreen) DRIDestroyInfoRec(pGlint->pDRIInfo); return FALSE; } + pDRIInfo->devPrivate = pGlintDRI; pDRIInfo->devPrivateSize = sizeof(GLINTDRIRec); pDRIInfo->contextSize = sizeof(GLINTDRIContextRec); @@ -463,6 +451,11 @@ GLINTDRIScreenInit(ScreenPtr pScreen) } } + /* Tell the client driver how many MX's we have */ + pGlintDRI->numMXDevices = pGlint->numMXDevices; + /* Tell the client about our screen size setup */ + pGlintDRI->pprod = pGlint->pprod; + /* setup device specific direct rendering memory maps */ /* pci region 0: control regs, first 4k page, priveledged writes */ @@ -543,8 +536,8 @@ GLINTDRIScreenInit(ScreenPtr pScreen) if ((bufs = drmAddBufs(pGlint->drmSubFD, xf86ConfigDRI.bufs[i].count, xf86ConfigDRI.bufs[i].size, - 0, /* flags */ - 0 /* offset */)) <= 0) { + 0, + 0 /* flags */)) <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] failure adding %d %d byte DMA buffers\n", xf86ConfigDRI.bufs[i].count, @@ -564,8 +557,8 @@ GLINTDRIScreenInit(ScreenPtr pScreen) if ((bufs = drmAddBufs(pGlint->drmSubFD, GLINT_DRI_BUF_COUNT, GLINT_DRI_BUF_SIZE, - 0, /* flags */ - 0 /* offset */)) <= 0) { + 0, + 0 /* flags */)) <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] failure adding %d %d byte DMA buffers\n", GLINT_DRI_BUF_COUNT, @@ -602,26 +595,13 @@ GLINTDRIScreenInit(ScreenPtr pScreen) ->thisCard)->funcnum); } - if (pGlint->numMXDevices == 2) { - if ( (pGlint->irq <= 0) || - GLINTDRIControlInitDualMX(pGlint->drmSubFD, pGlint->irq) ) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] cannot initialize dma with IRQ %d\n", - pGlint->irq); - DRICloseScreen(pScreen); - return FALSE; - } - } - - if (pGlint->numMXDevices == 1) { - if ( (pGlint->irq <= 0) || - GLINTDRIControlInitSingleMX(pGlint->drmSubFD, pGlint->irq) ) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] cannot initialize dma with IRQ %d\n", - pGlint->irq); - DRICloseScreen(pScreen); - return FALSE; - } + if ( (pGlint->irq <= 0) || + GLINTDRIControlInit(pGlint->drmSubFD, pGlint->irq) ) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] cannot initialize dma with IRQ %d\n", + pGlint->irq); + DRICloseScreen(pScreen); + return FALSE; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -670,7 +650,7 @@ GLINTCreateContext(ScreenPtr pScreen, VisualPtr visual, drmContext hwContext, void *pVisualConfigPriv, - DRIContextType context) + DRIContextType contextStore) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; GLINTPtr pGlint = GLINTPTR(pScrn); @@ -1161,7 +1141,7 @@ GLINTDRISwapContext( /* send gamma the context dump command */ GLINT_WAIT(3); - if (pGlint->numMXDevices > 1) + if (pGlint->numMXDevices == 2) GLINT_WRITE_REG(1, BroadcastMask); GLINT_WRITE_REG(3<<14, FilterMode); /* context bits on gamma */ GLINT_WRITE_REG(GLINT_GAMMA_CONTEXT_MASK, ContextDump); @@ -1206,7 +1186,7 @@ dumpIndex,readValue); /* send context restore command */ GLINT_WAIT(1); - if (pGlint->numMXDevices > 1) + if (pGlint->numMXDevices == 2) GLINT_WRITE_REG(1, BroadcastMask); GLINT_WAIT(3); @@ -1235,7 +1215,7 @@ dumpIndex,pWC->Gamma[dumpIndex]); pGlint->AccelInfoRec->NeedToSync = TRUE; /* finally the MX portions */ - if (pGlint->numMXDevices > 1) + if (pGlint->numMXDevices == 2) GLINT_SLOW_WRITE_REG(1, BroadcastMask); GLINT_SLOW_WRITE_REG(pWC->MX1.CSStart, SStart); GLINT_SLOW_WRITE_REG(pWC->MX1.CdSdx, dSdx); @@ -1488,7 +1468,7 @@ dumpIndex,pWC->Gamma[dumpIndex]); /* restore the 2D portion of the new context */ /* Restore MX1's registers */ - if (pGlint->numMXDevices > 1) + if (pGlint->numMXDevices == 2) GLINT_SLOW_WRITE_REG(1, BroadcastMask); GLINT_SLOW_WRITE_REG(pWC->MX1.CStartXDom, StartXDom); GLINT_SLOW_WRITE_REG(pWC->MX1.CdXDom, dXDom); diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.h b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.h index 03f4d9fed..9e11edda8 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.h @@ -50,6 +50,8 @@ typedef struct { drmMapFlags flagsControlRegs1; drmMapFlags flagsControlRegs2; drmMapFlags flagsControlRegs3; + int numMXDevices; + int pprod; } GLINTDRIRec, *GLINTDRIPtr; #define GLINT_DRI_BUF_COUNT 20 diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dripriv.h b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dripriv.h index c92d90f98..e026f8b18 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dripriv.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dripriv.h @@ -42,15 +42,15 @@ extern void GlxSetVisualConfigs( extern Bool GLINTCreateContext(ScreenPtr pScreen, VisualPtr visual, drmContext hwContext, - void *pVisualConfigPriv, - DRIContextType context); + void* pVisualConfigPriv, + DRIContextType contextStore); extern void GLINTDRISwapContext( ScreenPtr pScreen, DRISyncType syncType, DRIContextType readContextType, - void *readContextStore, + void* readContextStore, DRIContextType writeContextType, - void *writeContextStore); + void* writeContextStore); /* Macros to Setup Generic Kernel Device Driver to Handle DMA for gamma */ diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_driver.c index edd418ae3..f0b316729 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_driver.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_driver.c @@ -2658,6 +2658,9 @@ GLINTScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); + if (!pGlint->ShadowFB) + GLINTDGAInit(pScreen); + if (pScrn->bitsPerPixel > 8) { /* Fixup RGB ordering */ visual = pScreen->visuals + pScreen->numVisuals; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_regs.h b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_regs.h index f33e42c80..489bf8eed 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_regs.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_regs.h @@ -35,6 +35,9 @@ #define PCI_CHIP_3DLABS_PERMEDIA 0x04 #define PCI_CHIP_3DLABS_MX 0x06 #define PCI_CHIP_3DLABS_PERMEDIA2 0x07 +#define PCI_CHIP_3DLABS_GAMMA 0x08 +#define PCI_CHIP_3DLABS_PERMEDIA2V 0x09 +#define PCI_CHIP_3DLABS_PERMEDIA3 0x0A #define PCI_CHIP_TI_PERMEDIA 0x3d04 #define CFGRevisionId 0x08 @@ -90,6 +93,10 @@ #define SCLK_SEL_MCLK_HALF (3 << 10) #define ByDMAControl 0x00D8 +/* GLINT R3 & Permedia3 Region 0 Bypass Controls */ +#define PM3ByAperture1Mode 0x0300 +#define PM3ByAperture2Mode 0x0328 + /* GLINT 500TX LocalBuffer Registers */ #define LBMemoryCtl 0x1000 #define LBNumBanksMask 0x00000001 @@ -192,6 +199,17 @@ #define PMFramebufferWriteMask 0x1140 #define PMCount 0x1180 +/* Permedia 3 & GLINT R3 Memory Control */ +#define PM3MemCounter 0x1000 +#define PM3MemBypassWriteMask 0x1008 +#define PM3MemScratch 0x1010 +#define PM3LocalMemCaps 0x1018 +#define PM3LocalMemTimings 0x1020 +#define PM3LocalMemControl 0x1028 +#define PM3LocalMemRefresh 0x1030 +#define PM3LocalMemPowerDown 0x1038 +#define PM3RemoteMemControl 0x1100 + /* Framebuffer Registers */ #define FBMemoryCtl 0x1800 #define FBModeSel 0x1808 @@ -1146,14 +1164,15 @@ #define GLINT_READ_REG(r) \ GLINT_VERB_READ_REG(pGlint,r,__FILE__,__LINE__) #else -#define GLINT_WRITE_REG(v,r) \ -do{ \ - *(volatile CARD32 *)((char *)pGlint->IOBase+(r))=v; \ - mem_barrier(); \ -}while(0) -#define GLINT_READ_REG(r) \ - (*(volatile CARD32 *)((char *)pGlint->IOBase+(r))) -#endif + +#define GLINT_WRITE_REG(v,r) MMIO_OUT32(pGlint->IOBase,(unsigned long)r, v) +#define GLINT_READ_REG(r) MMIO_IN32(pGlint->IOBase,(unsigned long)r) +#define GLINT_SECONDARY_WRITE_REG(v,r) \ + MMIO_OUT32(pGlint->IOBase,(unsigned long)r+0x10000, v) +#define GLINT_SECONDARY_READ_REG(r) \ + MMIO_IN32(pGlint->IOBase,(unsigned long)r+0x10000) + +#endif /* DEBUG */ #define GLINT_WAIT(n) \ do{ \ @@ -1179,23 +1198,12 @@ do{ \ GLINTDACDelay(5); \ }while(0) -#define GLINT_SECONDARY_WRITE_REG(v,r) \ -do{ \ - *(volatile CARD32 *)((char *)pGlint->SecondaryBase+(r))=v; \ -}while(0) - -#define GLINT_SECONDARY_READ_REG(r) \ - (*(volatile CARD32 *)((char *)pGlint->SecondaryBase+(r))) - #define GLINT_SECONDARY_SLOW_WRITE_REG(v,r) \ do{ \ while(GLINT_READ_REG(InFIFOSpace)<1); \ GLINT_SECONDARY_WRITE_REG(v,r); \ }while(0) -#define GLINT_LOAD_PAR(v,r) \ - *(unsigned long *)((char*)pGlint->IOBase+r) = *((unsigned long *) &v) - #define REPLICATE(r) \ { \ if (pScrn->bitsPerPixel == 16) { \ @@ -1208,14 +1216,21 @@ do{ \ } \ } +#ifndef XF86DRI #define LOADROP(rop) \ { \ - if (pGlint->ROP != rop) { \ + if (pGlint->ROP != rop) { \ GLINT_WRITE_REG(rop<<1|UNIT_ENABLE, LogicalOpMode); \ pGlint->ROP = rop; \ } \ } - +#else +#define LOADROP(rop) \ + { \ + GLINT_WRITE_REG(rop<<1|UNIT_ENABLE, LogicalOpMode); \ + pGlint->ROP = rop; \ + } +#endif #define CHECKCLIPPING \ { \ @@ -1226,6 +1241,7 @@ do{ \ } \ } +#ifndef XF86DRI #define DO_PLANEMASK(planemask) \ { \ if (planemask != pGlint->planemask) { \ @@ -1234,4 +1250,12 @@ do{ \ GLINT_WRITE_REG(planemask, FBHardwareWriteMask);\ } \ } +#else +#define DO_PLANEMASK(planemask) \ + { \ + pGlint->planemask = planemask; \ + REPLICATE(planemask); \ + GLINT_WRITE_REG(planemask, FBHardwareWriteMask);\ + } +#endif #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile b/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile index 331396f38..9e167d6c7 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile +++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/Imakefile @@ -6,13 +6,9 @@ XCOMM #define IHaveModules #include <Server.tmpl> -# -# Uncomment these to build with DRI support when available -# -#undef BuildXF86DRI #if BuildXF86DRI -DRISRCS = i810_dri.c i810_drm.c -DRIOBJS = i810_dri.o i810_drm.o +DRISRCS = i810_dri.c +DRIOBJS = i810_dri.o DRIINCLUDES = -I$(SERVERSRC)/GL/dri -I$(LIBSRC)/GL/dri \ -I$(XF86OSSRC)/linux/drm/kernel DRIDEFINES = $(GLX_DEFINES) @@ -63,7 +59,6 @@ InstallDriverSDKNonExecFile(i810_cursor.c,$(DRIVERSDKDIR)/drivers/i810) InstallDriverSDKNonExecFile(i810_driver.c,$(DRIVERSDKDIR)/drivers/i810) InstallDriverSDKNonExecFile(i810_dri.c,$(DRIVERSDKDIR)/drivers/i810) InstallDriverSDKNonExecFile(i810_dri.h,$(DRIVERSDKDIR)/drivers/i810) -InstallDriverSDKNonExecFile(i810_dripriv.h,$(DRIVERSDKDIR)/drivers/i810) InstallDriverSDKNonExecFile(i810_io.c,$(DRIVERSDKDIR)/drivers/i810) InstallDriverSDKNonExecFile(i810_memory.c,$(DRIVERSDKDIR)/drivers/i810) InstallDriverSDKNonExecFile(i810_wmark.c,$(DRIVERSDKDIR)/drivers/i810) diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h index a37ddca72..030b66a91 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h @@ -43,9 +43,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xaa.h" #include "xf86Cursor.h" -#undef XF86DRI - - #ifdef XF86DRI #include "xf86drm.h" #include "sarea.h" diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c index 0f67180d2..1a410bcd1 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c @@ -271,6 +271,7 @@ I810WaitLpRing( ScrnInfoPtr pScrn, int n, int timeout_millis ) DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]); } #endif + pI810->AccelInfoRec = NULL; /* Stops recursive behavior */ FatalError("lockup\n"); } @@ -301,13 +302,9 @@ I810Sync( ScrnInfoPtr pScrn ) #ifdef XF86DRI /* VT switching tries to do this. */ - if (!pI810->LockHeld) { + if (!pI810->LockHeld && pI810->directRenderingEnabled) { return; } - - -/* if (pI810->directRenderingEnabled) */ -/* DRIUnlockLockQueiscent( pScrn->pScreen ); */ #endif /* Send a flush instruction and then wait till the ring is empty. @@ -635,19 +632,19 @@ I810RefreshRing(ScrnInfoPtr pScrn) } - +/* Emit on gaining VT? + */ void I810EmitInvarientState(ScrnInfoPtr pScrn) { I810Ptr pI810 = I810PTR(pScrn); - BEGIN_LP_RING( 8 ); + BEGIN_LP_RING( 10 ); OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); OUT_RING( GFX_CMD_CONTEXT_SEL | CS_UPDATE_USE | CS_USE_CTX0 ); OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); OUT_RING( 0 ); - OUT_RING( GFX_OP_COLOR_CHROMA_KEY ); OUT_RING( CC1_UPDATE_KILL_WRITE | CC1_DISABLE_KILL_WRITE | @@ -658,5 +655,8 @@ I810EmitInvarientState(ScrnInfoPtr pScrn) OUT_RING( 0 ); OUT_RING( 0 ); +/* OUT_RING( CMD_OP_Z_BUFFER_INFO ); */ +/* OUT_RING( pI810->DepthBuffer.Start | pI810->auxPitchBits); */ + ADVANCE_LP_RING(); } diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c index 7de2d1d7a..e2c48f68f 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c @@ -73,13 +73,26 @@ Bool I810InitDma(ScrnInfoPtr pScrn) { I810Ptr pI810 = I810PTR(pScrn); I810RingBuffer *ring = &(pI810->LpRing); + drmI810Init info; Bool ret_val; - ret_val = drmI810InitDma(pI810->drmSubFD, ring->mem.Start, - ring->mem.End, ring->mem.Size, - 6, 5, sizeof(XF86DRISAREARec)); - if(ret_val == FALSE) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I810 Dma Initialization Failed\n"); + info.start = ring->mem.Start; + info.end = ring->mem.End; + info.size = ring->mem.Size; + info.ring_map_idx = 6; + info.buffer_map_idx = 5; + info.sarea_off = sizeof(XF86DRISAREARec); + + info.front_offset = 0; + info.back_offset = pI810->BackBuffer.Start; + info.depth_offset = pI810->DepthBuffer.Start; + info.w = pScrn->virtualX; + info.h = pScrn->virtualY; + info.pitch = pI810->auxPitch; + info.pitch_bits = pI810->auxPitchBits; + + ret_val = drmI810InitDma(pI810->drmSubFD, &info); + if(ret_val == FALSE) ErrorF("I810 Dma Initialization Failed\n"); return ret_val; } @@ -214,7 +227,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) #if XFree86LOADER /* Check that the GLX, DRI, and DRM modules have been loaded by testing - * for canonical symbols in each module. */ + * for known symbols in each module. */ if (!LoaderSymbol("GlxSetVisualConfigs")) return FALSE; if (!LoaderSymbol("DRIScreenInit")) return FALSE; if (!LoaderSymbol("drmAvailable")) return FALSE; @@ -248,6 +261,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) pDRIInfo->drmDriverName = I810KernelDriverName; pDRIInfo->clientDriverName = I810ClientDriverName; pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", ((pciConfigPtr)pI810->PciInfo->thisCard)->busnum, ((pciConfigPtr)pI810->PciInfo->thisCard)->devnum, @@ -370,7 +384,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, &dcacheHandle); pI810->dcacheHandle = dcacheHandle; - xf86DrvMsg(pScreen->myNum, X_INFO, "dcacheHandle : %p\n", dcacheHandle); #define Elements(x) sizeof(x)/sizeof(*x) @@ -386,10 +399,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) } else { back_size = i810_pitches[pitch_idx] * (pScrn->virtualY + 4); - xf86DrvMsg(pScreen->myNum, X_INFO, "back_size: %d\n", back_size); - /* Round to 4k */ back_size = ((back_size + 4096 - 1) / 4096) * 4096; - xf86DrvMsg(pScreen->myNum, X_INFO, "back_size 2 : %d\n", back_size); } sysmem_size = pScrn->videoRam * 1024; @@ -407,15 +417,18 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) else { sysmem_size = sysmem_size - 2*back_size; } - xf86DrvMsg(pScreen->myNum, X_INFO, "sysmem_size : %d\n", sysmem_size); - - sysmem_size -= 4096; - if (sysmem_size > ((48*1024*1024) - 1) ) { - sysmem_size = (48*1024*1024) - (2*4096); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "User requested more memory then fits in the agp aperture\n" + + if(sysmem_size > 48*1024*1024) { + sysmem_size = 48*1024*1024; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "User requested more memory then fits in the agp aperture\n" "Truncating to %d bytes of memory\n", sysmem_size); } + + sysmem_size -= 4096; /* remove 4k for the hw cursor */ + pI810->SysMem.Start = 0; pI810->SysMem.Size = sysmem_size; pI810->SysMem.End = sysmem_size; @@ -425,11 +438,7 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) if (dcacheHandle != 0) { /* The Z buffer is always aligned to the 48 mb mark in the aperture */ - xf86DrvMsg(pScreen->myNum, X_INFO, - "dcacheHandle : %p, aligned to : %lx\n", - dcacheHandle, 48*1024*1024); - - if (drmAgpBind(pI810->drmSubFD, dcacheHandle, 48*1024*1024) == 0) { + if(drmAgpBind(pI810->drmSubFD, dcacheHandle, 48*1024*1024) == 0) { xf86memset (&pI810->DcacheMem, 0, sizeof(I810MemRange)); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: Found 4096K Z buffer memory\n"); @@ -459,8 +468,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) if (agpHandle != 0) { /* The backbuffer is always aligned to the 56 mb mark in the aperture */ - xf86DrvMsg(pScreen->myNum, X_INFO, "agpHandle : %p, aligned to : %lx\n", - agpHandle, 56*1024*1024); if(drmAgpBind(pI810->drmSubFD, agpHandle, 56*1024*1024) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bound backbuffer memory\n"); @@ -488,10 +495,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) pI810->zHandle = agpHandle; if(agpHandle != 0) { - xf86DrvMsg(pScreen->myNum, X_INFO, - "agpHandle : %p, aligned to : %lx\n", dcacheHandle, - 48*1024*1024); - if(drmAgpBind(pI810->drmSubFD, agpHandle, 48*1024*1024) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bound depthbuffer memory\n"); pI810->DepthBuffer.Start = 48*1024*1024; @@ -515,7 +518,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) /* Now allocate and bind the agp space. This memory will include the * regular framebuffer as well as texture memory. */ - drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, &agpHandle); if (agpHandle == 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAgpAlloc failed\n"); @@ -542,7 +544,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) "GART: Allocated 4K for mouse cursor image\n"); pI810->CursorStart = tom; tom += 4096; - xf86DrvMsg(pScreen->myNum, X_INFO, "tom : %lx\n", tom); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: cursor bind failed\n"); @@ -554,28 +555,21 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) pI810->CursorPhysical = 0; } - ErrorF("i : %d pI810->DepthBuffer %x\n", pitch_idx, pI810->DepthBuffer); - I810SetTiledMemory(pScrn, 1, pI810->DepthBuffer.Start, i810_pitches[pitch_idx], 8*1024*1024); - ErrorF("i : %d\n", pitch_idx); I810SetTiledMemory(pScrn, 2, pI810->BackBuffer.Start, i810_pitches[pitch_idx], 8*1024*1024); - ErrorF("i : %d\n", pitch_idx); pI810->auxPitch = i810_pitches[pitch_idx]; pI810->auxPitchBits = i810_pitch_flags[pitch_idx]; - pI810->SavedDcacheMem = pI810->DcacheMem; - pI810DRI->backbufferSize = pI810->BackBuffer.Size; - xf86DrvMsg(pScreen->myNum, X_INFO, "Backbuffer map : %lx\n", - pI810->BackBuffer.Start); + if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->BackBuffer.Start, pI810->BackBuffer.Size, DRM_AGP, 0, &pI810DRI->backbuffer) < 0) { @@ -584,8 +578,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) return FALSE; } - xf86DrvMsg(pScreen->myNum, X_INFO, "Depth map : %lx\n", - pI810->DepthBuffer.Start); pI810DRI->depthbufferSize = pI810->DepthBuffer.Size; if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->DepthBuffer.Start, pI810->DepthBuffer.Size, DRM_AGP, 0, @@ -624,7 +616,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) pI810DRI->agp_buffers = pI810->buffer_map; pI810DRI->agp_buf_size = pI810->BufferMem.Size; - ErrorF("Ring map : %lx\n", pI810->LpRing.mem.Start); if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->LpRing.mem.Start, pI810->LpRing.mem.Size, DRM_AGP, 0, &pI810->ring_map) < 0) { @@ -636,8 +627,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) /* Use the rest of memory for textures. */ pI810DRI->textureSize = pI810->SysMem.Size; - ErrorF("INITIAL texsize: %x\n", pI810DRI->textureSize); - i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS); if (i < I810_LOG_MIN_TEX_REGION_SIZE) @@ -646,18 +635,15 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) pI810DRI->logTextureGranularity = i; pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i; /* truncate */ - xf86DrvMsg(pScreen->myNum, X_INFO, - "REDUCED texsize: %x (i: %d)\n", pI810DRI->textureSize, i); - - if (pI810DRI->textureSize < 512*1024) { - xf86DrvMsg(pScreen->myNum, X_ERROR, "Less then 512k for textures\n"); + if(pI810DRI->textureSize < 512*1024) { + ErrorF("Less then 512k for textures\n"); DRICloseScreen(pScreen); + return FALSE; } I810AllocLow( &(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize); - ErrorF("Texture map : %lx\n", pI810->TexMem.Start); if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->TexMem.Start, pI810->TexMem.Size, DRM_AGP, 0, &pI810DRI->textures) < 0) { @@ -666,7 +652,6 @@ Bool I810DRIScreenInit(ScreenPtr pScreen) return FALSE; } - ErrorF("pI810->BufferMem.Start : %lx\n", pI810->BufferMem.Start); if((bufs = drmAddBufs(pI810->drmSubFD, I810_DMA_BUF_NR, I810_DMA_BUF_SZ, diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c index 3db1809ae..6d4c8aafb 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c @@ -1028,7 +1028,6 @@ DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, pI810 = I810PTR(pScrn); hwp = VGAHWPTR(pScrn); - if (I810_DEBUG&DEBUG_VERBOSE_VGA) { ErrorF("Setting mode in I810Restore:\n"); i810PrintMode( vgaReg, i810Reg ); @@ -1094,7 +1093,7 @@ DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, temp &= ~INTERLACE_ENABLE; temp |= i810Reg->InterlaceControl; hwp->writeCrtc(hwp, INTERLACE_CNTL, temp); - + temp=pI810->readControl(pI810, GRX, ADDRESS_MAPPING); temp &= 0xE0; /* Save reserved bits 7:5 */ temp |= i810Reg->AddressMapping; @@ -1532,14 +1531,6 @@ I810AllocateFront(ScrnInfoPtr pScrn) { pI810->FbMemBox.y2 * pI810->cpp) + 4095) & ~4095); - fprintf(stderr, "Framebuffer %x, size %x\n", - pI810->FrontBuffer.Start, - pI810->FrontBuffer.Size); - - fprintf(stderr, "DisplayWidth %x, virtualX %x\n", - pScrn->displayWidth, - pScrn->virtualX); - xf86memset( &(pI810->LpRing), 0, sizeof( I810RingBuffer ) ); if(I810AllocLow( &(pI810->LpRing.mem), &(pI810->SysMem), 16*4096 )) { if (I810_DEBUG & DEBUG_VERBOSE_MEMORY) @@ -1728,13 +1719,6 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { } #endif - ErrorF("InitFB box: %d,%d-%d,%d virt: %d,%d\n", - pI810->FbMemBox.x1, - pI810->FbMemBox.y1, - pI810->FbMemBox.x2, - pI810->FbMemBox.y2, - pScrn->virtualX, - pScrn->virtualY); if (!xf86InitFBManager(pScreen, &(pI810->FbMemBox))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -1890,9 +1874,10 @@ I810LeaveVT(int scrnIndex, int flags) { pI810->LockHeld = 1; } #endif - - I810RefreshRing( pScrn ); - I810Sync( pScrn ); + if(pI810->AccelInfoRec != NULL) { + I810RefreshRing( pScrn ); + I810Sync( pScrn ); + } I810Restore(pScrn); vgaHWLock(hwp); } diff --git a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c index 2cedd9682..f499ffa2d 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c @@ -46,7 +46,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i810.h" #include "i810_reg.h" +#ifdef linux #include <linux/agpgart.h> +#endif int I810AllocLow( I810MemRange *result, I810MemRange *pool, int size ) { @@ -83,6 +85,7 @@ extern int xf86errno; int I810AllocateGARTMemory( ScrnInfoPtr pScrn ) { +#ifdef linux struct _agp_info agpinf; struct _agp_bind bind; struct _agp_allocate alloc; @@ -220,18 +223,23 @@ int I810AllocateGARTMemory( ScrnInfoPtr pScrn ) return TRUE; +#else + return FALSE; +#endif } void I810FreeGARTMemory( ScrnInfoPtr pScrn ) { +#ifdef linux I810Ptr pI810 = I810PTR(pScrn); if (pI810->gartfd != -1) { xf86close( pI810->gartfd ); pI810->gartfd = -1; } +#endif } diff --git a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c index ffa073561..7f91b6630 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c @@ -502,10 +502,8 @@ Bool MGADRIScreenInit(ScreenPtr pScreen) pMGADRI->chipset = MGA_CARD_TYPE_G400; break; case PCI_CHIP_MGAG200: -#if 0 pMGADRI->chipset = MGA_CARD_TYPE_G200; break; -#endif case PCI_CHIP_MGAG200_PCI: default: xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -561,29 +559,37 @@ Bool MGADRIScreenInit(ScreenPtr pScreen) pMGADRI->textureSize = (pMGADRI->textureSize >> i) << i; /* truncate */ - /* Calculate similar constants for AGP texture space - */ - i = mylog2(pMGADRI->agpSize / MGA_NR_TEX_REGIONS); - if (i < MGA_LOG_MIN_TEX_REGION_SIZE) - i = MGA_LOG_MIN_TEX_REGION_SIZE; - - pMGADRI->logAgpTextureGranularity = i; - pMGADRI->agpTextureSize = (pMGADRI->agpSize >> i) << i; - - /* Here is where we need to do initialization of the dma engine */ - if ((bufs = drmAddBufs(pMGA->drmSubFD, + if((bufs = drmAddBufs(pMGA->drmSubFD, MGA_DMA_BUF_NR, MGA_DMA_BUF_SZ, DRM_AGP_BUFFER, - init_offset)) <= 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] failure adding %d %d byte DMA buffers\n", - MGA_DMA_BUF_NR, - MGA_DMA_BUF_SZ); - DRICloseScreen(pScreen); - return FALSE; + init_offset)) <= 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] failure adding %d %d byte DMA buffers\n", + MGA_DMA_BUF_NR, + MGA_DMA_BUF_SZ); + DRICloseScreen(pScreen); + return FALSE; } + + pMGADRI->agpBufferOffset = init_offset + pMGADRIServer->agp_private; + + /* Calculate texture constants for AGP texture space + */ + { + CARD32 agpTextureOffset = MGA_DMA_BUF_SZ * MGA_DMA_BUF_NR; + CARD32 agpTextureSize = pMGADRI->agpSize - agpTextureOffset; + + i = mylog2(agpTextureSize / MGA_NR_TEX_REGIONS); + if (i < MGA_LOG_MIN_TEX_REGION_SIZE) + i = MGA_LOG_MIN_TEX_REGION_SIZE; + + pMGADRI->logAgpTextureGranularity = i; + pMGADRI->agpTextureSize = (agpTextureSize >> i) << i; + pMGADRI->agpTextureOffset = agpTextureOffset; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] added %d %d byte DMA buffers\n", diff --git a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h index 7196bc954..b8518ee89 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h @@ -4,9 +4,11 @@ #define _MGA_DRI_ #include <xf86drm.h> -#include "mga_drm_public.h" +#include <xf86drmMga.h> -typedef struct _mga_dri_server_private { +#define MGA_MAX_DRAWABLES 256 + +typedef struct { int reserved_map_agpstart; int reserved_map_idx; int buffer_map_idx; @@ -17,6 +19,7 @@ typedef struct _mga_dri_server_private { int sgram; unsigned long agpMode; unsigned long agpHandle; + Bool agpAcquired; drmHandle agp_private; drmSize agpSizep; drmAddress agpBase; @@ -24,27 +27,115 @@ typedef struct _mga_dri_server_private { drmHandle regs; drmSize regsSize; drmAddress regsMap; - mgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES]; + drmMgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES]; drmBufMapPtr drmBufs; CARD8 *agp_map; -} MGADRIServerPrivate, *MGADRIServerPrivatePtr; +} MGADRIServerPrivateRec, *MGADRIServerPrivatePtr; typedef struct { - int deviceID; - int width; - int height; - int mem; - int cpp; - int stride; - int fbOffset; - int backOffset; - int depthOffset; - int textureOffset; - int textureSize; - drmHandle agp; - drmSize agpSize; + int chipset; + int width; + int height; + int mem; + int cpp; + unsigned int frontOffset; + unsigned int frontPitch; + + unsigned int backOffset; + unsigned int backPitch; + + unsigned int depthOffset; + unsigned int depthPitch; + + unsigned int textureOffset; + unsigned int textureSize; + int logTextureGranularity; + + /* Allow calculation of setup dma addresses. + */ + unsigned int agpBufferOffset; + + unsigned int agpTextureOffset; + unsigned int agpTextureSize; + int logAgpTextureGranularity; + + /* Redundant? + */ + unsigned int frontOrg; + unsigned int backOrg; + unsigned int depthOrg; + + unsigned int mAccess; + + drmHandle agp; + drmSize agpSize; } MGADRIRec, *MGADRIPtr; +/* WARNING: Do not change the SAREA structure without changing the kernel + * as well */ +typedef struct { + unsigned char next, prev; + unsigned char in_use; + unsigned int age; +} MGATexRegionRec, *MGATexRegionPtr; + +typedef struct { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + unsigned int ContextState[MGA_CTX_SETUP_SIZE]; + unsigned int ServerState[MGA_2D_SETUP_SIZE]; + unsigned int TexState[2][MGA_TEX_SETUP_SIZE]; + unsigned int WarpPipe; + unsigned int dirty; + + unsigned int nbox; + XF86DRIClipRectRec boxes[MGA_NR_SAREA_CLIPRECTS]; + + /* Information about the most recently used 3d drawable. The + * client fills in the req_* fields, the server fills in the + * exported_ fields and puts the cliprects into boxes, above. + * + * The client clears the exported_drawable field before + * clobbering the boxes data. + */ + unsigned int req_drawable; /* the X drawable id */ + unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ + + unsigned int exported_drawable; + unsigned int exported_index; + unsigned int exported_stamp; + unsigned int exported_buffers; + unsigned int exported_nfront; + unsigned int exported_nback; + int exported_back_x, exported_front_x, exported_w; + int exported_back_y, exported_front_y, exported_h; + XF86DRIClipRectRec exported_boxes[MGA_NR_SAREA_CLIPRECTS]; + + /* Counters for aging textures and for client-side throttling. + */ + unsigned int last_enqueue; /* last time a buffer was enqueued */ + unsigned int last_dispatch; /* age of the most recently dispatched buffer */ + unsigned int last_quiescent; /* */ + + /* LRU lists for texture memory in agp space and on the card */ + + MGATexRegionRec texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1]; + unsigned int texAge[MGA_NR_TEX_HEAPS]; + /* Mechanism to validate card state. + */ + int ctxOwner; +} MGASAREARec, *MGASAREAPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} MGAConfigPrivRec, *MGAConfigPrivPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} MGADRIContextRec, *MGADRIContextPtr; #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile b/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile index e3f7178bf..8f0f33a35 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/Imakefile @@ -6,9 +6,16 @@ XCOMM #define IHaveModules #include <Server.tmpl> -SRCS = r128_driver.c r128_cursor.c r128_accel.c # r128_i2c.c +#if BuildXF86DRI +DRISRCS = r128_dri.c +DRIOBJS = r128_dri.o +DRIINCLUDES = -I$(SERVERSRC)/GL/dri -I$(LIBSRC)/GL/dri +DRIDEFINES = $(GLX_DEFINES) +#endif + +SRCS = r128_driver.c r128_cursor.c r128_accel.c $(DRISRCS) # r128_i2c.c -OBJS = r128_driver.o r128_cursor.o r128_accel.o # r128_i2c.o +OBJS = r128_driver.o r128_cursor.o r128_accel.o $(DRIOBJS) # r128_i2c.o #if defined(XF86DriverSDK) INCLUDES = -I. -I../../include @@ -22,9 +29,12 @@ INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86OSSRC) \ -I$(XF86SRC)/ddc -I$(XF86SRC)/i2c -I$(XF86OSSRC)/vbe \ -I$(XF86SRC)/int10 -I$(SERVERSRC)/Xext \ -I$(FONTINCSRC) -I$(SERVERSRC)/include -I$(XINCLUDESRC) \ - -I$(EXTINCSRC) -I$(XF86SRC)/xf24_32bpp + -I$(EXTINCSRC) -I$(XF86SRC)/xf24_32bpp \ + $(DRIINCLUDES) #endif +DEFINES = $(DRIDEFINES) + #if MakeHasPosixVariableSubstitutions SubdirLibraryRule($(OBJS)) #endif @@ -49,5 +59,10 @@ InstallDriverSDKNonExecFile(r128_cursor.c,$(DRIVERSDKDIR)/drivers/r128) InstallDriverSDKNonExecFile(r128_driver.c,$(DRIVERSDKDIR)/drivers/r128) InstallDriverSDKNonExecFile(r128_reg.h,$(DRIVERSDKDIR)/drivers/r128) +InstallDriverSDKNonExecFile(r128_dri.c,$(DRIVERSDKDIR)/drivers/r128) +InstallDriverSDKNonExecFile(r128_dri.h,$(DRIVERSDKDIR)/drivers/r128) +InstallDriverSDKNonExecFile(r128_dripriv.h,$(DRIVERSDKDIR)/drivers/r128) +InstallDriverSDKNonExecFile(r128_sarea.h,$(DRIVERSDKDIR)/drivers/r128) + InstallDriverSDKObjectModule(r128,$(DRIVERSDKMODULEDIR),drivers) diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h index d5d120153..acb04f96e 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h @@ -1,8 +1,8 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h,v 1.8 2000/02/23 04:47:18 martin Exp $ */ /************************************************************************** -Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -40,6 +40,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R128_TIMEOUT 2000000 /* Fall out of wait loops after this count */ #define R128_MMIOSIZE 0x80000 + /* R128_NAME is used for the server-side + ddx driver, the client-side DRI driver, + and the kernel-level DRM driver. */ #define R128_NAME "r128" #define R128_VERSION_MAJOR 3 #define R128_VERSION_MINOR 0 @@ -157,7 +160,7 @@ typedef struct { unsigned char *FB; /* Map of frame buffer */ CARD32 MemCntl; - CARD32 BusCntl; + CARD32 BusCntl; unsigned long FbMapSize; /* Size of frame buffer, in bytes */ int Flags; /* Saved copy of mode flags */ @@ -168,6 +171,8 @@ typedef struct { R128SaveRec ModeReg; /* Current mode */ Bool (*CloseScreen)(int, ScreenPtr); + Bool PaletteSavedOnVT; /* Palette saved on last VT switch */ + I2CBusPtr i2c; XAAInfoRecPtr accel; xf86CursorInfoPtr cursor; @@ -199,8 +204,98 @@ typedef struct { int scanline_words; int scanline_direct; int scanline_bpp; /* Only used for ImageWrite */ + +#ifdef XF86DRI + Bool directRenderingEnabled; + DRIInfoPtr pDRIInfo; + int drmFD; + int numVisualConfigs; + __GLXvisualConfig *pVisualConfigs; + R128ConfigPrivPtr pVisualConfigsPriv; + + drmHandle fbHandle; + + drmSize registerSize; + drmHandle registerHandle; + + Bool IsPCI; /* Current card is a PCI card */ + + drmSize agpSize; + drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ + unsigned long agpOffset; + unsigned char *AGP; /* Map */ + int agpMode; + + Bool CCEInUse; /* CCE is currently active */ + int CCEMode; /* CCE mode that server/clients use */ + int CCEFifoSize; /* Size of the CCE command FIFO */ + Bool CCESecure; /* CCE security enabled */ + int CCEusecTimeout; /* CCE timeout in usecs */ + Bool CCE2D; /* CCE is used for X server 2D prims */ + + /* CCE ring buffer data */ + unsigned long ringStart; /* Offset into AGP space */ + drmHandle ringHandle; /* Handle from drmAddMap */ + drmSize ringMapSize; /* Size of map */ + int ringSize; /* Size of ring (in MB) */ + unsigned char *ring; /* Map */ + int ringSizeLog2QW; + + unsigned long ringReadOffset; /* Offset into AGP space */ + drmHandle ringReadPtrHandle; /* Handle from drmAddMap */ + drmSize ringReadMapSize; /* Size of map */ + unsigned char *ringReadPtr; /* Map */ + + /* CCE vertex buffer data */ + unsigned long vbStart; /* Offset into AGP space */ + drmHandle vbHandle; /* Handle from drmAddMap */ + drmSize vbMapSize; /* Size of map */ + int vbSize; /* Size of vert bufs (in MB) */ + unsigned char *vb; /* Map */ + int vbBufSize; /* Size of individual vert buf */ + int vbNumBufs; /* Number of vert bufs */ + drmBufMapPtr vbBufs; /* Buffer map */ + + /* CCE indirect buffer data */ + unsigned long indStart; /* Offset into AGP space */ + drmHandle indHandle; /* Handle from drmAddMap */ + drmSize indMapSize; /* Size of map */ + int indSize; /* Size of indirect bufs (in MB) */ + unsigned char *ind; /* Map */ + + /* CCE AGP Texture data */ + unsigned long agpTexStart; /* Offset into AGP space */ + drmHandle agpTexHandle; /* Handle from drmAddMap */ + drmSize agpTexMapSize; /* Size of map */ + int agpTexSize; /* Size of AGP tex space (in MB) */ + unsigned char *agpTex; /* Map */ + int log2AGPTexGran; + + /* DRI screen private data */ + int fbX; + int fbY; + int backX; + int backY; + int depthX; + int depthY; + int textureX; + int textureY; + int textureSize; + int log2TexGran; +#endif } R128InfoRec, *R128InfoPtr; +#define R128WaitForFifo(pScrn, entries) \ +do { \ + if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \ + info->fifo_slots -= entries; \ +} while (0) + +extern void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries); +extern void R128WaitForIdle(ScrnInfoPtr pScrn); +extern void R128EngineReset(ScrnInfoPtr pScrn); +extern void R128EngineFlush(ScrnInfoPtr pScrn); + extern int INPLL(ScrnInfoPtr pScrn, int addr); extern void R128WaitForVerticalSync(ScrnInfoPtr pScrn); @@ -208,4 +303,16 @@ extern Bool R128AccelInit(ScreenPtr pScreen); extern void R128EngineInit(ScrnInfoPtr pScrn); extern Bool R128CursorInit(ScreenPtr pScreen); +extern int R128MinBits(int val); + +#ifdef XF86DRI +extern Bool R128DRIScreenInit(ScreenPtr pScreen); +extern void R128DRICloseScreen(ScreenPtr pScreen); +extern Bool R128DRIFinishScreenInit(ScreenPtr pScreen); +extern void R128CCEStart(ScrnInfoPtr pScrn); +extern void R128CCEStop(ScrnInfoPtr pScrn); +extern void R128CCEResetRing(ScrnInfoPtr pScrn); +extern void R128CCEWaitForIdle(ScrnInfoPtr pScrn); +#endif + #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c index 5b0223661..f42569767 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c @@ -1,8 +1,8 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c,v 1.7 2000/02/23 04:47:18 martin Exp $ */ /************************************************************************** -Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -95,6 +95,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* DDC support */ #include "xf86DDC.h" + /* DRI support */ +#ifdef XF86DRI +#include "GL/glxint.h" +#include "xf86drm.h" +#include "sarea.h" +#define _XF86DRI_SERVER_ +#include "xf86dri.h" +#include "dri.h" +#include "r128_dri.h" +#include "r128_dripriv.h" +#include "r128_sarea.h" +#endif + /* Driver data structures */ #include "r128.h" #include "r128_reg.h" @@ -122,7 +135,7 @@ static struct { }; /* Flush all dirty data in the Pixel Cache to memory. */ -static void R128EngineFlush(ScrnInfoPtr pScrn) +void R128EngineFlush(ScrnInfoPtr pScrn) { int i; R128MMIO_VARS(); @@ -134,11 +147,12 @@ static void R128EngineFlush(ScrnInfoPtr pScrn) } /* Reset graphics card to known state. */ -static void R128EngineReset(ScrnInfoPtr pScrn) +void R128EngineReset(ScrnInfoPtr pScrn) { - CARD32 clock_cntl_index; - CARD32 mclk_cntl; - CARD32 gen_reset_cntl; + R128InfoPtr info = R128PTR(pScrn); + CARD32 clock_cntl_index; + CARD32 mclk_cntl; + CARD32 gen_reset_cntl; R128MMIO_VARS(); R128EngineFlush(pScrn); @@ -158,17 +172,15 @@ static void R128EngineReset(ScrnInfoPtr pScrn) OUTPLL(R128_MCLK_CNTL, mclk_cntl); OUTREG(R128_CLOCK_CNTL_INDEX, clock_cntl_index); OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl); -} -#define R128WaitForFifo(pScrn, entries) \ -do { \ - if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \ - info->fifo_slots -= entries; \ -} while (0) +#ifdef XF86DRI + if (R128CCE_USE_RING_BUFFER(info->CCEMode)) R128CCEResetRing(pScrn); +#endif +} /* The FIFO has 64 slots. This routines waits until at least `entries' of these slots are empty. */ -static void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries) +void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries) { R128InfoPtr info = R128PTR(pScrn); int i; @@ -186,15 +198,19 @@ static void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FIFO timed out, resetting engine...\n"); R128EngineReset(pScrn); +#if XF86DRI + if (info->CCE2D) R128CCEStart(pScrn); +#endif } } /* Wait for the graphics engine to be completely idle: the FIFO has drained, the Pixel Cache is flushed, and the engine is idle. This is a standard "sync" function that will make the hardware "quiescent". */ -static void R128WaitForIdle(ScrnInfoPtr pScrn) +void R128WaitForIdle(ScrnInfoPtr pScrn) { - int i; + R128InfoPtr info = R128PTR(pScrn); + int i; R128MMIO_VARS(); R128WaitForFifoFunction(pScrn, 64); @@ -213,6 +229,9 @@ static void R128WaitForIdle(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); R128EngineReset(pScrn); +#if XF86DRI + if (info->CCE2D) R128CCEStart(pScrn); +#endif } } @@ -966,19 +985,33 @@ void R128EngineInit(ScrnInfoPtr pScrn) OUTREG(R128_DP_SRC_BKGD_CLR, 0x00000000); OUTREG(R128_DP_WRITE_MASK, 0xffffffff); +#if X_BYTE_ORDER == X_BIG_ENDIAN + OUTREGP(R128_DP_DATATYPE, + R128_HOST_BIG_ENDIAN_EN, ~R128_HOST_BIG_ENDIAN_EN); +#else + OUTREGP(R128_DP_DATATYPE, 0, ~R128_HOST_BIG_ENDIAN_EN); +#endif + R128WaitForIdle(pScrn); } -/* Initialize XAA for supported acceleration and also initialize the - graphics hardware for acceleration. */ -Bool R128AccelInit(ScreenPtr pScreen) +#ifdef XF86DRI + /* FIXME: When direct rendering is enabled, we should use the CCE to + draw 2D commands */ +static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - R128InfoPtr info = R128PTR(pScrn); - XAAInfoRecPtr a; + a->Flags = 0; + + /* Sync */ + a->Sync = R128CCEWaitForIdle; + +} +#endif + +static void R128MMIOAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) +{ + R128InfoPtr info = R128PTR(pScrn); - if (!(a = info->accel = XAACreateInfoRec())) return FALSE; - a->Flags = (PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER); @@ -1065,7 +1098,26 @@ Bool R128AccelInit(ScreenPtr pScreen) | SCANLINE_PAD_DWORD | SYNC_AFTER_IMAGE_WRITE); #endif - +} + +/* Initialize XAA for supported acceleration and also initialize the + graphics hardware for acceleration. */ +Bool R128AccelInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + XAAInfoRecPtr a; + + if (!(a = info->accel = XAACreateInfoRec())) return FALSE; + +#ifdef XF86DRI + /* FIXME: When direct rendering is enabled, we should use the CCE to + draw 2D commands */ + if (info->CCE2D) R128CCEAccelInit(pScrn, a); + else +#endif + R128MMIOAccelInit(pScrn, a); + R128EngineInit(pScrn); return XAAInit(pScreen, a); } diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c index a96872702..2667443d9 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c @@ -1,8 +1,8 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_cursor.c,v 1.6 2000/03/06 22:59:26 dawes Exp $ */ /************************************************************************** -Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -60,6 +60,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* DDC support */ #include "xf86DDC.h" + /* DRI support */ +#ifdef XF86DRI +#include "GL/glxint.h" +#include "xf86drm.h" +#include "sarea.h" +#define _XF86DRI_SERVER_ +#include "xf86dri.h" +#include "dri.h" +#include "r128_dri.h" +#include "r128_dripriv.h" +#include "r128_sarea.h" +#endif + /* Driver data structures */ #include "r128.h" #include "r128_reg.h" @@ -92,16 +105,19 @@ static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) (xorigin,yorigin). */ static void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { - R128InfoPtr info = R128PTR(pScrn); - int xorigin = 0; - int yorigin = 0; - int total_y = pScrn->frameY1 - pScrn->frameY0; + R128InfoPtr info = R128PTR(pScrn); + xf86CursorInfoPtr cursor = info->cursor; + int xorigin = 0; + int yorigin = 0; + int total_y = pScrn->frameY1 - pScrn->frameY0; R128MMIO_VARS(); - if (x < 0) xorigin = -x; - if (y < 0) yorigin = -y; - if (y > total_y) y = total_y; - if (info->Flags & V_DBLSCAN) y *= 2; + if (x < 0) xorigin = -x; + if (y < 0) yorigin = -y; + if (y > total_y) y = total_y; + if (info->Flags & V_DBLSCAN) y *= 2; + if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; + if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin); OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK @@ -126,47 +142,58 @@ static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) #if X_BYTE_ORDER == X_BIG_ENDIAN switch(info->pixel_bytes) { - case 4: - case 3: - for (y = 0; y < 64; y++) { - P_SWAP32(d,s); - d++; s++; - P_SWAP32(d,s); - d++; s++; - P_SWAP32(d,s); - d++; s++; - P_SWAP32(d,s); - d++; s++; - } - break; - case 2: - for (y = 0; y < 64; y++) { - P_SWAP16(d,s); - d++; s++; - P_SWAP16(d,s); - d++; s++; - P_SWAP16(d,s); - d++; s++; - P_SWAP16(d,s); - d++; s++; - } - break; - default: - for (y = 0; y < 64; y++) { + case 4: + case 3: + for (y = 0; y < 64; y++) { + P_SWAP32(d,s); + d++; s++; + P_SWAP32(d,s); + d++; s++; + P_SWAP32(d,s); + d++; s++; + P_SWAP32(d,s); + d++; s++; + } + break; + case 2: + for (y = 0; y < 64; y++) { + P_SWAP16(d,s); + d++; s++; + P_SWAP16(d,s); + d++; s++; + P_SWAP16(d,s); + d++; s++; + P_SWAP16(d,s); + d++; s++; + } + break; + default: + for (y = 0; y < 64; y++) { *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - } + } } #else - for (y = 0; y < 64; y++) { + for (y = 0; y < 64; y++) { *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; } #endif + + /* Set the area after the cursor to be all transparent so that we + won't display corrupted cursors on the screen */ + for (y = 0; y < 64; y++) { + *d++ = 0xffffffff; /* The AND bits */ + *d++ = 0xffffffff; + *d++ = 0x00000000; /* The XOR bits */ + *d++ = 0x00000000; + } + + OUTREG(R128_CRTC_GEN_CNTL, save); } @@ -204,6 +231,7 @@ Bool R128CursorInit(ScreenPtr pScreen) FBAreaPtr fbarea; int width; int height; + int size; if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE; @@ -227,8 +255,9 @@ Bool R128CursorInit(ScreenPtr pScreen) cursor->ShowCursor = R128ShowCursor; cursor->UseHWCursor = R128UseHWCursor; + size = (cursor->MaxWidth/4) * cursor->MaxHeight; width = pScrn->displayWidth; - height = (1024 + 1023) / pScrn->displayWidth; + height = (size*2 + 1023) / pScrn->displayWidth; fbarea = xf86AllocateOffscreenArea(pScreen, width, height, @@ -246,7 +275,7 @@ Bool R128CursorInit(ScreenPtr pScreen) info->cursor_start = R128_ALIGN((fbarea->box.x1 + width * fbarea->box.y1) * info->pixel_bytes, 16); - info->cursor_end = info->cursor_start + 1024; + info->cursor_end = info->cursor_start + size; } R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n", diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c new file mode 100644 index 000000000..cb647d6b6 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c @@ -0,0 +1,1242 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Rickard E. Faith <faith@precisioninsight.com> + * Daryll Strauss <daryll@precisioninsight.com> + * + */ + + + /* X and server generic header files */ +#include "xf86.h" +#include "xf86_ansic.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86RAC.h" +#include "xf86cmap.h" +#include "xf86fbman.h" + + /* Backing store, software cursor, and + colormap initialization */ +#include "mibstore.h" +#include "mipointer.h" +#include "micmap.h" + + /* CFB support */ +#define PSZ 8 +#include "cfb.h" +#undef PSZ +#include "cfb16.h" +#include "cfb24.h" +#include "cfb32.h" +#include "cfb24_32.h" + + /* XAA and Cursor Support */ +#include "xaa.h" +#include "xf86Cursor.h" + + /* PCI support */ +#include "xf86PciInfo.h" +#include "xf86Pci.h" + + /* DDC support */ +#include "xf86DDC.h" + + /* DRI support */ +#include "GL/glxint.h" +#include "GL/glxtokens.h" +#include "xf86drm.h" +#include "xf86drmR128.h" +#include "sarea.h" +#define _XF86DRI_SERVER_ +#include "xf86dri.h" +#include "dri.h" +#include "r128_dri.h" +#include "r128_sarea.h" +#include "r128_dripriv.h" + + /* Driver data structures */ +#include "r128.h" +#include "r128_reg.h" + +#define R128_WATERMARK_L 16 +#define R128_WATERMARK_M 8 +#define R128_WATERMARK_N 8 +#define R128_WATERMARK_K 128 + +static int CCEFifoSlots = 0; + +#define R128CCEWaitForFifo(pScrn, entries) \ +do { \ + if (CCEFifoSlots < entries) R128WaitForFifoFunction(pScrn, entries); \ + CCEFifoSlots -= entries; \ +} while (0) + +/* Wait for at least `entries' slots are free. The actual number of + slots available is stored in info->CCEFifoSize. */ +static void R128CCEWaitForFifoFunction(ScrnInfoPtr pScrn, int entries) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + int i; + + for (;;) { + for (i = 0; i < R128_TIMEOUT; i++) { + CCEFifoSlots = INREG(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK; + if (CCEFifoSlots >= entries) return; + } + R128EngineReset(pScrn); + if (info->CCE2D) R128CCEStart(pScrn); + } +} + +/* Wait until the CCE is completely idle: the FIFO has drained and the + CCE is idle. */ +void R128CCEWaitForIdle(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + int i; + + if (!info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return; + + if (R128CCE_USE_RING_BUFFER(info->CCEMode)) { + volatile CARD32 *r128RingReadPtr = + (volatile CARD32 *)(info->ringReadPtr); + R128SAREAPrivPtr pSAREAPriv; + + OUTREGP(R128_PM4_BUFFER_DL_WPTR, + R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE); + + pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen); + + for (;;) { + for (i = 0; i < R128_TIMEOUT; i++) { + if (*r128RingReadPtr == pSAREAPriv->ringWrite) { + int pm4stat = INREG(R128_PM4_STAT); + if ((pm4stat & R128_PM4_FIFOCNT_MASK) >= info->CCEFifoSize + && !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) + return; + } + } + R128EngineReset(pScrn); + if (info->CCE2D) R128CCEStart(pScrn); + } + } else { + R128CCEWaitForFifoFunction(pScrn, info->CCEFifoSize); + + for (;;) { + for (i = 0; i < R128_TIMEOUT; i++) { + if (!(INREG(R128_PM4_STAT) + & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + R128EngineFlush(pScrn); + return; + } + } + R128EngineReset(pScrn); + if (info->CCE2D) R128CCEStart(pScrn); + } + } +} + +/* Reset the ring buffer status, if the engine was reset */ +void R128CCEResetRing(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128SAREAPrivPtr pSAREAPriv; + volatile CARD32 *r128RingReadPtr; + + if (!info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return; + + r128RingReadPtr = (volatile CARD32 *)(info->ringReadPtr); + pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen); + + OUTREG(R128_PM4_BUFFER_DL_WPTR, 0); + OUTREG(R128_PM4_BUFFER_DL_RPTR, 0); + pSAREAPriv->ringWrite = 0; + *r128RingReadPtr = 0; + + /* Resetting the ring turns off the CCE */ + info->CCEInUse = FALSE; +} + +/* Start the CCE, but only if it is not already in use and the requested + mode is a CCE mode. The mode is stored in info->CCEMode. */ +void R128CCEStart(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + if (info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return; + + R128WaitForIdle(pScrn); + OUTREG(R128_PM4_BUFFER_CNTL, info->CCEMode | info->ringSizeLog2QW); + (void)INREG(R128_PM4_BUFFER_ADDR); /* as per the sample code */ + OUTREG(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); + info->CCEInUse = TRUE; +} + +/* Stop the CCE, but only if it is in use and the requested mode is not + the non-CCE mode. This function also flushes any outstanding + requests before switching modes.*/ +void R128CCEStop(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + if (!info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return; + + R128CCEWaitForIdle(pScrn); + OUTREG(R128_PM4_MICRO_CNTL, 0); + OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4); + R128EngineReset(pScrn); + info->CCEInUse = FALSE; +} + +/* Initialize the visual configs that are supported by the hardware. + These are combined with the visual configs that the indirect + rendering core supports, and the intersection is exported to the + client. */ +static Bool R128InitVisualConfigs(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + int numConfigs = 0; + __GLXvisualConfig *pConfigs = 0; + R128ConfigPrivPtr pR128Configs = 0; + R128ConfigPrivPtr *pR128ConfigPtrs = 0; + int i, accum, stencil; + + switch (pR128->pixel_code) { + case 8: /* 8bpp mode is not support */ + case 15: /* FIXME */ + case 24: /* FIXME */ + return FALSE; + +#define R128_USE_ACCUM 1 +#define R128_USE_STENCIL 0 /* Only in 24 depth mode */ + + case 16: + numConfigs = 1; + if (R128_USE_ACCUM) numConfigs *= 2; + + if (!(pConfigs + = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig), + numConfigs))) { + return FALSE; + } + if (!(pR128Configs + = (R128ConfigPrivPtr)xnfcalloc(sizeof(R128ConfigPrivRec), + numConfigs))) { + xfree(pConfigs); + return FALSE; + } + if (!(pR128ConfigPtrs + = (R128ConfigPrivPtr*)xnfcalloc(sizeof(R128ConfigPrivPtr), + numConfigs))) { + xfree(pConfigs); + xfree(pR128Configs); + return FALSE; + } + + i = 0; + for (accum = 0; accum <= R128_USE_ACCUM; accum++) { + pR128ConfigPtrs[i] = &pR128Configs[i]; + + pConfigs[i].vid = -1; + pConfigs[i].class = -1; + pConfigs[i].rgba = TRUE; + pConfigs[i].redSize = 5; + pConfigs[i].greenSize = 6; + pConfigs[i].blueSize = 5; + pConfigs[i].redMask = 0x0000F800; + pConfigs[i].greenMask = 0x000007E0; + pConfigs[i].blueMask = 0x0000001F; + + pConfigs[i].alphaMask = 0; + if (accum) { /* Simulated in software */ + pConfigs[i].accumRedSize = 16; + pConfigs[i].accumGreenSize = 16; + pConfigs[i].accumBlueSize = 16; + pConfigs[i].accumAlphaSize = 0; + } else { + pConfigs[i].accumRedSize = 0; + pConfigs[i].accumGreenSize = 0; + pConfigs[i].accumBlueSize = 0; + pConfigs[i].accumAlphaSize = 0; + } + pConfigs[i].doubleBuffer = TRUE; + pConfigs[i].stereo = FALSE; + pConfigs[i].bufferSize = 16; + pConfigs[i].depthSize = 16; + pConfigs[i].stencilSize = 0; + pConfigs[i].auxBuffers = 0; + pConfigs[i].level = 0; + if (accum) + pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; + else + pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].transparentPixel = 0; + pConfigs[i].transparentRed = 0; + pConfigs[i].transparentGreen = 0; + pConfigs[i].transparentBlue = 0; + pConfigs[i].transparentAlpha = 0; + pConfigs[i].transparentIndex = 0; + i++; + } + break; + case 32: + numConfigs = 1; + if (R128_USE_ACCUM) numConfigs *= 2; + if (R128_USE_STENCIL) numConfigs *= 2; + + if (!(pConfigs + = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig), + numConfigs))) { + return FALSE; + } + if (!(pR128Configs + = (R128ConfigPrivPtr)xnfcalloc(sizeof(R128ConfigPrivRec), + numConfigs))) { + xfree(pConfigs); + return FALSE; + } + if (!(pR128ConfigPtrs + = (R128ConfigPrivPtr*)xnfcalloc(sizeof(R128ConfigPrivPtr), + numConfigs))) { + xfree(pConfigs); + xfree(pR128Configs); + return FALSE; + } + + i = 0; + for (accum = 0; accum <= R128_USE_ACCUM; accum++) { + for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) { + pR128ConfigPtrs[i] = &pR128Configs[i]; + + pConfigs[i].vid = -1; + pConfigs[i].class = -1; + pConfigs[i].rgba = TRUE; + pConfigs[i].redSize = 8; + pConfigs[i].greenSize = 8; + pConfigs[i].blueSize = 8; + pConfigs[i].redMask = 0x00FF0000; + pConfigs[i].greenMask = 0x0000FF00; + pConfigs[i].blueMask = 0x000000FF; + + pConfigs[i].alphaMask = 0; + if (accum) { /* Simulated in software */ + pConfigs[i].accumRedSize = 16; + pConfigs[i].accumGreenSize = 16; + pConfigs[i].accumBlueSize = 16; + pConfigs[i].accumAlphaSize = 0; + } else { + pConfigs[i].accumRedSize = 0; + pConfigs[i].accumGreenSize = 0; + pConfigs[i].accumBlueSize = 0; + pConfigs[i].accumAlphaSize = 0; + } + pConfigs[i].doubleBuffer = TRUE; + pConfigs[i].stereo = FALSE; + pConfigs[i].bufferSize = 24; + if (stencil) { + pConfigs[i].depthSize = 24; + pConfigs[i].stencilSize = 8; + } else { + pConfigs[i].depthSize = 32; + pConfigs[i].stencilSize = 0; + } + pConfigs[i].auxBuffers = 0; + pConfigs[i].level = 0; + if (accum) + pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; + else + pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].transparentPixel = 0; + pConfigs[i].transparentRed = 0; + pConfigs[i].transparentGreen = 0; + pConfigs[i].transparentBlue = 0; + pConfigs[i].transparentAlpha = 0; + pConfigs[i].transparentIndex = 0; + i++; + } + } + break; + } + + pR128->numVisualConfigs = numConfigs; + pR128->pVisualConfigs = pConfigs; + pR128->pVisualConfigsPriv = pR128Configs; + GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pR128ConfigPtrs); + return TRUE; +} + +/* Create the Rage 128-specific context information */ +static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual, + drmContext hwContext, void *pVisualConfigPriv, + DRIContextType contextStore) +{ + /* Nothing yet */ + return TRUE; +} + +/* Destroy the Rage 128-specific context information */ +static void R128DestroyContext(ScreenPtr pScreen, drmContext hwContext, + DRIContextType contextStore) +{ + /* Nothing yet */ +} + +/* Called when the X server is woken up to allow the last client's + context to be saved and the X server's context to be loaded. This is + not necessary for the Rage 128 since the client detects when it's + context is not currently loaded and then load's it itself. Since the + registers to start and stop the CCE are privileged, only the X server + can start/stop the engine. */ +static void R128EnterServer(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + + if (pR128->accel) pR128->accel->NeedToSync = TRUE; + +#if 1 + if (!pR128->CCE2D) R128CCEStop(pScrn); +#else + if (pR128->CCE2D) R128CCEWaitForIdle(pScrn); + else R128CCEStop(pScrn); +#endif +} + +/* Called when the X server goes to sleep to allow the X server's + context to be saved and the last client's context to be loaded. This + is not necessary for the Rage 128 since the client detects when it's + context is not currently loaded and then load's it itself. Since the + registers to start and stop the CCE are privileged, only the X server + can start/stop the engine. */ +static void R128LeaveServer(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + +#if 1 + if (!pR128->CCE2D) R128CCEStart(pScrn); +#else + if (pR128->CCE2D) R128CCEWaitForIdle(pScrn); + else R128CCEStart(pScrn); +#endif +} + +/* Contexts can be swapped by the X server if necessary. This callback + is currently only used to perform any functions necessary when + entering or leaving the X server, and in the future might not be + necessary. */ +static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, + DRIContextType oldContextType, void *oldContext, + DRIContextType newContextType, void *newContext) +{ + if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) && + (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */ + R128EnterServer(pScreen); + } + if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && + (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ + R128LeaveServer(pScreen); + } +} + +/* Initialize the state of the back and depth buffers. */ +static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) +{ + /* FIXME: This routine needs to have acceleration turned on */ + ScreenPtr pScreen = pWin->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + BoxPtr pbox; + int nbox; + int depth; + + /* FIXME: Use accel when CCE 2D code is written */ + if (pR128->CCE2D) return; + + /* FIXME: This should be based on the __GLXvisualConfig info */ + switch (pScrn->bitsPerPixel) { + case 8: depth = 0x000000ff; break; + case 16: depth = 0x0000ffff; break; + case 24: depth = 0x00ffffff; break; + case 32: depth = 0xffffffff; break; + default: depth = 0x00000000; break; + } + + /* FIXME: Copy XAAPaintWindow() and use REGION_TRANSLATE() */ + /* FIXME: Only initialize the back and depth buffers for contexts + that request them */ + + pbox = REGION_RECTS(prgn); + nbox = REGION_NUM_RECTS(prgn); + + (*pR128->accel->SetupForSolidFill)(pScrn, 0, GXcopy, -1); + for (; nbox; nbox--, pbox++) { + (*pR128->accel->SubsequentSolidFillRect)(pScrn, + pbox->x1 + pR128->fbX, + pbox->y1 + pR128->fbY, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + (*pR128->accel->SubsequentSolidFillRect)(pScrn, + pbox->x1 + pR128->backX, + pbox->y1 + pR128->backY, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + } + + (*pR128->accel->SetupForSolidFill)(pScrn, depth, GXcopy, -1); + for (; nbox; nbox--, pbox++) + (*pR128->accel->SubsequentSolidFillRect)(pScrn, + pbox->x1 + pR128->depthX, + pbox->y1 + pR128->depthY, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + + pR128->accel->NeedToSync = TRUE; +} + +/* Copy the back and depth buffers when the X server moves a window. */ +static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc, CARD32 index) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + + /* FIXME: This routine needs to have acceleration turned on */ + /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */ + /* FIXME: Only initialize the back and depth buffers for contexts + that request them */ + + /* FIXME: Use accel when CCE 2D code is written */ + if (pR128->CCE2D) return; +} + +/* Initialize the AGP state. Request memory for use in AGP space, and + initialize the Rage 128 registers to point to that memory. */ +static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen) +{ + unsigned char *R128MMIO = pR128->MMIO; + unsigned long mode; + unsigned int vendor, device; + int ret; + unsigned long cntl; + int s, l; + int flags; + + if (drmAgpAcquire(pR128->drmFD) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not available\n"); + return FALSE; + } + + /* Modify the mode if the default mode is + not appropriate for this particular + combination of graphics card and AGP + chipset. */ + + mode = drmAgpGetMode(pR128->drmFD); /* Default mode */ + vendor = drmAgpVendorId(pR128->drmFD); + device = drmAgpDeviceId(pR128->drmFD); + + mode &= ~R128_AGP_MODE_MASK; + switch (pR128->agpMode) { + case 2: mode |= R128_AGP_2X_MODE; + case 1: default: mode |= R128_AGP_1X_MODE; + } + + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", + mode, vendor, device, + pR128->PciInfo->vendor, + pR128->PciInfo->chipType); + + if (drmAgpEnable(pR128->drmFD, mode) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n"); + drmAgpRelease(pR128->drmFD); + return FALSE; + } + + pR128->agpOffset = 0; + + if ((ret = drmAgpAlloc(pR128->drmFD, pR128->agpSize*1024*1024, 0, NULL, + &pR128->agpMemHandle)) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret); + drmAgpRelease(pR128->drmFD); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] %d kB allocated with handle 0x%08x\n", + pR128->agpSize*1024, pR128->agpMemHandle); + + if (drmAgpBind(pR128->drmFD, pR128->agpMemHandle, pR128->agpOffset) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n"); + drmAgpFree(pR128->drmFD, pR128->agpMemHandle); + drmAgpRelease(pR128->drmFD); + return FALSE; + } + + /* Initialize the CCE ring buffer data */ + pR128->ringStart = pR128->agpOffset; + pR128->ringMapSize = pR128->ringSize*1024*1024 + 4096; + pR128->ringSizeLog2QW = R128MinBits(pR128->ringSize*1024*1024/8) - 1; + + pR128->ringReadOffset = pR128->ringStart + pR128->ringMapSize; + pR128->ringReadMapSize = 4096; + + /* Reserve space for the vertex buffer */ + pR128->vbStart = pR128->ringReadOffset + pR128->ringReadMapSize; + pR128->vbMapSize = pR128->vbSize*1024*1024; + + /* Reserve space for the indirect buffer */ + pR128->indStart = pR128->vbStart + pR128->vbMapSize; + pR128->indMapSize = pR128->indSize*1024*1024; + + /* Reserve the rest for AGP textures */ + pR128->agpTexStart = pR128->indStart + pR128->indMapSize; + s = (pR128->agpSize*1024*1024 - pR128->agpTexStart); + l = R128MinBits((s-1) / R128_NR_TEX_REGIONS); + if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; + pR128->agpTexMapSize = (s >> l) << l; + pR128->log2AGPTexGran = l; + + if (pR128->CCESecure) flags = DRM_READ_ONLY; + else flags = 0; + + if (drmAddMap(pR128->drmFD, pR128->ringStart, pR128->ringMapSize, + DRM_AGP, flags, &pR128->ringHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not add ring mapping\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] ring handle = 0x%08lx\n", pR128->ringHandle); + + if (drmMap(pR128->drmFD, pR128->ringHandle, pR128->ringMapSize, + (drmAddressPtr)&pR128->ring) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] Ring mapped at 0x%08lx\n", + (unsigned long)pR128->ring); + + if (drmAddMap(pR128->drmFD, pR128->ringReadOffset, pR128->ringReadMapSize, + DRM_AGP, flags, &pR128->ringReadPtrHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not add ring read ptr mapping\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] ring read ptr handle = 0x%08lx\n", + pR128->ringReadPtrHandle); + + if (drmMap(pR128->drmFD, pR128->ringReadPtrHandle, pR128->ringReadMapSize, + (drmAddressPtr)&pR128->ringReadPtr) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not map ring read ptr\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] Ring read ptr mapped at 0x%08lx\n", + (unsigned long)pR128->ringReadPtr); + + if (drmAddMap(pR128->drmFD, pR128->vbStart, pR128->vbMapSize, + DRM_AGP, 0, &pR128->vbHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not add vertex buffers mapping\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] vertex buffers handle = 0x%08lx\n", pR128->vbHandle); + + if (drmMap(pR128->drmFD, pR128->vbHandle, pR128->vbMapSize, + (drmAddressPtr)&pR128->vb) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not map vertex buffers\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] Vertex buffers mapped at 0x%08lx\n", + (unsigned long)pR128->vb); + + if (drmAddMap(pR128->drmFD, pR128->indStart, pR128->indMapSize, + DRM_AGP, flags, &pR128->indHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not add indirect buffers mapping\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] indirect buffers handle = 0x%08lx\n", pR128->indHandle); + + if (drmMap(pR128->drmFD, pR128->indHandle, pR128->indMapSize, + (drmAddressPtr)&pR128->ind) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not map indirect buffers\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] Indirect buffers mapped at 0x%08lx\n", + (unsigned long)pR128->ind); + + if (drmAddMap(pR128->drmFD, pR128->agpTexStart, pR128->agpTexMapSize, + DRM_AGP, 0, &pR128->agpTexHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not add AGP texture map mapping\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] AGP texture map handle = 0x%08lx\n", + pR128->agpTexHandle); + + if (drmMap(pR128->drmFD, pR128->agpTexHandle, pR128->agpTexMapSize, + (drmAddressPtr)&pR128->agpTex) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Could not map AGP texture map\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] AGP Texture map mapped at 0x%08lx\n", + (unsigned long)pR128->agpTex); + + /* Initialize Rage 128's AGP registers */ + cntl = INREG(R128_AGP_CNTL); + cntl &= ~R128_AGP_APER_SIZE_MASK; + switch (pR128->agpSize) { + case 256: cntl |= R128_AGP_APER_SIZE_256MB; break; + case 128: cntl |= R128_AGP_APER_SIZE_128MB; break; + case 64: cntl |= R128_AGP_APER_SIZE_64MB; break; + case 32: cntl |= R128_AGP_APER_SIZE_32MB; break; + case 16: cntl |= R128_AGP_APER_SIZE_16MB; break; + case 8: cntl |= R128_AGP_APER_SIZE_8MB; break; + case 4: cntl |= R128_AGP_APER_SIZE_4MB; break; + default: + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Illegal aperture size %d kB\n", + pR128->agpSize*1024); + return FALSE; + } + OUTREG(R128_AGP_BASE, pR128->ringHandle); /* Ring buf is at AGP offset 0 */ + OUTREG(R128_AGP_CNTL, cntl); + + return TRUE; +} + +/* Add a map for the MMIO registers that will be accessed by any + DRI-based clients. */ +static Bool R128DRIMapInit(R128InfoPtr pR128, ScreenPtr pScreen) +{ + int flags; + + if (pR128->CCESecure) flags = DRM_READ_ONLY; + else flags = 0; + + /* Map registers */ + pR128->registerSize = R128_MMIOSIZE; + if (drmAddMap(pR128->drmFD, pR128->MMIOAddr, pR128->registerSize, + DRM_REGISTERS, flags, &pR128->registerHandle) < 0) { + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[drm] register handle = 0x%08lx\n", pR128->registerHandle); + + return TRUE; +} + +/* Initialize the ring buffer state for use in the X server and any + DRI-based clients. */ +static void R128DRICCEInitRingBuffer(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + unsigned long addr; + + /* FIXME: When we use the CCE for the X server, we should move this + function (and the support functions above) to r128_accel.c */ + + /* The manual (p. 2) says this address is + in "VM space". This means it's an + offset from the start of AGP space. */ + OUTREG(R128_PM4_BUFFER_OFFSET, info->ringStart | 0x02000000); + + OUTREG(R128_PM4_BUFFER_DL_WPTR, 0); + OUTREG(R128_PM4_BUFFER_DL_RPTR, 0); + + /* DL_RPTR_ADDR is a physical address. + This should be in the SAREA. */ + *(volatile long unsigned *)(info->ringReadPtr) = 0; + OUTREG(R128_PM4_BUFFER_DL_RPTR_ADDR, (info->ringReadPtrHandle)); + + /* Set watermark control */ + OUTREG(R128_PM4_BUFFER_WM_CNTL, + ((R128_WATERMARK_L/4) << R128_WMA_SHIFT) + | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT) + | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT) + | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT)); + + addr = INREG(R128_PM4_BUFFER_ADDR); /* Force read. Why? Because it's + in the examples... */ + +#if 0 + R128CCEWaitForIdle(pScrn); +#endif + + /* Turn on bus mastering */ + info->BusCntl &= ~R128_BUS_MASTER_DIS; + OUTREGP(R128_BUS_CNTL, 0, ~R128_BUS_MASTER_DIS); +} + +/* Initialize the kernel data structures. */ +static int R128DRIKernelInit(R128InfoPtr pR128, ScreenPtr pScreen) +{ + drmR128Init drmInfo; + + drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); + drmInfo.is_pci = pR128->IsPCI; + drmInfo.cce_mode = pR128->CCEMode; + drmInfo.cce_fifo_size = pR128->CCEFifoSize; + drmInfo.cce_secure = pR128->CCESecure; + drmInfo.ring_size = pR128->ringSize*1024*1024; + drmInfo.usec_timeout = pR128->CCEusecTimeout; + + drmInfo.fb_offset = pR128->LinearAddr; + drmInfo.agp_ring_offset = pR128->ringHandle; + drmInfo.agp_read_ptr_offset = pR128->ringReadPtrHandle; + drmInfo.agp_vertbufs_offset = pR128->vbHandle; + drmInfo.agp_indbufs_offset = pR128->indHandle; + drmInfo.agp_textures_offset = pR128->agpTexHandle; + drmInfo.mmio_offset = pR128->registerHandle; + + if (drmR128InitCCE(pR128->drmFD, &drmInfo) < 0) return FALSE; + + return TRUE; +} + +/* Add a map for the vertex buffers that will be accessed by any + DRI-based clients. */ +static Bool R128DRIBufInit(R128InfoPtr pR128, ScreenPtr pScreen) +{ + /* Initialize vertex buffers */ + if ((pR128->vbNumBufs = drmAddBufs(pR128->drmFD, + pR128->vbMapSize / pR128->vbBufSize, + pR128->vbBufSize, + DRM_AGP_BUFFER, + pR128->vbStart)) <= 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Could not create vertex buffers list\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[drm] Added %d %d byte vertex buffers\n", + pR128->vbNumBufs, pR128->vbBufSize); + + if (drmMarkBufs(pR128->drmFD, 0.133333, 0.266666)) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Failed to mark vertex buffers list\n"); + return FALSE; + } + + if (!(pR128->vbBufs = drmMapBufs(pR128->drmFD))) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Failed to map vertex buffers list\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[drm] Mapped %d vertex buffers\n", + pR128->vbBufs->count); + + return TRUE; +} + +/* Load the microcode for the CCE */ +static void R128DRILoadMicrocode(ScrnInfoPtr pScrn) +{ + unsigned char *R128MMIO = R128PTR(pScrn)->MMIO; + int i; + unsigned long R128Microcode[] = { + /* CCE microcode (from ATI) */ + 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, 1617039951, + 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, 599558925, 0, 589505315, 0, + 596487092, 0, 589505315, 1, 11544576, 1, 206848, 1, 311296, 1, 198656, 2, + 912273422, 11, 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, + 28, 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, 30, 1, + 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, 1, 15630, 1, 51200, + 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, 15717, 1, 15718, 2, 43, 1, + 15936948, 1, 570480831, 1, 14715071, 12, 322123831, 1, 33953125, 12, 55, 1, + 33559908, 1, 15718, 2, 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, + 509952, 1, 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1, + 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, 15975928, 1, + 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, 268449859, 2, 10307, 12, + 176, 1, 15734, 1, 15735, 1, 15630, 1, 15631, 1, 5253120, 6, 3145810, 16, + 2150645232U, 1, 15864, 2, 82, 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, + 1, 7817, 1, 15729, 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, + 1, 16008, 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0, + 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, 180224, 1, + 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, 114880, 14, 125, 12, + 206975, 1, 33559995, 12, 198784, 0, 33570236, 1, 15803, 0, 15804, 3, + 294912, 1, 294912, 3, 442370, 1, 11544576, 0, 811612160, 1, 12593152, 1, + 11536384, 1, 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, + 14793, 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1, + 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, 114880, 14, + 159, 12, 198784, 1, 1109409213, 12, 198783, 1, 1107312059, 12, 198784, 1, + 1109409212, 2, 162, 1, 1075854781, 1, 1073757627, 1, 1075854780, 1, 540672, + 1, 10485760, 6, 3145894, 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, + 0, 0, 256, 14, 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, + 1, 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, 33560360, 1, + 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, 409611, 9, 188, 0, + 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }; + + R128WaitForIdle(pScrn); + + OUTREG(R128_PM4_MICROCODE_ADDR, 0); + for (i = 0; i < 256; i += 1) { + OUTREG(R128_PM4_MICROCODE_DATAH, R128Microcode[i*2]); + OUTREG(R128_PM4_MICROCODE_DATAL, R128Microcode[i*2 + 1]); + } +} + +/* Initialize the CCE state, and start the CCE (if used by the X server) */ +static void R128DRICCEInit(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + /* CCEMode is initialized in r128_driver.c */ + switch (info->CCEMode) { + case R128_PM4_NONPM4: info->CCEFifoSize = 0; break; + case R128_PM4_192PIO: info->CCEFifoSize = 192; break; + case R128_PM4_192BM: info->CCEFifoSize = 192; break; + case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break; + case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break; + case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break; + } + + if (info->CCE2D) { + /* Make sure the CCE is on for the X server */ + R128CCEStart(pScrn); + } else { + /* Make sure the CCE is off for the X server */ + OUTREG(R128_PM4_MICRO_CNTL, 0); + OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4); + } +} + +/* Initialize the screen-specific data structures for the DRI and the + Rage 128. This is the main entry point to the device-specific + initialization code. It calls device-independent DRI functions to + create the DRI data structures and initialize the DRI state. */ +Bool R128DRIScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + DRIInfoPtr pDRIInfo; + R128DRIPtr pR128DRI; + + switch (pR128->pixel_code) { + case 8: + /* These modes are not supported (yet). */ + case 15: + case 24: + return FALSE; + + /* Only 16 and 32 color depths are supports currently. */ + case 16: + case 32: + break; + } + + /* Create the DRI data structure, and fill it in before calling the + DRIScreenInit(). */ + if (!(pDRIInfo = DRICreateInfoRec())) return FALSE; + + pR128->pDRIInfo = pDRIInfo; + pDRIInfo->drmDriverName = R128_NAME; + pDRIInfo->clientDriverName = R128_NAME; + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, + "PCI:%d:%d:%d", + pR128->PciInfo->bus, + pR128->PciInfo->device, + pR128->PciInfo->func); + pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR; + pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR; + pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH; + pDRIInfo->frameBufferPhysicalAddress = pR128->LinearAddr; + pDRIInfo->frameBufferSize = pR128->FbMapSize; + pDRIInfo->frameBufferStride = (pScrn->displayWidth + * pR128->pixel_bytes); + pDRIInfo->ddxDrawableTableEntry = R128_MAX_DRAWABLES; + pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES + < R128_MAX_DRAWABLES + ? SAREA_MAX_DRAWABLES + : R128_MAX_DRAWABLES); + +#ifdef NOT_DONE + /* FIXME: Need to extend DRI protocol to pass this size back to + * client for SAREA mapping that includes a device private record + */ + pDRIInfo->SAREASize = + ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ + /* + shared memory device private rec */ +#else + /* For now the mapping works by using a fixed size defined + * in the SAREA header + */ + if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) { + ErrorF("Data does not fit in SAREA\n"); + return FALSE; + } + pDRIInfo->SAREASize = SAREA_MAX; +#endif + + if (!(pR128DRI = (R128DRIPtr)xnfcalloc(sizeof(R128DRIRec),1))) { + DRIDestroyInfoRec(pR128->pDRIInfo); + pR128->pDRIInfo = NULL; + return FALSE; + } + pDRIInfo->devPrivate = pR128DRI; + pDRIInfo->devPrivateSize = sizeof(R128DRIRec); + pDRIInfo->contextSize = sizeof(R128DRIContextRec); + + pDRIInfo->CreateContext = R128CreateContext; + pDRIInfo->DestroyContext = R128DestroyContext; + pDRIInfo->SwapContext = R128DRISwapContext; + pDRIInfo->InitBuffers = R128DRIInitBuffers; + pDRIInfo->MoveBuffers = R128DRIMoveBuffers; + pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + + if (!DRIScreenInit(pScreen, pDRIInfo, &pR128->drmFD)) { + xfree(pDRIInfo->devPrivate); + pDRIInfo->devPrivate = NULL; + DRIDestroyInfoRec(pDRIInfo); + pDRIInfo = NULL; + return FALSE; + } + + /* Initialize AGP */ + if (!pR128->IsPCI && !R128DRIAgpInit(pR128, pScreen)) { + R128DRICloseScreen(pScreen); + return FALSE; + } + + /* DRIScreenInit doesn't add all the + common mappings. Add additional + mappings here. */ + if (!R128DRIMapInit(pR128, pScreen)) { + R128DRICloseScreen(pScreen); + return FALSE; + } + + /* Initialize the ring buffer */ + if (!pR128->IsPCI) R128DRICCEInitRingBuffer(pScrn); + + /* Initialize the kernel data structures */ + if (!R128DRIKernelInit(pR128, pScreen)) { + R128DRICloseScreen(pScreen); + return FALSE; + } + + /* Initialize vertex buffers list */ + if (!pR128->IsPCI && !R128DRIBufInit(pR128, pScreen)) { + R128DRICloseScreen(pScreen); + return FALSE; + } + + /* FIXME: When are these mappings unmapped? */ + + if (!R128InitVisualConfigs(pScreen)) { + R128DRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Visual configs initialized\n"); + + /* Load the CCE Microcode */ + R128DRILoadMicrocode(pScrn); + + /* Reset the Graphics Engine */ + R128EngineReset(pScrn); + + return TRUE; +} + +/* Finish initializing the device-dependent DRI state, and call + DRIFinishScreenInit() to complete the device-independent DRI + initialization. */ +Bool R128DRIFinishScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + R128SAREAPrivPtr pSAREAPriv; + R128DRIPtr pR128DRI; + + /* Init and start the CCE */ + R128DRICCEInit(pScrn); + + pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen); + memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); + + pR128->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; + /* pR128->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */ + + pR128DRI = (R128DRIPtr)pR128->pDRIInfo->devPrivate; + pR128DRI->registerHandle = pR128->registerHandle; + pR128DRI->registerSize = pR128->registerSize; + + pR128DRI->ringHandle = pR128->ringHandle; + pR128DRI->ringMapSize = pR128->ringMapSize; + pR128DRI->ringSize = pR128->ringSize*1024*1024; + + pR128DRI->ringReadPtrHandle = pR128->ringReadPtrHandle; + pR128DRI->ringReadMapSize = pR128->ringReadMapSize; + + pR128DRI->vbHandle = pR128->vbHandle; + pR128DRI->vbMapSize = pR128->vbMapSize; + pR128DRI->vbOffset = pR128->vbStart; + pR128DRI->vbBufSize = pR128->vbBufSize; + + pR128DRI->indHandle = pR128->indHandle; + pR128DRI->indMapSize = pR128->indMapSize; + + pR128DRI->agpTexHandle = pR128->agpTexHandle; + pR128DRI->agpTexMapSize = pR128->agpTexMapSize; + pR128DRI->log2AGPTexGran = pR128->log2AGPTexGran; + pR128DRI->agpTexOffset = pR128->agpTexStart; + + pR128DRI->deviceID = pR128->Chipset; + pR128DRI->width = pScrn->virtualX; + pR128DRI->height = pScrn->virtualY; + pR128DRI->depth = pScrn->depth; + pR128DRI->bpp = pScrn->bitsPerPixel; + + pR128DRI->fbX = pR128->fbX; + pR128DRI->fbY = pR128->fbY; + pR128DRI->backX = pR128->backX; + pR128DRI->backY = pR128->backY; + pR128DRI->depthX = pR128->depthX; + pR128DRI->depthY = pR128->depthY; + pR128DRI->textureX = pR128->textureX; + pR128DRI->textureY = pR128->textureY; + pR128DRI->textureSize = pR128->textureSize; + pR128DRI->log2TexGran = pR128->log2TexGran; + + pR128DRI->IsPCI = pR128->IsPCI; + + pR128DRI->CCEMode = pR128->CCEMode; + pR128DRI->CCEFifoSize = pR128->CCEFifoSize; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%08lx %d\n", + pR128DRI->registerHandle, pR128DRI->registerSize); + return DRIFinishScreenInit(pScreen); +} + +/* The screen is being closed, so clean up any state and free any + resources used by the DRI. */ +void R128DRICloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + + /* Stop the CCE if it is still in use */ + if (pR128->CCE2D) R128CCEStop(pScrn); + + /* De-allocate vertex buffers */ + if (pR128->vbBufs) { + drmUnmapBufs(pR128->vbBufs); + pR128->vbBufs = NULL; + } + + /* De-allocate all kernel resources */ + drmR128CleanupCCE(pR128->drmFD); + + /* De-allocate all AGP resources */ + if (pR128->agpTex) { + drmUnmap(pR128->agpTex, pR128->agpTexMapSize); + pR128->agpTex = NULL; + } + if (pR128->ind) { + drmUnmap(pR128->ind, pR128->indMapSize); + pR128->ind = NULL; + } + if (pR128->vb) { + drmUnmap(pR128->vb, pR128->vbMapSize); + pR128->vb = NULL; + } + if (pR128->ringReadPtr) { + drmUnmap(pR128->ringReadPtr, pR128->ringReadMapSize); + pR128->ringReadPtr = NULL; + } + if (pR128->ring) { + drmUnmap(pR128->ring, pR128->ringMapSize); + pR128->ring = NULL; + } + if (pR128->agpMemHandle) { + drmAgpUnbind(pR128->drmFD, pR128->agpMemHandle); + drmAgpFree(pR128->drmFD, pR128->agpMemHandle); + pR128->agpMemHandle = 0; + drmAgpRelease(pR128->drmFD); + } + + /* De-allocate all DRI resources */ + DRICloseScreen(pScreen); + + /* De-allocate all DRI data structures */ + if (pR128->pDRIInfo) { + if (pR128->pDRIInfo->devPrivate) { + xfree(pR128->pDRIInfo->devPrivate); + pR128->pDRIInfo->devPrivate = NULL; + } + DRIDestroyInfoRec(pR128->pDRIInfo); + pR128->pDRIInfo = NULL; + } + if (pR128->pVisualConfigs) { + xfree(pR128->pVisualConfigs); + pR128->pVisualConfigs = NULL; + } + if (pR128->pVisualConfigsPriv) { + xfree(pR128->pVisualConfigsPriv); + pR128->pVisualConfigsPriv = NULL; + } +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h new file mode 100644 index 000000000..533aadb2f --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h @@ -0,0 +1,116 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Rickard E. Faith <faith@precisioninsight.com> + * + */ + +#ifndef _R128_DRI_ +#define _R128_DRI_ + +#include <xf86drm.h> + +/* DRI Driver defaults */ +#define R128_DEFAULT_CCE_PIO_MODE R128_PM4_64PIO_64VCBM_64INDBM +#define R128_DEFAULT_CCE_BM_MODE R128_PM4_64BM_64VCBM_64INDBM +#define R128_DEFAULT_AGP_MODE 2 +#define R128_DEFAULT_AGP_SIZE 8 /* MB (must be a power of 2 and > 4MB) */ +#define R128_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */ +#define R128_DEFAULT_VB_SIZE 1 /* MB (must be page aligned) */ +#define R128_DEFAULT_IND_SIZE 1 /* MB (must be page aligned) */ +#define R128_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */ + +#define R128_DEFAULT_VB_BUF_SIZE 16384 /* bytes */ +#define R128_DEFAULT_CCE_TIMEOUT 10000 /* usecs */ + +#define R128_AGP_MAX_MODE 2 + +#define R128CCE_USE_RING_BUFFER(m) \ +(((m) == R128_PM4_192BM) || \ + ((m) == R128_PM4_128BM_64INDBM) || \ + ((m) == R128_PM4_64BM_128INDBM) || \ + ((m) == R128_PM4_64BM_64VCBM_64INDBM)) + +typedef struct { + /* MMIO register data */ + drmHandle registerHandle; + drmSize registerSize; + + /* CCE ring buffer data */ + drmHandle ringHandle; + drmSize ringMapSize; + int ringSize; + + /* CCE ring read pointer data */ + drmHandle ringReadPtrHandle; + drmSize ringReadMapSize; + + /* CCE vertex buffer data */ + drmHandle vbHandle; + drmSize vbMapSize; + int vbOffset; + int vbBufSize; + + /* CCE indirect buffer data */ + drmHandle indHandle; + drmSize indMapSize; + + /* CCE AGP Texture data */ + drmHandle agpTexHandle; + drmSize agpTexMapSize; + int log2AGPTexGran; + int agpTexOffset; + + /* DRI screen private data */ + int deviceID; /* PCI device ID */ + int width; /* Width in pixels of display */ + int height; /* Height in scanlines of display */ + int depth; /* Depth of display (8, 15, 16, 24) */ + int bpp; /* Bit depth of display (8, 16, 24, 32) */ + + int fbX; /* Start of frame buffer */ + int fbY; + int backX; /* Start of shared back buffer */ + int backY; + int depthX; /* Start of shared depth buffer */ + int depthY; + int textureX; /* Start of texture data in frame buffer */ + int textureY; + int textureSize; + int log2TexGran; + + int IsPCI; /* Current card is a PCI card */ + + int CCEMode; /* CCE mode that server/clients use */ + int CCEFifoSize; /* Size of the CCE command FIFO */ +} R128DRIRec, *R128DRIPtr; + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h new file mode 100644 index 000000000..acec5e269 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h @@ -0,0 +1,54 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Rickard E. Faith <faith@precisioninsight.com> + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_DRIPRIV_H_ +#define _R128_DRIPRIV_H_ + +#define R128_MAX_DRAWABLES 256 + +extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, + void **configprivs); + +typedef struct { + /* Nothing here yet */ + int dummy; +} R128ConfigPrivRec, *R128ConfigPrivPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} R128DRIContextRec, *R128DRIContextPtr; + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c index b5da4cb6e..f30d86aa8 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c @@ -1,8 +1,8 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c,v 1.26 2000/03/06 23:17:44 martin Exp $ */ /************************************************************************** -Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -107,6 +107,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* VESA support */ #include "vbe.h" + /* DRI support */ +#ifdef XF86DRI +#include "GL/glxint.h" +#include "xf86drm.h" +#include "sarea.h" +#define _XF86DRI_SERVER_ +#include "xf86dri.h" +#include "dri.h" +#include "r128_dri.h" +#include "r128_dripriv.h" +#include "r128_sarea.h" +#endif + /* Driver data structures */ #include "r128.h" #include "r128_reg.h" @@ -176,17 +189,41 @@ typedef enum { OPTION_HW_CURSOR, OPTION_DAC_6BIT, OPTION_DAC_8BIT, +#ifdef XF86DRI + OPTION_IS_PCI, + OPTION_CCE_PIO, + OPTION_NO_SECURITY, + OPTION_USEC_TIMEOUT, + OPTION_AGP_MODE, + OPTION_AGP_SIZE, + OPTION_RING_SIZE, + OPTION_VERT_SIZE, + OPTION_VBUF_SIZE, + OPTION_USE_CCE_2D, +#endif OPTION_FBDEV } R128Opts; static OptionInfoRec R128Options[] = { - { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, TRUE }, - { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, - { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, TRUE }, + { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, +#ifdef XF86DRI + { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CCE_PIO, "CCEPIOMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NO_SECURITY, "CCENoSecurity", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_USEC_TIMEOUT, "CCEusecTimeout", OPTV_INTEGER, {0}, FALSE }, + { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, + { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_VERT_SIZE, "VBListSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_VBUF_SIZE, "VBSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_USE_CCE_2D, "UseCCEfor2D", OPTV_BOOLEAN, {0}, FALSE }, +#endif + { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } }; R128RAMRec R128RAM[] = { /* Memory Specifications @@ -299,6 +336,38 @@ static const char *ramdacSymbols[] = { NULL }; +#ifdef XF86DRI +static const char *drmSymbols[] = { + "drmAddBufs", + "drmAddMap", + "drmAvailable", + "drmCtlAddCommand", + "drmCtlInstHandler", + "drmGetInterruptFromBusID", + "drmMapBufs", + "drmMarkBufs", + "drmUnmapBufs", + NULL +}; + +static const char *driSymbols[] = { + "DRIGetDrawableIndex", + "DRIFinishScreenInit", + "DRIDestroyInfoRec", + "DRICloseScreen", + "DRIDestroyInfoRec", + "DRIScreenInit", + "DRIDestroyInfoRec", + "DRICreateInfoRec", + "DRILock", + "DRIUnlock", + "DRIGetSAREAPrivate", + "DRIGetContext", + "GlxSetVisualConfigs", + NULL +}; +#endif + static MODULESETUPPROTO(R128Setup); static XF86ModuleVersionInfo R128VersRec = @@ -347,6 +416,10 @@ static pointer R128Setup(pointer module, pointer opts, int *errmaj, xaaSymbols, xf8_32bppSymbols, ramdacSymbols, +#ifdef XF86DRI + drmSymbols, + driSymbols, +#endif fbdevHWSymbols, vbeSymbols, 0 /* ddcsymbols */, @@ -518,7 +591,7 @@ static void R128Unblank(ScrnInfoPtr pScrn) } /* Compute log base 2 of val. */ -static int R128MinBits(int val) +int R128MinBits(int val) { int bits; @@ -779,6 +852,7 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) int offset = 0; /* RAM Type */ MessageType from; unsigned char *R128MMIO; + /* Chipset */ from = X_PROBED; if (dev->chipset && *dev->chipset) { @@ -876,7 +950,7 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) switch (info->MemCntl & 0x3) { case 0: /* SDR SGRAM 1:1 */ switch (info->Chipset) { - case PCI_CHIP_RAGE128RE: + case PCI_CHIP_RAGE128RE: case PCI_CHIP_RAGE128RF: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */ case PCI_CHIP_RAGE128RK: case PCI_CHIP_RAGE128RL: @@ -895,12 +969,28 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) pScrn->videoRam); from = X_CONFIG; pScrn->videoRam = dev->videoRam; - } + } pScrn->videoRam &= ~1023; info->FbMapSize = pScrn->videoRam * 1024; xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name); +#ifdef XF86DRI + /* AGP/PCI */ + if (xf86ReturnOptValBool(R128Options, OPTION_IS_PCI, FALSE)) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n"); + } else { + switch (info->Chipset) { + case PCI_CHIP_RAGE128RE: + case PCI_CHIP_RAGE128RK: info->IsPCI = TRUE; break; + case PCI_CHIP_RAGE128RF: + case PCI_CHIP_RAGE128RL: + case PCI_CHIP_RAGE128PF: + default: info->IsPCI = FALSE; break; + } + } +#endif return TRUE; } @@ -1053,6 +1143,143 @@ static Bool R128PreInitInt10(ScrnInfoPtr pScrn) return TRUE; } +#ifdef XF86DRI +static Bool R128PreInitDRI(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + + if (info->IsPCI) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CCE in PIO mode\n"); + info->CCEMode = R128_DEFAULT_CCE_PIO_MODE; + } else if (xf86ReturnOptValBool(R128Options, OPTION_CCE_PIO, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CCE in PIO mode\n"); + info->CCEMode = R128_DEFAULT_CCE_PIO_MODE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CCE in BM mode\n"); + info->CCEMode = R128_DEFAULT_CCE_BM_MODE; + } + + if (xf86ReturnOptValBool(R128Options, OPTION_USE_CCE_2D, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using CCE for 2D\n"); + info->CCE2D = TRUE; + } else { + info->CCE2D = FALSE; + } + + if (xf86ReturnOptValBool(R128Options, OPTION_NO_SECURITY, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "WARNING!!! CCE Security checks disabled!!! **********\n"); + info->CCESecure = FALSE; + } else { + info->CCESecure = TRUE; + } + + info->agpMode = R128_DEFAULT_AGP_MODE; + info->agpSize = R128_DEFAULT_AGP_SIZE; + info->ringSize = R128_DEFAULT_RING_SIZE; + info->vbSize = R128_DEFAULT_VB_SIZE; + info->indSize = R128_DEFAULT_IND_SIZE; + info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE; + + info->vbBufSize = R128_DEFAULT_VB_BUF_SIZE; + + info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT; + + if (!info->IsPCI) { + if (xf86GetOptValInteger(R128Options, + OPTION_AGP_MODE, &(info->agpMode))) { + if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal AGP Mode: %d\n", info->agpMode); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using AGP %dx mode\n", info->agpMode); + } + + if (xf86GetOptValInteger(R128Options, + OPTION_AGP_SIZE, (int *)&(info->agpSize))) { + switch (info->agpSize) { + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal AGP size: %d MB\n", info->agpSize); + return FALSE; + } + } + + if (xf86GetOptValInteger(R128Options, + OPTION_RING_SIZE, &(info->ringSize))) { + if (info->ringSize < 1 || info->ringSize >= info->agpSize) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal ring buffer size: %d MB\n", + info->ringSize); + return FALSE; + } + } + + if (xf86GetOptValInteger(R128Options, + OPTION_VERT_SIZE, &(info->vbSize))) { + if (info->vbSize < 1 || info->vbSize >= info->agpSize) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal vertex buffers list size: %d MB\n", + info->vbSize); + return FALSE; + } + } + + if (xf86GetOptValInteger(R128Options, + OPTION_VBUF_SIZE, &(info->vbBufSize))) { + int numBufs = info->vbSize*1024*1024/info->vbBufSize; + if (numBufs < 2 || numBufs > 512) { /* FIXME: 512 is arbitrary */ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal individual vertex buffer size: %d bytes\n", + info->vbBufSize); + return FALSE; + } + } + + if (info->ringSize + info->vbSize + info->indSize + info->agpTexSize > + info->agpSize) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Buffers are too big for requested AGP space\n"); + return FALSE; + } + + info->agpTexSize = info->agpSize - (info->ringSize + + info->vbSize + + info->indSize); + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using %d MB AGP aperture\n", info->agpSize); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using %d MB for the ring buffer\n", info->ringSize); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using %d MB for vertex buffers\n", info->vbSize); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using %d MB for indirect buffers\n", info->indSize); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using %d MB for AGP textures\n", info->agpTexSize); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using %d byte vertex buffers\n", info->vbBufSize); + } + + if (xf86GetOptValInteger(R128Options, OPTION_USEC_TIMEOUT, + &(info->CCEusecTimeout))) { + /* This option checked by the R128 DRM kernel module */ + } + + return TRUE; +} +#endif + extern xf86MonPtr ConfiguredMonitor; static void @@ -1152,6 +1379,10 @@ static Bool R128PreInit(ScrnInfoPtr pScrn, int flags) if (!R128PreInitAccel(pScrn)) goto fail; +#ifdef XF86DRI + if (!R128PreInitDRI(pScrn)) goto fail; +#endif + return TRUE; fail: @@ -1231,9 +1462,20 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset)); +#ifdef XF86DRI + /* Turn off the CCE for now. */ + info->CCEInUse = FALSE; +#endif + if (!R128MapMem(pScrn)) return FALSE; pScrn->fbOffset = 0; - +#ifdef XF86DRI + info->fbX = 0; + info->fbY = 0; +#endif + + info->PaletteSavedOnVT = FALSE; + R128Save(pScrn); if (info->FBDev) { if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; @@ -1251,6 +1493,18 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, pScrn->rgbBits, pScrn->defaultVisual)) return FALSE; +#ifdef XF86DRI + /* Setup DRI after visuals have been + established, but before cfbScreenInit is + called. cfbScreenInit will eventually + call the driver's InitGLXVisuals call + back. */ + if (!xf86ReturnOptValBool(R128Options, OPTION_NOACCEL, FALSE)) + info->directRenderingEnabled = R128DRIScreenInit(pScreen); + else + info->directRenderingEnabled = FALSE; +#endif + #ifdef USE_FB if (!fbScreenInit (pScreen, info->FB, pScrn->virtualX, pScrn->virtualY, @@ -1358,6 +1612,101 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, } } +#ifdef XF86DRI + /* Allocate frame buffer space for the + shared back and depth buffers as well + as for local textures. */ + if (info->directRenderingEnabled) { + FBAreaPtr fbarea; + int width_bytes = pScrn->displayWidth * info->pixel_bytes; + int maxy = info->FbMapSize / width_bytes; + int l; + + /* Allocate the shared back buffer */ + if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->virtualX, + pScrn->virtualY, + 32, NULL, NULL, NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved back buffer from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + + info->backX = fbarea->box.x1; + info->backY = fbarea->box.y1; + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n"); + info->backX = -1; + info->backY = -1; + } + + /* Allocate the shared depth buffer */ + if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->virtualX, + pScrn->virtualY, + 32, NULL, NULL, NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved depth buffer from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + + info->depthX = fbarea->box.x1; + info->depthY = fbarea->box.y1; + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n"); + info->depthX = -1; + info->depthY = -1; + } + + /* Allocate local texture space */ + if (((maxy - MemBox.y2 - 1) * width_bytes) > + (pScrn->virtualX * pScrn->virtualY * 2 * info->pixel_bytes)) { + info->textureX = 0; + info->textureY = MemBox.y2 + 1; + info->textureSize = (maxy - MemBox.y2 - 1) * width_bytes; + + l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS); + if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; + + info->log2TexGran = l; + info->textureSize = (info->textureSize >> l) << l; + + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved %d kb for textures: (%d,%d)-(%d,%d)\n", + info->textureSize/1024, + info->textureX, info->textureY, + pScrn->displayWidth, maxy); + } else if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->virtualX, + pScrn->virtualY * 2, + 32, + NULL, NULL, NULL))) { + info->textureX = fbarea->box.x1; + info->textureY = fbarea->box.y1; + info->textureSize = ((fbarea->box.y2 - fbarea->box.y1) * + (fbarea->box.x2 - fbarea->box.x1) * + info->pixel_bytes); + + l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS); + if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; + + info->log2TexGran = l; + info->textureSize = (info->textureSize >> l) << l; + + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved %d kb for textures: (%d,%d)-(%d,%d)\n", + info->textureSize/1024, + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, + "Unable to reserve texture space in frame buffer\n"); + info->textureX = -1; + info->textureY = -1; + } + } +#endif + /* Backing store setup */ miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); @@ -1453,6 +1802,21 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); +#ifdef XF86DRI + /* DRI finalization */ + if (info->directRenderingEnabled) { + /* Now that mi, cfb, drm and others have + done their thing, complete the DRI + setup. */ + info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen); + } + if (info->directRenderingEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n"); + } +#endif + return TRUE; } @@ -1473,7 +1837,7 @@ static void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) OUTREG(R128_GEN_INT_CNTL, restore->gen_int_cntl); OUTREG(R128_CAP0_TRIG_CNTL, restore->cap0_trig_cntl); OUTREG(R128_CAP1_TRIG_CNTL, restore->cap1_trig_cntl); - OUTREG(R128_BUS_CNTL, restore->bus_cntl); + OUTREG(R128_BUS_CNTL, restore->bus_cntl); } /* Write CRTC registers. */ @@ -1603,7 +1967,7 @@ static void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save) save->gen_int_cntl = INREG(R128_GEN_INT_CNTL); save->cap0_trig_cntl = INREG(R128_CAP0_TRIG_CNTL); save->cap1_trig_cntl = INREG(R128_CAP1_TRIG_CNTL); - save->bus_cntl = INREG(R128_BUS_CNTL); + save->bus_cntl = INREG(R128_BUS_CNTL); } /* Read CRTC registers. */ @@ -2025,7 +2389,7 @@ static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save) R128InitPLLRegisters(pScrn, save, mode, &info->pll, dot_clock); if (!R128InitDDARegisters(pScrn, save, mode, &info->pll, info)) return FALSE; - R128InitPalette(save, info); + if (!info->PaletteSavedOnVT) R128InitPalette(save, info); R128TRACE(("R128Init returns %p\n", save)); return TRUE; @@ -2037,6 +2401,7 @@ static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) R128InfoPtr info = R128PTR(pScrn); if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE; + /* FIXME? DRILock/DRIUnlock here? */ R128Blank(pScrn); R128RestoreMode(pScrn, &info->ModeReg); R128Unblank(pScrn); @@ -2096,14 +2461,43 @@ static void R128AdjustFrame(int scrnIndex, int x, int y, int flags) mode. */ static Bool R128EnterVT(int scrnIndex, int flags) { - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + R128InfoPtr info = R128PTR(pScrn); R128TRACE(("R128EnterVT\n")); +#ifdef XF86DRI + if (R128PTR(pScrn)->directRenderingEnabled) { + R128CCEStart(pScrn); + DRIUnlock(pScrn->pScreen); + } +#endif if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; + info->PaletteSavedOnVT = FALSE; R128AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + return TRUE; } +/* Called when VT switching away from the X server. Restore the original + text mode. */ +static void R128LeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + R128InfoPtr info = R128PTR(pScrn); + R128SavePtr save = &info->ModeReg; + + R128TRACE(("R128LeaveVT\n")); +#ifdef XF86DRI + if (R128PTR(pScrn)->directRenderingEnabled) { + DRILock(pScrn->pScreen, 0); + R128CCEStop(pScrn); + } +#endif + R128SavePalette(pScrn, save); + info->PaletteSavedOnVT = TRUE; + R128Restore(pScrn); +} + static Bool R128EnterVTFBDev(int scrnIndex, int flags) { @@ -2116,8 +2510,6 @@ R128EnterVTFBDev(int scrnIndex, int flags) return TRUE; } -/* Called when VT switching away from the X server. Restore the original - text mode. */ static void R128LeaveVTFBDev(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; @@ -2127,14 +2519,6 @@ static void R128LeaveVTFBDev(int scrnIndex, int flags) fbdevHWLeaveVT(scrnIndex,flags); } -static void R128LeaveVT(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - R128TRACE(("R128LeaveVT\n")); - R128Restore(pScrn); -} - /* Called at the end of each server generation. Restore the original text mode, unmap video memory, and unwrap and call the saved CloseScreen function. */ @@ -2144,6 +2528,15 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) R128InfoPtr info = R128PTR(pScrn); R128TRACE(("R128CloseScreen\n")); + +#ifdef XF86DRI + /* Disable direct rendering */ + if (info->directRenderingEnabled) { + R128DRICloseScreen(pScreen); + info->directRenderingEnabled = FALSE; + } +#endif + if (pScrn->vtSema) { R128Restore(pScrn); R128UnmapMem(pScrn); diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h index 86652affa..144fd9efe 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h @@ -1,8 +1,8 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h,v 1.6 2000/02/23 04:47:19 martin Exp $ */ /************************************************************************** -Copyright 1999 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -159,9 +159,20 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_AGP_APER_OFFSET 0x0178 #define R128_AGP_BASE 0x0170 #define R128_AGP_CNTL 0x0174 +# define R128_AGP_APER_SIZE_256MB (0x00 << 0) +# define R128_AGP_APER_SIZE_128MB (0x20 << 0) +# define R128_AGP_APER_SIZE_64MB (0x30 << 0) +# define R128_AGP_APER_SIZE_32MB (0x38 << 0) +# define R128_AGP_APER_SIZE_16MB (0x3c << 0) +# define R128_AGP_APER_SIZE_8MB (0x3e << 0) +# define R128_AGP_APER_SIZE_4MB (0x3f << 0) +# define R128_AGP_APER_SIZE_MASK (0x3f << 0) #define R128_AGP_COMMAND 0x0f58 /* PCI */ #define R128_AGP_PLL_CNTL 0x0010 /* PLL */ #define R128_AGP_STATUS 0x0f54 /* PCI */ +# define R128_AGP_1X_MODE 0x01 +# define R128_AGP_2X_MODE 0x02 +# define R128_AGP_MODE_MASK 0x03 #define R128_AMCGPIO_A_REG 0x01a0 #define R128_AMCGPIO_EN_REG 0x01a8 #define R128_AMCGPIO_MASK 0x0194 @@ -169,6 +180,15 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_ATTRDR 0x03c1 /* VGA */ #define R128_ATTRDW 0x03c0 /* VGA */ #define R128_ATTRX 0x03c0 /* VGA */ +# define R128_AUX1_SC_EN (1 << 0) +# define R128_AUX1_SC_MODE_OR (0 << 1) +# define R128_AUX1_SC_MODE_NAND (1 << 1) +# define R128_AUX2_SC_EN (1 << 2) +# define R128_AUX2_SC_MODE_OR (0 << 3) +# define R128_AUX2_SC_MODE_NAND (1 << 3) +# define R128_AUX3_SC_EN (1 << 4) +# define R128_AUX3_SC_MODE_OR (0 << 5) +# define R128_AUX3_SC_MODE_NAND (1 << 5) #define R128_AUX_SC_CNTL 0x1660 #define R128_AUX1_SC_BOTTOM 0x1670 #define R128_AUX1_SC_LEFT 0x1664 @@ -257,11 +277,12 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_BRUSH_SCALE 0x1470 #define R128_BRUSH_Y_X 0x1474 #define R128_BUS_CNTL 0x0030 -# define R128_BUS_RD_DISCARD_EN (1 << 24) -# define R128_BUS_RD_ABORT_EN (1 << 25) -# define R128_BUS_MSTR_DISCONNECT_EN (1 << 28) -# define R128_BUS_WRT_BURST (1 << 29) -# define R128_BUS_READ_BURST (1 << 30) +# define R128_BUS_MASTER_DIS (1 << 6) +# define R128_BUS_RD_DISCARD_EN (1 << 24) +# define R128_BUS_RD_ABORT_EN (1 << 25) +# define R128_BUS_MSTR_DISCONNECT_EN (1 << 28) +# define R128_BUS_WRT_BURST (1 << 29) +# define R128_BUS_READ_BURST (1 << 30) #define R128_BUS_CNTL1 0x0034 #define R128_CACHE_CNTL 0x1724 @@ -297,6 +318,9 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_CONFIG_REG_APER_SIZE 0x0110 #define R128_CONFIG_XSTRAP 0x00e4 #define R128_CONSTANT_COLOR_C 0x1d34 +# define R128_CONSTANT_COLOR_MASK 0x00ffffff +# define R128_CONSTANT_COLOR_ONE 0x00ffffff +# define R128_CONSTANT_COLOR_ZERO 0x00000000 #define R128_CRC_CMDFIFO_ADDR 0x0740 #define R128_CRC_CMDFIFO_DOUT 0x0744 #define R128_CRTC_CRNT_FRAME 0x0214 @@ -360,8 +384,13 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 # define R128_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) # define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) -#define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824 +#define R128_FOG_3D_TABLE_START 0x1810 +#define R128_FOG_3D_TABLE_END 0x1814 +#define R128_FOG_3D_TABLE_DENSITY 0x181c +#define R128_FOG_TABLE_INDEX 0x1a14 +#define R128_FOG_TABLE_DATA 0x1a18 #define R128_DESTINATION_3D_CLR_CMP_VAL 0x1820 +#define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824 #define R128_DEVICE_ID 0x0f02 /* PCI */ #define R128_DP_BRUSH_BKGD_CLR 0x1478 #define R128_DP_BRUSH_FRGD_CLR 0x147c @@ -373,6 +402,7 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l # define R128_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) # define R128_DST_X_DIR_LEFT_TO_RIGHT (1 << 31) #define R128_DP_DATATYPE 0x16c4 +# define R128_HOST_BIG_ENDIAN_EN (1 << 29) #define R128_DP_GUI_MASTER_CNTL 0x146c # define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) # define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) @@ -388,6 +418,19 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l # define R128_GMC_BRUSH_8x8_COLOR (10 << 4) # define R128_GMC_BRUSH_1X8_COLOR (12 << 4) # define R128_GMC_BRUSH_SOLID_COLOR (13 << 4) +# define R128_GMC_BRUSH_NONE (15 << 4) +# define R128_GMC_DST_8BPP_CI (2 << 8) +# define R128_GMC_DST_15BPP (3 << 8) +# define R128_GMC_DST_16BPP (4 << 8) +# define R128_GMC_DST_24BPP (5 << 8) +# define R128_GMC_DST_32BPP (6 << 8) +# define R128_GMC_DST_8BPP_RGB (7 << 8) +# define R128_GMC_DST_Y8 (8 << 8) +# define R128_GMC_DST_RGB8 (9 << 8) +# define R128_GMC_DST_VYUY (11 << 8) +# define R128_GMC_DST_YVYU (12 << 8) +# define R128_GMC_DST_AYUV444 (14 << 8) +# define R128_GMC_DST_ARGB4444 (15 << 8) # define R128_GMC_DST_DATATYPE_MASK (0x0f << 8) # define R128_GMC_DST_DATATYPE_SHIFT 8 # define R128_GMC_SRC_DATATYPE_MASK (3 << 12) @@ -395,8 +438,11 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l # define R128_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12) # define R128_GMC_SRC_DATATYPE_COLOR (3 << 12) # define R128_GMC_BYTE_PIX_ORDER (1 << 14) +# define R128_GMC_BYTE_MSB_TO_LSB (0 << 14) # define R128_GMC_BYTE_LSB_TO_MSB (1 << 14) # define R128_GMC_CONVERSION_TEMP (1 << 15) +# define R128_GMC_CONVERSION_TEMP_6500 (0 << 15) +# define R128_GMC_CONVERSION_TEMP_9300 (1 << 15) # define R128_GMC_ROP3_MASK (0xff << 16) # define R128_DP_SRC_SOURCE_MASK (7 << 24) # define R128_DP_SRC_SOURCE_MEMORY (2 << 24) @@ -404,7 +450,7 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l # define R128_GMC_3D_FCN_EN (1 << 27) # define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28) # define R128_AUX_CLIP_DIS (1 << 29) -# define R128_GMC_WR_MSK_DS (1 << 30) +# define R128_GMC_WR_MSK_DIS (1 << 30) # define R128_GMC_LD_BRUSH_Y_X (1 << 31) # define R128_ROP3_ZERO 0x00000000 # define R128_ROP3_DSa 0x00880000 @@ -456,6 +502,7 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_DST_PITCH 0x1408 #define R128_DST_PITCH_OFFSET 0x142c #define R128_DST_PITCH_OFFSET_C 0x1c80 +# define R128_PITCH_SHIFT 21 #define R128_DST_WIDTH 0x140c #define R128_DST_WIDTH_HEIGHT 0x1598 #define R128_DST_WIDTH_X 0x1588 @@ -573,7 +620,6 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_MEM_VGA_RP_SEL 0x003c #define R128_MEM_VGA_WP_SEL 0x0038 #define R128_MIN_GRANT 0x0f3e /* PCI */ -#define R128_MISC_3D_STATE_CNTL_REG 0x1CA0 #define R128_MM_DATA 0x0004 #define R128_MM_INDEX 0x0000 #define R128_MPLL_CNTL 0x000e /* PLL */ @@ -592,7 +638,10 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_PC_DEBUG_MODE 0x1760 #define R128_PC_GUI_CTLSTAT 0x1748 #define R128_PC_GUI_MODE 0x1744 +# define R128_PC_IGNORE_UNIFY (1 << 5) #define R128_PC_NGUI_CTLSTAT 0x0184 +# define R128_PC_FLUSH_GUI (3 << 0) +# define R128_PC_RI_GUI (1 << 2) # define R128_PC_FLUSH_ALL 0x00ff # define R128_PC_BUSY (1 << 31) #define R128_PC_NGUI_MODE 0x0180 @@ -689,6 +738,538 @@ static inline unsigned short regr16(volatile unsigned long base_addr, unsigned l #define R128_XDLL_CNTL 0x000c /* PLL */ #define R128_XPLL_CNTL 0x000b /* PLL */ + /* Registers for CCE and Microcode Engine */ +#define R128_PM4_MICROCODE_ADDR 0x07d4 +#define R128_PM4_MICROCODE_RADDR 0x07d8 +#define R128_PM4_MICROCODE_DATAH 0x07dc +#define R128_PM4_MICROCODE_DATAL 0x07e0 + +#define R128_PM4_BUFFER_OFFSET 0x0700 +#define R128_PM4_BUFFER_CNTL 0x0704 +# define R128_PM4_NONPM4 (0 << 28) +# define R128_PM4_192PIO (1 << 28) +# define R128_PM4_192BM (2 << 28) +# define R128_PM4_128PIO_64INDBM (3 << 28) +# define R128_PM4_128BM_64INDBM (4 << 28) +# define R128_PM4_64PIO_128INDBM (5 << 28) +# define R128_PM4_64BM_128INDBM (6 << 28) +# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) +# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) +# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) +#define R128_PM4_BUFFER_WM_CNTL 0x0708 +# define R128_WMA_SHIFT 0 +# define R128_WMB_SHIFT 8 +# define R128_WMC_SHIFT 16 +# define R128_WB_WM_SHIFT 24 +#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c +#define R128_PM4_BUFFER_DL_RPTR 0x0710 +#define R128_PM4_BUFFER_DL_WPTR 0x0714 +# define R128_PM4_BUFFER_DL_DONE (1 << 31) +#define R128_PM4_VC_FPU_SETUP 0x071c +# define R128_FRONT_DIR_CW (0 << 0) +# define R128_FRONT_DIR_CCW (1 << 0) +# define R128_FRONT_DIR_MASK (1 << 0) +# define R128_BACKFACE_CULL (0 << 1) +# define R128_BACKFACE_POINTS (1 << 1) +# define R128_BACKFACE_LINES (2 << 1) +# define R128_BACKFACE_SOLID (3 << 1) +# define R128_BACKFACE_MASK (3 << 1) +# define R128_FRONTFACE_CULL (0 << 3) +# define R128_FRONTFACE_POINTS (1 << 3) +# define R128_FRONTFACE_LINES (2 << 3) +# define R128_FRONTFACE_SOLID (3 << 3) +# define R128_FRONTFACE_MASK (3 << 3) +# define R128_FPU_COLOR_SOLID (0 << 5) +# define R128_FPU_COLOR_FLAT (1 << 5) +# define R128_FPU_COLOR_GOURAUD (2 << 5) +# define R128_FPU_COLOR_GOURAUD2 (3 << 5) +# define R128_FPU_SUB_PIX_2BITS (0 << 7) +# define R128_FPU_SUB_PIX_4BITS (1 << 7) +# define R128_FPU_MODE_2D (0 << 8) +# define R128_FPU_MODE_3D (1 << 8) +# define R128_TRAP_BITS_DISABLE (1 << 9) +# define R128_EDGE_ANTIALIAS (1 << 10) +# define R128_SUPERSAMPLE (1 << 11) +# define R128_XFACTOR_2 (0 << 12) +# define R128_XFACTOR_4 (1 << 12) +# define R128_YFACTOR_2 (0 << 13) +# define R128_YFACTOR_4 (1 << 13) +# define R128_FLAT_SHADE_VERTEX_D3D (0 << 14) +# define R128_FLAT_SHADE_VERTEX_OGL (1 << 14) +# define R128_FPU_ROUND_TRUNCATE (0 << 15) +# define R128_FPU_ROUND_NEAREST (1 << 15) +# define R128_WM_SEL_8DW (0 << 16) +# define R128_WM_SEL_16DW (1 << 16) +# define R128_WM_SEL_32DW (2 << 16) +#define R128_PM4_STAT 0x07b8 +# define R128_PM4_FIFOCNT_MASK 0x0fff +# define R128_PM4_BUSY (1 << 16) +# define R128_PM4_GUI_ACTIVE (1 << 31) +#define R128_PM4_BUFFER_ADDR 0x07f0 +#define R128_PM4_MICRO_CNTL 0x07fc +# define R128_PM4_MICRO_FREERUN (1 << 30) +#define R128_PM4_FIFO_DATA_EVEN 0x1000 +#define R128_PM4_FIFO_DATA_ODD 0x1004 + #define R128_SCALE_3D_CNTL 0x1a00 +# define R128_SCALE_DITHER_ERR_DIFF (0 << 1) +# define R128_SCALE_DITHER_TABLE (1 << 1) +# define R128_TEX_CACHE_SIZE_FULL (0 << 2) +# define R128_TEX_CACHE_SIZE_HALF (1 << 2) +# define R128_DITHER_INIT_CURR (0 << 3) +# define R128_DITHER_INIT_RESET (1 << 3) +# define R128_ROUND_24BIT (1 << 4) +# define R128_TEX_CACHE_DISABLE (1 << 5) +# define R128_SCALE_3D_NOOP (0 << 6) +# define R128_SCALE_3D_SCALE (1 << 6) +# define R128_SCALE_3D_TEXMAP_SHADE (2 << 6) +# define R128_SCALE_PIX_BLEND (0 << 8) +# define R128_SCALE_PIX_REPLICATE (1 << 8) +# define R128_TEX_CACHE_SPLIT (1 << 9) +# define R128_APPLE_YUV_MODE (1 << 10) +# define R128_TEX_CACHE_PALLETE_MODE (1 << 11) +# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) +# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12) +# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12) +# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12) +# define R128_FOG_TABLE (1 << 14) +# define R128_SIGNED_DST_CLAMP (1 << 15) +# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16) +# define R128_ALPHA_BLEND_SRC_ONE (1 << 16) +# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16) +# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16) +# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16) +# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16) +# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16) +# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16) +# define R128_ALPHA_BLEND_SRC_SAT (10 << 16) +# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16) +# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16) +# define R128_ALPHA_BLEND_DST_ZERO (0 << 20) +# define R128_ALPHA_BLEND_DST_ONE (1 << 20) +# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20) +# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20) +# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20) +# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20) +# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20) +# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20) +# define R128_ALPHA_TEST_NEVER (0 << 24) +# define R128_ALPHA_TEST_LESS (1 << 24) +# define R128_ALPHA_TEST_LESSEQUAL (2 << 24) +# define R128_ALPHA_TEST_EQUAL (3 << 24) +# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24) +# define R128_ALPHA_TEST_GREATER (5 << 24) +# define R128_ALPHA_TEST_NEQUAL (6 << 24) +# define R128_ALPHA_TEST_ALWAYS (7 << 24) +# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28) +# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28) +# define R128_COMPOSITE_SHADOW (1 << 29) +# define R128_TEX_MAP_ALPHA_IN_TEXTURE (1 << 30) +# define R128_TEX_CACHE_LINE_SIZE_8QW (0 << 31) +# define R128_TEX_CACHE_LINE_SIZE_4QW (1 << 31) + +#define R128_SETUP_CNTL 0x1bc4 +# define R128_DONT_START_TRIANGLE (1 << 0) +# define R128_Z_BIAS (0 << 1) +# define R128_DONT_START_ANY_ON (1 << 2) +# define R128_COLOR_SOLID_COLOR (0 << 3) +# define R128_COLOR_FLAT_VERT_1 (1 << 3) +# define R128_COLOR_FLAT_VERT_2 (2 << 3) +# define R128_COLOR_FLAT_VERT_3 (3 << 3) +# define R128_COLOR_GOURAUD (4 << 3) +# define R128_PRIM_TYPE_TRI (0 << 7) +# define R128_PRIM_TYPE_LINE (1 << 7) +# define R128_PRIM_TYPE_POINT (2 << 7) +# define R128_PRIM_TYPE_POLY_EDGE (3 << 7) +# define R128_TEXTURE_ST_MULT_W (0 << 9) +# define R128_TEXTURE_ST_DIRECT (1 << 9) +# define R128_STARTING_VERTEX_1 (1 << 14) +# define R128_STARTING_VERTEX_2 (2 << 14) +# define R128_STARTING_VERTEX_3 (3 << 14) +# define R128_ENDING_VERTEX_1 (1 << 16) +# define R128_ENDING_VERTEX_2 (2 << 16) +# define R128_ENDING_VERTEX_3 (3 << 16) +# define R128_SU_POLY_LINE_LAST (0 << 18) +# define R128_SU_POLY_LINE_NOT_LAST (1 << 18) +# define R128_SUB_PIX_2BITS (0 << 19) +# define R128_SUB_PIX_4BITS (1 << 19) +# define R128_SET_UP_CONTINUE (1 << 31) + +#define R128_WINDOW_XY_OFFSET 0x1bcc +# define R128_WINDOW_Y_SHIFT 4 +# define R128_WINDOW_X_SHIFT 20 + +#define R128_Z_OFFSET_C 0x1c90 +#define R128_Z_PITCH_C 0x1c94 +#define R128_Z_STEN_CNTL_C 0x1c98 +# define R128_Z_PIX_WIDTH_16 (0 << 1) +# define R128_Z_PIX_WIDTH_24 (1 << 1) +# define R128_Z_PIX_WIDTH_32 (2 << 1) +# define R128_Z_PIX_WIDTH_MASK (3 << 1) +# define R128_Z_TEST_NEVER (0 << 4) +# define R128_Z_TEST_LESS (1 << 4) +# define R128_Z_TEST_LESSEQUAL (2 << 4) +# define R128_Z_TEST_EQUAL (3 << 4) +# define R128_Z_TEST_GREATEREQUAL (4 << 4) +# define R128_Z_TEST_GREATER (5 << 4) +# define R128_Z_TEST_NEQUAL (6 << 4) +# define R128_Z_TEST_ALWAYS (7 << 4) +# define R128_Z_TEST_MASK (7 << 4) +# define R128_STENCIL_TEST_NEVER (0 << 12) +# define R128_STENCIL_TEST_LESS (1 << 12) +# define R128_STENCIL_TEST_LESSEQUAL (2 << 12) +# define R128_STENCIL_TEST_EQUAL (3 << 12) +# define R128_STENCIL_TEST_GREATEREQUAL (4 << 12) +# define R128_STENCIL_TEST_GREATER (5 << 12) +# define R128_STENCIL_TEST_NEQUAL (6 << 12) +# define R128_STENCIL_TEST_ALWAYS (7 << 12) +# define R128_STENCIL_S_FAIL_KEEP (0 << 16) +# define R128_STENCIL_S_FAIL_ZERO (1 << 16) +# define R128_STENCIL_S_FAIL_REPLACE (2 << 16) +# define R128_STENCIL_S_FAIL_INC (3 << 16) +# define R128_STENCIL_S_FAIL_DEC (4 << 16) +# define R128_STENCIL_S_FAIL_INV (5 << 16) +# define R128_STENCIL_ZPASS_KEEP (0 << 20) +# define R128_STENCIL_ZPASS_ZERO (1 << 20) +# define R128_STENCIL_ZPASS_REPLACE (2 << 20) +# define R128_STENCIL_ZPASS_INC (3 << 20) +# define R128_STENCIL_ZPASS_DEC (4 << 20) +# define R128_STENCIL_ZPASS_INV (5 << 20) +# define R128_STENCIL_ZFAIL_KEEP (0 << 24) +# define R128_STENCIL_ZFAIL_ZERO (1 << 24) +# define R128_STENCIL_ZFAIL_REPLACE (2 << 24) +# define R128_STENCIL_ZFAIL_INC (3 << 24) +# define R128_STENCIL_ZFAIL_DEC (4 << 24) +# define R128_STENCIL_ZFAIL_INV (5 << 24) +#define R128_TEX_CNTL_C 0x1c9c +# define R128_Z_ENABLE (1 << 0) +# define R128_Z_WRITE_ENABLE (1 << 1) +# define R128_STENCIL_ENABLE (1 << 3) +# define R128_SHADE_ENABLE (0 << 4) +# define R128_TEXMAP_ENABLE (1 << 4) +# define R128_SEC_TEXMAP_ENABLE (1 << 5) +# define R128_FOG_ENABLE (1 << 7) +# define R128_DITHER_ENABLE (1 << 8) +# define R128_ALPHA_ENABLE (1 << 9) +# define R128_ALPHA_TEST_ENABLE (1 << 10) +# define R128_SPEC_LIGHT_ENABLE (1 << 11) +# define R128_TEX_CHROMA_KEY_ENABLE (1 << 12) +# define R128_ALPHA_IN_TEX_COMPLETE_A (0 << 13) +# define R128_ALPHA_IN_TEX_LSB_A (1 << 13) +# define R128_LIGHT_DIS (0 << 14) +# define R128_LIGHT_COPY (1 << 14) +# define R128_LIGHT_MODULATE (2 << 14) +# define R128_LIGHT_ADD (3 << 14) +# define R128_LIGHT_BLEND_CONSTANT (4 << 14) +# define R128_LIGHT_BLEND_TEXTURE (5 << 14) +# define R128_LIGHT_BLEND_VERTEX (6 << 14) +# define R128_LIGHT_BLEND_CONST_COLOR (7 << 14) +# define R128_ALPHA_LIGHT_DIS (0 << 18) +# define R128_ALPHA_LIGHT_COPY (1 << 18) +# define R128_ALPHA_LIGHT_MODULATE (2 << 18) +# define R128_ALPHA_LIGHT_ADD (3 << 18) +# define R128_ANTI_ALIAS (1 << 21) +# define R128_TEX_CACHE_FLUSH (1 << 23) +# define R128_LOD_BIAS_SHIFT 24 +#define R128_MISC_3D_STATE_CNTL_REG 0x1ca0 +# define R128_REF_ALPHA_MASK 0xff +# define R128_MISC_SCALE_3D_NOOP (0 << 8) +# define R128_MISC_SCALE_3D_SCALE (1 << 8) +# define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8) +# define R128_MISC_SCALE_PIX_BLEND (0 << 10) +# define R128_MISC_SCALE_PIX_REPLICATE (1 << 10) +# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) +# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12) +# define R128_FOG_VERTEX (0 << 14) +# define R128_FOG_TABLE (1 << 14) +# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16) +# define R128_ALPHA_BLEND_SRC_ONE (1 << 16) +# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16) +# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16) +# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16) +# define R128_ALPHA_BLEND_SRC_DESTALPHA (6 << 16) +# define R128_ALPHA_BLEND_SRC_INVDESTALPHA (7 << 16) +# define R128_ALPHA_BLEND_SRC_DESTCOLOR (8 << 16) +# define R128_ALPHA_BLEND_SRC_INVDESTCOLOR (9 << 16) +# define R128_ALPHA_BLEND_SRC_SRCALPHASAT (10 << 16) +# define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA (11 << 16) +# define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16) +# define R128_ALPHA_BLEND_SRC_MASK (15 << 16) +# define R128_ALPHA_BLEND_DST_ZERO (0 << 20) +# define R128_ALPHA_BLEND_DST_ONE (1 << 20) +# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20) +# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20) +# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20) +# define R128_ALPHA_BLEND_DST_DESTALPHA (6 << 20) +# define R128_ALPHA_BLEND_DST_INVDESTALPHA (7 << 20) +# define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20) +# define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20) +# define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20) +# define R128_ALPHA_BLEND_DST_MASK (15 << 20) +# define R128_ALPHA_TEST_NEVER (0 << 24) +# define R128_ALPHA_TEST_LESS (1 << 24) +# define R128_ALPHA_TEST_LESSEQUAL (2 << 24) +# define R128_ALPHA_TEST_EQUAL (3 << 24) +# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24) +# define R128_ALPHA_TEST_GREATER (5 << 24) +# define R128_ALPHA_TEST_NEQUAL (6 << 24) +# define R128_ALPHA_TEST_ALWAYS (7 << 24) +# define R128_ALPHA_TEST_MASK (7 << 24) +#define R128_TEXTURE_CLR_CMP_CLR_C 0x1ca4 +#define R128_TEXTURE_CLR_CMP_MSK_C 0x1ca8 +#define R128_FOG_COLOR_C 0x1cac +# define R128_FOG_BLUE_SHIFT 0 +# define R128_FOG_GREEN_SHIFT 8 +# define R128_FOG_RED_SHIFT 16 +#define R128_PRIM_TEX_CNTL_C 0x1cb0 +# define R128_MIN_BLEND_NEAREST (0 << 1) +# define R128_MIN_BLEND_LINEAR (1 << 1) +# define R128_MIN_BLEND_MIPNEAREST (2 << 1) +# define R128_MIN_BLEND_MIPLINEAR (3 << 1) +# define R128_MIN_BLEND_LINEARMIPNEAREST (4 << 1) +# define R128_MIN_BLEND_LINEARMIPLINEAR (5 << 1) +# define R128_MIN_BLEND_MASK (7 << 1) +# define R128_MAG_BLEND_NEAREST (0 << 4) +# define R128_MAG_BLEND_LINEAR (1 << 4) +# define R128_MAG_BLEND_MASK (7 << 4) +# define R128_MIP_MAP_DISABLE (1 << 7) +# define R128_TEX_CLAMP_S_WRAP (0 << 8) +# define R128_TEX_CLAMP_S_MIRROR (1 << 8) +# define R128_TEX_CLAMP_S_CLAMP (2 << 8) +# define R128_TEX_CLAMP_S_BORDER_COLOR (3 << 8) +# define R128_TEX_CLAMP_S_MASK (3 << 8) +# define R128_TEX_WRAP_S (1 << 10) +# define R128_TEX_CLAMP_T_WRAP (0 << 11) +# define R128_TEX_CLAMP_T_MIRROR (1 << 11) +# define R128_TEX_CLAMP_T_CLAMP (2 << 11) +# define R128_TEX_CLAMP_T_BORDER_COLOR (3 << 11) +# define R128_TEX_CLAMP_T_MASK (3 << 11) +# define R128_TEX_WRAP_T (1 << 13) +# define R128_TEX_PERSPECTIVE_DISABLE (1 << 14) +# define R128_DATATYPE_VQ (0 << 16) +# define R128_DATATYPE_CI4 (1 << 16) +# define R128_DATATYPE_CI8 (2 << 16) +# define R128_DATATYPE_ARGB1555 (3 << 16) +# define R128_DATATYPE_RGB565 (4 << 16) +# define R128_DATATYPE_RGB888 (5 << 16) +# define R128_DATATYPE_ARGB8888 (6 << 16) +# define R128_DATATYPE_RGB332 (7 << 16) +# define R128_DATATYPE_Y8 (8 << 16) +# define R128_DATATYPE_RGB8 (9 << 16) +# define R128_DATATYPE_CI16 (10 << 16) +# define R128_DATATYPE_YUV422 (11 << 16) +# define R128_DATATYPE_YUV422_2 (12 << 16) +# define R128_DATATYPE_AYUV444 (14 << 16) +# define R128_DATATYPE_ARGB4444 (15 << 16) +# define R128_PALLETE_EITHER (0 << 20) +# define R128_PALLETE_1 (1 << 20) +# define R128_PALLETE_2 (2 << 20) +# define R128_PSEUDOCOLOR_DT_RGB565 (0 << 24) +# define R128_PSEUDOCOLOR_DT_ARGB1555 (1 << 24) +# define R128_PSEUDOCOLOR_DT_ARGB4444 (2 << 24) +#define R128_PRIM_TEXTURE_COMBINE_CNTL_C 0x1cb4 +# define R128_COMB_DIS (0 << 0) +# define R128_COMB_COPY (1 << 0) +# define R128_COMB_COPY_INP (2 << 0) +# define R128_COMB_MODULATE (3 << 0) +# define R128_COMB_MODULATE2X (4 << 0) +# define R128_COMB_MODULATE4X (5 << 0) +# define R128_COMB_ADD (6 << 0) +# define R128_COMB_ADD_SIGNED (7 << 0) +# define R128_COMB_BLEND_VERTEX (8 << 0) +# define R128_COMB_BLEND_TEXTURE (9 << 0) +# define R128_COMB_BLEND_CONST (10 << 0) +# define R128_COMB_BLEND_PREMULT (11 << 0) +# define R128_COMB_BLEND_PREV (12 << 0) +# define R128_COMB_BLEND_PREMULT_INV (13 << 0) +# define R128_COMB_ADD_SIGNED2X (14 << 0) +# define R128_COMB_BLEND_CONST_COLOR (15 << 0) +# define R128_COMB_MASK (15 << 0) +# define R128_COLOR_FACTOR_TEX (4 << 4) +# define R128_COLOR_FACTOR_NTEX (5 << 4) +# define R128_COLOR_FACTOR_ALPHA (6 << 4) +# define R128_COLOR_FACTOR_NALPHA (7 << 4) +# define R128_COLOR_FACTOR_MASK (15 << 4) +# define R128_INPUT_FACTOR_CONST_COLOR (2 << 10) +# define R128_INPUT_FACTOR_CONST_ALPHA (3 << 10) +# define R128_INPUT_FACTOR_INT_COLOR (4 << 10) +# define R128_INPUT_FACTOR_INT_ALPHA (5 << 10) +# define R128_INPUT_FACTOR_MASK (15 << 10) +# define R128_COMB_ALPHA_DIS (0 << 14) +# define R128_COMB_ALPHA_COPY (1 << 14) +# define R128_COMB_ALPHA_COPY_INP (2 << 14) +# define R128_COMB_ALPHA_MODULATE (3 << 14) +# define R128_COMB_ALPHA_MODULATE2X (4 << 14) +# define R128_COMB_ALPHA_MODULATE4X (5 << 14) +# define R128_COMB_ALPHA_ADD (6 << 14) +# define R128_COMB_ALPHA_ADD_SIGNED (7 << 14) +# define R128_COMB_ALPHA_ADD_SIGNED2X (14 << 14) +# define R128_COMB_ALPHA_MASK (15 << 14) +# define R128_ALPHA_FACTOR_TEX_ALPHA (6 << 18) +# define R128_ALPHA_FACTOR_NTEX_ALPHA (7 << 18) +# define R128_ALPHA_FACTOR_MASK (15 << 18) +# define R128_INP_FACTOR_A_CONST_ALPHA (1 << 25) +# define R128_INP_FACTOR_A_INT_ALPHA (2 << 25) +# define R128_INP_FACTOR_A_MASK (7 << 25) +#define R128_TEX_SIZE_PITCH_C 0x1cb8 +# define R128_TEX_PITCH_SHIFT 0 +# define R128_TEX_SIZE_SHIFT 4 +# define R128_TEX_HEIGHT_SHIFT 8 +# define R128_TEX_MIN_SIZE_SHIFT 12 +# define R128_SEC_TEX_PITCH_SHIFT 16 +# define R128_SEC_TEX_SIZE_SHIFT 20 +# define R128_SEC_TEX_HEIGHT_SHIFT 24 +# define R128_SEC_TEX_MIN_SIZE_SHIFT 28 +# define R128_TEX_PITCH_MASK (0x0f << 0) +# define R128_TEX_SIZE_MASK (0x0f << 4) +# define R128_TEX_HEIGHT_MASK (0x0f << 8) +# define R128_TEX_MIN_SIZE_MASK (0x0f << 12) +# define R128_SEC_TEX_PITCH_MASK (0x0f << 16) +# define R128_SEC_TEX_SIZE_MASK (0x0f << 20) +# define R128_SEC_TEX_HEIGHT_MASK (0x0f << 24) +# define R128_SEC_TEX_MIN_SIZE_MASK (0x0f << 28) +# define R128_TEX_SIZE_PITCH_SHIFT 0 +# define R128_SEC_TEX_SIZE_PITCH_SHIFT 16 +# define R128_TEX_SIZE_PITCH_MASK (0xffff << 0) +# define R128_SEC_TEX_SIZE_PITCH_MASK (0xffff << 16) +#define R128_PRIM_TEX_0_OFFSET_C 0x1cbc +#define R128_PRIM_TEX_1_OFFSET_C 0x1cc0 +#define R128_PRIM_TEX_2_OFFSET_C 0x1cc4 +#define R128_PRIM_TEX_3_OFFSET_C 0x1cc8 +#define R128_PRIM_TEX_4_OFFSET_C 0x1ccc +#define R128_PRIM_TEX_5_OFFSET_C 0x1cd0 +#define R128_PRIM_TEX_6_OFFSET_C 0x1cd4 +#define R128_PRIM_TEX_7_OFFSET_C 0x1cd8 +#define R128_PRIM_TEX_8_OFFSET_C 0x1cdc +#define R128_PRIM_TEX_9_OFFSET_C 0x1ce0 +#define R128_PRIM_TEX_10_OFFSET_C 0x1ce4 +# define R128_TEX_NO_TILE (0 << 30) +# define R128_TEX_TILED_BY_HOST (1 << 30) +# define R128_TEX_TILED_BY_STORAGE (2 << 30) +# define R128_TEX_TILED_BY_STORAGE2 (3 << 30) + +#define R128_SEC_TEX_CNTL_C 0x1d00 +# define R128_SEC_SELECT_PRIM_ST (0 << 0) +# define R128_SEC_SELECT_SEC_ST (1 << 0) +#define R128_SEC_TEX_COMBINE_CNTL_C 0x1d04 +# define R128_INPUT_FACTOR_PREV_COLOR (8 << 10) +# define R128_INPUT_FACTOR_PREV_ALPHA (9 << 10) +# define R128_INP_FACTOR_A_PREV_ALPHA (4 << 25) +#define R128_SEC_TEX_0_OFFSET_C 0x1d08 +#define R128_SEC_TEX_1_OFFSET_C 0x1d0c +#define R128_SEC_TEX_2_OFFSET_C 0x1d10 +#define R128_SEC_TEX_3_OFFSET_C 0x1d14 +#define R128_SEC_TEX_4_OFFSET_C 0x1d18 +#define R128_SEC_TEX_5_OFFSET_C 0x1d1c +#define R128_SEC_TEX_6_OFFSET_C 0x1d20 +#define R128_SEC_TEX_7_OFFSET_C 0x1d24 +#define R128_SEC_TEX_8_OFFSET_C 0x1d28 +#define R128_SEC_TEX_9_OFFSET_C 0x1d2c +#define R128_SEC_TEX_10_OFFSET_C 0x1d30 +#define R128_CONSTANT_COLOR_C 0x1d34 +# define R128_CONSTANT_BLUE_SHIFT 0 +# define R128_CONSTANT_GREEN_SHIFT 8 +# define R128_CONSTANT_RED_SHIFT 16 +# define R128_CONSTANT_ALPHA_SHIFT 24 +#define R128_PRIM_TEXTURE_BORDER_COLOR_C 0x1d38 +# define R128_PRIM_TEX_BORDER_BLUE_SHIFT 0 +# define R128_PRIM_TEX_BORDER_GREEN_SHIFT 8 +# define R128_PRIM_TEX_BORDER_RED_SHIFT 16 +# define R128_PRIM_TEX_BORDER_ALPHA_SHIFT 24 +#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c +# define R128_SEC_TEX_BORDER_BLUE_SHIFT 0 +# define R128_SEC_TEX_BORDER_GREEN_SHIFT 8 +# define R128_SEC_TEX_BORDER_RED_SHIFT 16 +# define R128_SEC_TEX_BORDER_ALPHA_SHIFT 24 +#define R128_STEN_REF_MASK_C 0x1d40 +# define R128_STEN_REFERENCE_SHIFT 0 +# define R128_STEN_MASK_SHIFT 16 +# define R128_STEN_WRITE_MASK_SHIFT 24 +#define R128_PLANE_3D_MASK_C 0x1d44 + + + /* Constants */ +#define R128_AGP_TEX_OFFSET 0x02000000 + +#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0 +#define R128_SWAP_AGE_REG R128_GUI_SCRATCH_REG1 + + /* CCE packet types */ +#define R128_CCE_PACKET0 0x00000000 +#define R128_CCE_PACKET0_ONE_REG_WR 0x00008000 +#define R128_CCE_PACKET1 0x40000000 +#define R128_CCE_PACKET2 0x80000000 +#define R128_CCE_PACKET3_NOP 0xC0001000 +#define R128_CCE_PACKET3_PAINT 0xC0001100 +#define R128_CCE_PACKET3_BITBLT 0xC0001200 +#define R128_CCE_PACKET3_SMALLTEXT 0xC0001300 +#define R128_CCE_PACKET3_HOSTDATA_BLT 0xC0001400 +#define R128_CCE_PACKET3_POLYLINE 0xC0001500 +#define R128_CCE_PACKET3_SCALING 0xC0001600 +#define R128_CCE_PACKET3_TRANS_SCALING 0xC0001700 +#define R128_CCE_PACKET3_POLYSCANLINES 0xC0001800 +#define R128_CCE_PACKET3_NEXT_CHAR 0xC0001900 +#define R128_CCE_PACKET3_PAINT_MULTI 0xC0001A00 +#define R128_CCE_PACKET3_BITBLT_MULTI 0xC0001B00 +#define R128_CCE_PACKET3_PLY_NEXTSCAN 0xC0001D00 +#define R128_CCE_PACKET3_SET_SCISSORS 0xC0001E00 +#define R128_CCE_PACKET3_SET_MODE24BPP 0xC0001F00 +#define R128_CCE_PACKET3_CNTL_PAINT 0xC0009100 +#define R128_CCE_PACKET3_CNTL_BITBLT 0xC0009200 +#define R128_CCE_PACKET3_CNTL_SMALLTEXT 0xC0009300 +#define R128_CCE_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 +#define R128_CCE_PACKET3_CNTL_POLYLINE 0xC0009500 +#define R128_CCE_PACKET3_CNTL_SCALING 0xC0009600 +#define R128_CCE_PACKET3_CNTL_TRANS_SCALING 0xC0009700 +#define R128_CCE_PACKET3_CNTL_POLYSCANLINES 0xC0009800 +#define R128_CCE_PACKET3_CNTL_NEXT_CHAR 0xC0009900 +#define R128_CCE_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 +#define R128_CCE_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 +#define R128_CCE_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 +#define R128_CCE_PACKET3_3D_SAVE_CONTEXT 0xC0002000 +#define R128_CCE_PACKET3_3D_PLAY_CONTEXT 0xC0002100 +#define R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 +#define R128_CCE_PACKET3_3D_RNDR_GEN_PRIM 0xC0002500 +#define R128_CCE_PACKET3_LOAD_PALETTE 0xC0002C00 +#define R128_CCE_PACKET3_PURGE 0xC0002D00 +#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE 0xC0002E00 +# define R128_CCE_PACKET_MASK 0xC0000000 +# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000 +# define R128_CCE_PACKET_MAX_DWORDS (1 << 14) +# define R128_CCE_PACKET0_REG_MASK 0x000007ff +# define R128_CCE_PACKET1_REG0_MASK 0x000007ff +# define R128_CCE_PACKET1_REG1_MASK 0x003ff800 + +#define R128_CCE_VC_FRMT_RHW 0x00000001 +#define R128_CCE_VC_FRMT_DIFFUSE_BGR 0x00000002 +#define R128_CCE_VC_FRMT_DIFFUSE_A 0x00000004 +#define R128_CCE_VC_FRMT_DIFFUSE_ARGB 0x00000008 +#define R128_CCE_VC_FRMT_SPEC_BGR 0x00000010 +#define R128_CCE_VC_FRMT_SPEC_F 0x00000020 +#define R128_CCE_VC_FRMT_SPEC_FRGB 0x00000040 +#define R128_CCE_VC_FRMT_S_T 0x00000080 +#define R128_CCE_VC_FRMT_S2_T2 0x00000100 +#define R128_CCE_VC_FRMT_RHW2 0x00000200 + +#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000 +#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001 +#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002 +#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007 +#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010 +#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020 +#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 +#define R128_CCE_VC_CNTL_NUM_SHIFT 16 #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h new file mode 100644 index 000000000..c5d99df34 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h @@ -0,0 +1,77 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_SAREA_H_ +#define _R128_SAREA_H_ + +/* There are 2 heaps (local/AGP). Each region within a heap is a + minimum of 64k, and there are at most 64 of them per heap. */ +#define R128_LOCAL_TEX_HEAP 0 +#define R128_AGP_TEX_HEAP 1 +#define R128_NR_TEX_HEAPS 2 +#define R128_NR_TEX_REGIONS 64 +#define R128_LOG_TEX_GRANULARITY 16 + +typedef struct { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char in_use; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} R128TexRegion; + +typedef struct { + /* Maintain an LRU of contiguous regions of texture space. If you + * think you own a region of texture memory, and it has an age + * different to the one you set, then you are mistaken and it has + * been stolen by another client. If global texAge hasn't changed, + * there is no need to walk the list. + * + * These regions can be used as a proxy for the fine-grained texture + * information of other clients - by maintaining them in the same + * lru which is used to age their own textures, clients have an + * approximate lru for the whole of global texture space, and can + * make informed decisions as to which areas to kick out. There is + * no need to choose whether to kick out your own texture or someone + * else's - simply eject them all in LRU order. + */ + /* Last elt is sentinal */ + R128TexRegion texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; + /* last time texture was uploaded */ + int texAge[R128_NR_TEX_HEAPS]; + + int ctxOwner; /* last context to upload state */ + + int ringWrite; /* current ring buffer write index */ +} R128SAREAPriv, *R128SAREAPrivPtr; + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/loader/xf86sym.c b/xc/programs/Xserver/hw/xfree86/loader/xf86sym.c index 3d21e1c87..9844d6d90 100644 --- a/xc/programs/Xserver/hw/xfree86/loader/xf86sym.c +++ b/xc/programs/Xserver/hw/xfree86/loader/xf86sym.c @@ -54,6 +54,12 @@ #include "xf86Priv.h" #include "vbe.h" +#ifdef __FreeBSD__ +/* XXX used in drmOpen(). This should change to use a less os-specific + * method. */ +int sysctlbyname(const char*, void *, size_t *, void *, size_t); +#endif + extern xf86MonPtr ConfiguredMonitor; /* XXX Should get all of these from elsewhere */ @@ -894,6 +900,10 @@ LOOKUP xfree86LookupTab[] = { #endif #endif +#ifdef __FreeBSD__ + SYMFUNC(sysctlbyname) +#endif + /* * and now some variables */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/Imakefile index 7041d435a..c42f5b2b7 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/Imakefile +++ b/xc/programs/Xserver/hw/xfree86/os-support/Imakefile @@ -100,6 +100,7 @@ OS_SUBDIR = sco #if BuildXF86DRI && !DoLoadableServer DRM_SRC = $(OS_SUBDIR)/drm/?*.c DRM_OBJ = $(OS_SUBDIR)/drm/?*.o +DRM_DONES = $(OS_SUBDIR)/drm/DONE #endif SUBDIRS = $(OS_SUBDIR) $(BUS_SUBDIR) misc vbe @@ -107,7 +108,7 @@ SUBDIRS = $(OS_SUBDIR) $(BUS_SUBDIR) misc vbe SRCS = $(OS_SUBDIR)/?*.c $(BUS_SUBDIR)/?*.c misc/?*.c vbe/?*.c $(DRM_SRC) OBJS = $(OS_SUBDIR)/?*.o $(BUS_SUBDIR)/?*.o misc/?*.o vbe/?*.o $(DRM_OBJ) -DONES = $(OS_SUBDIR)/DONE $(BUS_SUBDIR)/DONE misc/DONE vbe/DONE +DONES = $(OS_SUBDIR)/DONE $(BUS_SUBDIR)/DONE misc/DONE vbe/DONE $(DRM_DONES) #if HasParallelMake MakeMutex($(SUBDIRS) $(OBJS) $(DONES)) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/bsd/Imakefile index b0ec00a5e..81f28bea8 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/Imakefile +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/Imakefile @@ -43,6 +43,11 @@ IOPERM_OBJ = ioperm_noop.o # endif #endif +#if BuildXF86DRI +DRI_SRC = sigio.c +DRI_OBJ = sigio.o +#endif + MOUSESRC = bsd_mouse.c MOUSEOBJ = bsd_mouse.o @@ -84,12 +89,12 @@ AXP_OBJ=bsd_ev56.o SRCS = bsd_init.c bsd_video.c bsd_io.c bsd_VTsw.c \ libc_wrapper.c $(IOPERM_SRC) std_kbdEv.c posix_tty.c $(MOUSESRC) \ $(RES_SRC) stdPci.c vidmem.c $(JOYSTICK_SRC) sigio.c $(APMSRC) \ - $(AXP_SRC) + $(AXP_SRC) kmod_noop.c OBJS = bsd_init.o bsd_video.o bsd_io.o bsd_VTsw.o \ libc_wrapper.o $(IOPERM_OBJ) std_kbdEv.o posix_tty.o $(MOUSEOBJ) \ $(RES_OBJ) stdPci.o vidmem.o $(JOYSTICK_OBJ) sigio.o $(APMOBJ) \ - $(AXP_OBJ) + $(AXP_OBJ) kmod_noop.o INCLUDES = -I$(XF86COMSRC) -I$(XF86OSSRC) -I. -I$(SERVERSRC)/include \ -I$(XINCLUDESRC) -I$(EXTINCSRC) -I$(SERVERSRC)/mi -I$(APINCLUDES) \ @@ -114,6 +119,14 @@ SpecialObjectRule(bsd_ev56.o, bsd_ev56.c, -mcpu=ev56) SubdirLibraryRule($(OBJS)) NormalLibraryObjectRule() +#if BuildXF86DRI +#define IHaveSubdirs +SUBDIRS = drm + +MakeSubdirs($(SUBDIRS)) +DependSubdirs($(SUBDIRS)) +#endif + #if BuildXInputExt # if DoLoadableServer # if JoystickSupport @@ -136,6 +149,7 @@ LinkSourceFile(stdResource.c,../shared) LinkSourceFile(stdPci.c,../shared) LinkSourceFile(vidmem.c,../shared) LinkSourceFile(sigio.c,../shared) +LinkSourceFile(kmod_noop.c,../shared) DependTarget() diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile new file mode 100644 index 000000000..4639b530d --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/Imakefile @@ -0,0 +1,41 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile,v 1.4 1999/09/25 14:37:49 dawes Exp $ +XCOMM $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile,v 1.7 1999/09/14 19:55:15 faith Exp $ + +#define IHaveModules +#include <Server.tmpl> + +#if DoLoadableServer +MSRC = drmmodule.c +MOBJ = drmmodule.o +#endif + +#if BuildXF86DRI +#if HasMTRRSupport +MTRR_DEFINES = -DHAS_MTRR_SUPPORT +#endif + +SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmI810.c xf86drmMga.c xf86drmR128.c $(MSRC) +OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o xf86drmI810.o xf86drmMga.o xf86drmR128.o $(MOBJ) + + +INCLUDES = -I$(XF86COMSRC) -I$(XF86OSSRC) -I. -I$(SERVERSRC)/include \ + -I$(XINCLUDESRC) -I$(EXTINCSRC) -I../.. -Ikernel + +DEFINES = $(MTRR_DEFINES) $(GLX_DEFINES) + +ModuleObjectRule() +LibraryModuleTarget(drm,$(OBJS)) +NormalLintTarget($(SRCS)) + +InstallLibraryModule(drm,$(MODULEDIR),freebsd) + +#define IHaveSubdirs +SUBDIRS = kernel + +MakeSubdirs($(SUBDIRS)) +DependSubdirs($(SUBDIRS)) +#endif + + + +InstallDriverSDKLibraryModule(drm,$(DRIVERSDKMODULEDIR),freebsd) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/drmmodule.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/drmmodule.c new file mode 100644 index 000000000..1ddf3f4c1 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/drmmodule.c @@ -0,0 +1,56 @@ +/* drmmodule.c -- Module initialization + * Created: Fri Jun 4 09:05:48 1999 by faith@precisioninsight.com + * Revised: Fri Jun 4 09:09:22 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/drmmodule.c,v 1.1 1999/06/07 13:01:42 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/drmmodule.c,v 1.1 1999/06/14 07:32:01 dawes Exp $ + * + */ + +#include "xf86Module.h" + +static MODULESETUPPROTO(drmSetup); + +static XF86ModuleVersionInfo VersRec = +{ + "drm", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_EXTENSION, + ABI_EXTENSION_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +XF86ModuleData drmModuleData = { &VersRec, drmSetup, NULL }; + +static pointer +drmSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + return (void *)1; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Imakefile new file mode 100644 index 000000000..cf042d218 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Imakefile @@ -0,0 +1,31 @@ +XCOMM $XFree86$ +XCOMM $PI$ + +#include <Server.tmpl> + +LinkSourceFile(xf86drm.c,..) +LinkSourceFile(xf86drmHash.c,..) +LinkSourceFile(xf86drmRandom.c,..) +LinkSourceFile(xf86drmSL.c,..) +LinkSourceFile(xf86drm.h,$(XF86OSSRC)) +LinkSourceFile(xf86_OSproc.h,$(XF86OSSRC)) +LinkSourceFile(sigio.c,$(XF86OSSRC)/shared) + +XCOMM This is a kludge until we determine how best to build the +XCOMM kernel-specific device driver. This allows us to continue +XCOMM to maintain the single Makefile.bsd with kernel-specific +XCOMM support. Later, we can move to a different Imakefile. + +#if BuildXF86DRI && BuildXF86DRM +all:: + $(MAKE) -f Makefile.bsd + +install:: + $(MAKE) -f Makefile.bsd install +#else +all:: + echo 'Use "make -f Makefile.bsd" to manually build drm.o' +#endif + +clean:: + $(MAKE) -f Makefile.bsd clean diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Makefile.bsd b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Makefile.bsd new file mode 100644 index 000000000..ff26c7628 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/Makefile.bsd @@ -0,0 +1,5 @@ +# $FreeBSD$ + +SUBDIR = drm tdfx gamma + +.include <bsd.subdir.mk> diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h new file mode 100644 index 000000000..9e0ade357 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h @@ -0,0 +1,359 @@ +/* drm.h -- Header for Direct Rendering Manager -*- c -*- + * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 13:08:18 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h,v 1.46 1999/08/20 20:00:53 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h,v 1.1 1999/09/25 14:37:58 dawes Exp $ + * + */ + +#ifndef _DRM_H_ +#define _DRM_H_ + +#include <sys/ioccom.h> /* For _IO* macros */ + +#define DRM_DEV_DRM "/dev/drm" +#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) +#define DRM_DEV_UID 0 +#define DRM_DEV_GID 0 + + +#define DRM_NAME "drm" /* Name in kernel, /dev */ +#define DRM_MIN_ORDER 5 /* At least 2^5 bytes = 32 bytes */ +#define DRM_MAX_ORDER 22 /* Up to 2^22 bytes = 4MB */ +#define DRM_RAM_PERCENT 10 /* How much system ram can we lock? */ + +#define _DRM_LOCK_HELD 0x80000000 /* Hardware lock is held */ +#define _DRM_LOCK_CONT 0x40000000 /* Hardware lock is contended */ +#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) +#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) +#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) + +typedef unsigned long drm_handle_t; +typedef unsigned int drm_context_t; +typedef unsigned int drm_drawable_t; +typedef unsigned int drm_magic_t; + +/* Warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well */ + +typedef struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +} drm_clip_rect_t; + +/* Seperate include files for the i810/mga specific structures */ +#include "mga_drm.h" +#include "i810_drm.h" +#include "r128_drm.h" + +typedef struct drm_version { + int version_major; /* Major version */ + int version_minor; /* Minor version */ + int version_patchlevel;/* Patch level */ + size_t name_len; /* Length of name buffer */ + char *name; /* Name of driver */ + size_t date_len; /* Length of date buffer */ + char *date; /* User-space buffer to hold date */ + size_t desc_len; /* Length of desc buffer */ + char *desc; /* User-space buffer to hold desc */ +} drm_version_t; + +typedef struct drm_unique { + size_t unique_len; /* Length of unique */ + char *unique; /* Unique name for driver instantiation */ +} drm_unique_t; + +typedef struct drm_list { + int count; /* Length of user-space structures */ + drm_version_t *version; +} drm_list_t; + +typedef struct drm_block { + int unused; +} drm_block_t; + +typedef struct drm_control { + enum { + DRM_ADD_COMMAND, + DRM_RM_COMMAND, + DRM_INST_HANDLER, + DRM_UNINST_HANDLER + } func; + int irq; +} drm_control_t; + +typedef enum drm_map_type { + _DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */ + _DRM_REGISTERS = 1, /* no caching, no core dump */ + _DRM_SHM = 2, /* shared, cached */ + _DRM_AGP = 3 /* AGP/GART */ +} drm_map_type_t; + +typedef enum drm_map_flags { + _DRM_RESTRICTED = 0x01, /* Cannot be mapped to user-virtual */ + _DRM_READ_ONLY = 0x02, + _DRM_LOCKED = 0x04, /* shared, cached, locked */ + _DRM_KERNEL = 0x08, /* kernel requires access */ + _DRM_WRITE_COMBINING = 0x10, /* use write-combining if available */ + _DRM_CONTAINS_LOCK = 0x20 /* SHM page that contains lock */ +} drm_map_flags_t; + +typedef struct drm_map { + unsigned long offset; /* Requested physical address (0 for SAREA)*/ + unsigned long size; /* Requested physical size (bytes) */ + drm_map_type_t type; /* Type of memory to map */ + drm_map_flags_t flags; /* Flags */ + void *handle; /* User-space: "Handle" to pass to mmap */ + /* Kernel-space: kernel-virtual address */ + int mtrr; /* MTRR slot used */ + /* Private data */ +} drm_map_t; + +typedef enum drm_lock_flags { + _DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */ + _DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */ + _DRM_LOCK_FLUSH = 0x04, /* Flush this context's DMA queue first */ + _DRM_LOCK_FLUSH_ALL = 0x08, /* Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + _DRM_HALT_ALL_QUEUES = 0x10, /* Halt all current and future queues */ + _DRM_HALT_CUR_QUEUES = 0x20 /* Halt all current queues */ +} drm_lock_flags_t; + +typedef struct drm_lock { + int context; + drm_lock_flags_t flags; +} drm_lock_t; + +typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */ + /* Flags for DMA buffer dispatch */ + _DRM_DMA_BLOCK = 0x01, /* Block until buffer dispatched. + Note, the buffer may not yet have + been processed by the hardware -- + getting a hardware lock with the + hardware quiescent will ensure + that the buffer has been + processed. */ + _DRM_DMA_WHILE_LOCKED = 0x02, /* Dispatch while lock held */ + _DRM_DMA_PRIORITY = 0x04, /* High priority dispatch */ + + /* Flags for DMA buffer request */ + _DRM_DMA_WAIT = 0x10, /* Wait for free buffers */ + _DRM_DMA_SMALLER_OK = 0x20, /* Smaller-than-requested buffers ok */ + _DRM_DMA_LARGER_OK = 0x40 /* Larger-than-requested buffers ok */ +} drm_dma_flags_t; + +typedef struct drm_buf_desc { + int count; /* Number of buffers of this size */ + int size; /* Size in bytes */ + int low_mark; /* Low water mark */ + int high_mark; /* High water mark */ + enum { + _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */ + } flags; + unsigned long agp_start; /* Start address of where the agp buffers + * are in the agp aperture */ +} drm_buf_desc_t; + +typedef struct drm_buf_info { + int count; /* Entries in list */ + drm_buf_desc_t *list; +} drm_buf_info_t; + +typedef struct drm_buf_free { + int count; + int *list; +} drm_buf_free_t; + +typedef struct drm_buf_pub { + int idx; /* Index into master buflist */ + int total; /* Buffer size */ + int used; /* Amount of buffer in use (for DMA) */ + void *address; /* Address of buffer */ +} drm_buf_pub_t; + +typedef struct drm_buf_map { + int count; /* Length of buflist */ + void *virtual; /* Mmaped area in user-virtual */ + drm_buf_pub_t *list; /* Buffer information */ +} drm_buf_map_t; + +typedef struct drm_dma { + /* Indices here refer to the offset into + buflist in drm_buf_get_t. */ + int context; /* Context handle */ + int send_count; /* Number of buffers to send */ + int *send_indices; /* List of handles to buffers */ + int *send_sizes; /* Lengths of data to send */ + drm_dma_flags_t flags; /* Flags */ + int request_count; /* Number of buffers requested */ + int request_size; /* Desired size for buffers */ + int *request_indices; /* Buffer information */ + int *request_sizes; + int granted_count; /* Number of buffers granted */ +} drm_dma_t; + +typedef enum { + _DRM_CONTEXT_PRESERVED = 0x01, + _DRM_CONTEXT_2DONLY = 0x02 +} drm_ctx_flags_t; + +typedef struct drm_ctx { + drm_context_t handle; + drm_ctx_flags_t flags; +} drm_ctx_t; + +typedef struct drm_ctx_res { + int count; + drm_ctx_t *contexts; +} drm_ctx_res_t; + +typedef struct drm_draw { + drm_drawable_t handle; +} drm_draw_t; + +typedef struct drm_auth { + drm_magic_t magic; +} drm_auth_t; + +typedef struct drm_irq_busid { + int irq; + int busnum; + int devnum; + int funcnum; +} drm_irq_busid_t; + +typedef struct drm_agp_mode { + unsigned long mode; +} drm_agp_mode_t; + + /* For drm_agp_alloc -- allocated a buffer */ +typedef struct drm_agp_buffer { + unsigned long size; /* In bytes -- will round to page boundary */ + unsigned long handle; /* Used for BIND/UNBIND ioctls */ + unsigned long type; /* Type of memory to allocate */ + unsigned long physical; /* Physical used by i810 */ +} drm_agp_buffer_t; + + /* For drm_agp_bind */ +typedef struct drm_agp_binding { + unsigned long handle; /* From drm_agp_buffer */ + unsigned long offset; /* In bytes -- will round to page boundary */ +} drm_agp_binding_t; + +typedef struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +} drm_agp_info_t; + +#define DRM_IOCTL_BASE 'd' +#define DRM_IOCTL_NR(n) ((n) & 0xff) +#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) +#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size) +#define DRM_IOW(nr,size) _IOW(DRM_IOCTL_BASE,nr,size) +#define DRM_IOWR(nr,size) _IOWR(DRM_IOCTL_BASE,nr,size) + + +#define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) +#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t) +#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t) + +#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) +#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t) +#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t) +#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t) +#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t) +#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t) +#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t) +#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t) +#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t) +#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t) +#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t) + +#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t) +#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t) +#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t) +#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t) +#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t) +#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t) +#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t) +#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t) +#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t) +#define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t) +#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t) +#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t) +#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t) + +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t) + +/* Mga specific ioctls */ +#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t) +#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x42, drm_mga_clear_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t ) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) + +/* I810 specific ioctls */ +#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) +#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) +#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t) +#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) +#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) +#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t) +#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46) + +/* Rage 128 specific ioctls */ +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) +#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43) +#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/Makefile b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/Makefile new file mode 100644 index 000000000..6a70a5b0f --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +KMOD = drm +SRCS = init.c memory.c auth.c context.c drawable.c bufs.c \ + lists.c lock.c ioctl.c fops.c vm.c dma.c sysctl.c \ + agpsupport.c +SRCS += device_if.h bus_if.h pci_if.h +CFLAGS += ${DEBUG_FLAGS} -I.. # -DDRM_AGP +KERN = /usr/src/sys + +@: + ln -sf /sys @ + +machine: + ln -sf /sys/i386/include machine + +.include "/usr/src/sys/conf/kmod.mk" diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/agpsupport.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/agpsupport.c new file mode 100644 index 000000000..53444c907 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/agpsupport.c @@ -0,0 +1,271 @@ +/* agpsupport.c -- DRM support for AGP/GART backend + * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * Author: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +#ifdef DRM_AGP + +#include <pci/agpvar.h> + +MODULE_DEPEND(drm, agp, 1, 1, 1); + +int +drm_agp_info(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + struct agp_info *kern; + drm_agp_info_t info; + + if (!dev->agp->acquired) return EINVAL; + + kern = &dev->agp->info; + agp_get_info(dev->agp->agpdev, kern); + info.agp_version_major = 1; + info.agp_version_minor = 0; + info.mode = kern->ai_mode; + info.aperture_base = kern->ai_aperture_base; + info.aperture_size = kern->ai_aperture_size; + info.memory_allowed = kern->ai_memory_allowed; + info.memory_used = kern->ai_memory_used; + info.id_vendor = kern->ai_devid & 0xffff; + info.id_device = kern->ai_devid >> 16; + + *(drm_agp_info_t *) data = info; + return 0; +} + +int +drm_agp_acquire(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + int retcode; + + if (dev->agp->acquired) return EINVAL; + retcode = agp_acquire(dev->agp->agpdev); + if (retcode) return retcode; + dev->agp->acquired = 1; + return 0; +} + +int +drm_agp_release(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + + if (!dev->agp->acquired) return EINVAL; + agp_release(dev->agp->agpdev); + dev->agp->acquired = 0; + return 0; + +} + +int +drm_agp_enable(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_agp_mode_t mode; + + if (!dev->agp->acquired) return EINVAL; + + mode = *(drm_agp_mode_t *) data; + + dev->agp->mode = mode.mode; + agp_enable(dev->agp->agpdev, mode.mode); + dev->agp->base = dev->agp->info.ai_aperture_base; + dev->agp->enabled = 1; + return 0; +} + +int drm_agp_alloc(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_agp_buffer_t request; + drm_agp_mem_t *entry; + void *handle; + unsigned long pages; + u_int32_t type; + struct agp_memory_info info; + + if (!dev->agp->acquired) return EINVAL; + + request = *(drm_agp_buffer_t *) data; + + if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS))) + return ENOMEM; + + memset(entry, 0, sizeof(*entry)); + + pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; + type = (u_int32_t) request.type; + + if (!(handle = drm_alloc_agp(pages, type))) { + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return ENOMEM; + } + + entry->handle = handle; + entry->bound = 0; + entry->pages = pages; + entry->prev = NULL; + entry->next = dev->agp->memory; + if (dev->agp->memory) dev->agp->memory->prev = entry; + dev->agp->memory = entry; + + agp_memory_info(dev->agp->agpdev, entry->handle, &info); + + request.handle = (unsigned long) entry->handle; + request.physical = info.ami_physical; + + *(drm_agp_buffer_t *) data = request; + + return 0; +} + +static drm_agp_mem_t * +drm_agp_lookup_entry(drm_device_t *dev, void *handle) +{ + drm_agp_mem_t *entry; + + for (entry = dev->agp->memory; entry; entry = entry->next) { + if (entry->handle == handle) return entry; + } + return NULL; +} + +int +drm_agp_unbind(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_agp_binding_t request; + drm_agp_mem_t *entry; + + if (!dev->agp->acquired) return EINVAL; + request = *(drm_agp_binding_t *) data; + if (!(entry = drm_agp_lookup_entry(dev, (void *) request.handle))) + return EINVAL; + if (!entry->bound) return EINVAL; + return drm_unbind_agp(entry->handle); +} + +int drm_agp_bind(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_agp_binding_t request; + drm_agp_mem_t *entry; + int retcode; + int page; + + if (!dev->agp->acquired) return EINVAL; + request = *(drm_agp_binding_t *) data; + if (!(entry = drm_agp_lookup_entry(dev, (void *) request.handle))) + return EINVAL; + if (entry->bound) return EINVAL; + page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; + if ((retcode = drm_bind_agp(entry->handle, page))) return retcode; + entry->bound = dev->agp->base + (page << PAGE_SHIFT); + return 0; +} + +int drm_agp_free(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_agp_buffer_t request; + drm_agp_mem_t *entry; + + if (!dev->agp->acquired) return EINVAL; + request = *(drm_agp_buffer_t *) data; + if (!(entry = drm_agp_lookup_entry(dev, (void*) request.handle))) + return EINVAL; + if (entry->bound) drm_unbind_agp(entry->handle); + + if (entry->prev) entry->prev->next = entry->next; + else dev->agp->memory = entry->next; + if (entry->next) entry->next->prev = entry->prev; + drm_free_agp(entry->handle, entry->pages); + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return 0; +} + +drm_agp_head_t *drm_agp_init(void) +{ + device_t agpdev; + drm_agp_head_t *head = NULL; + int agp_available = 1; + + agpdev = agp_find_device(); + if (!agpdev) + agp_available = 0; + + DRM_DEBUG("agp_available = %d\n", agp_available); + + if (agp_available) { + if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) + return NULL; + head->agpdev = agpdev; + memset((void *)head, 0, sizeof(*head)); + agp_get_info(agpdev, &head->info); + head->memory = NULL; +#if 0 /* bogus */ + switch (head->agp_info.chipset) { + case INTEL_GENERIC: head->chipset = "Intel"; break; + case INTEL_LX: head->chipset = "Intel 440LX"; break; + case INTEL_BX: head->chipset = "Intel 440BX"; break; + case INTEL_GX: head->chipset = "Intel 440GX"; break; + case INTEL_I810: head->chipset = "Intel i810"; break; + case VIA_GENERIC: head->chipset = "VIA"; break; + case VIA_VP3: head->chipset = "VIA VP3"; break; + case VIA_MVP3: head->chipset = "VIA MVP3"; break; + case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; + case SIS_GENERIC: head->chipset = "SiS"; break; + case AMD_GENERIC: head->chipset = "AMD"; break; + case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; + case ALI_GENERIC: head->chipset = "ALi"; break; + case ALI_M1541: head->chipset = "ALi M1541"; break; + default: + } +#endif + DRM_INFO("AGP at 0x%08x %dMB\n", + head->info.ai_aperture_base, + head->info.ai_aperture_size >> 20); + } + return head; +} + +#endif /* DRM_AGP */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/auth.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/auth.c new file mode 100644 index 000000000..f7b3bc493 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/auth.c @@ -0,0 +1,168 @@ +/* auth.c -- IOCTLs for authentication -*- c -*- + * Created: Tue Feb 2 08:37:54 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 11:31:48 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/auth.c,v 1.4 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/auth.c,v 1.1 1999/09/25 14:37:57 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +static int drm_hash_magic(drm_magic_t magic) +{ + return magic & (DRM_HASH_SIZE-1); +} + +static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic) +{ + drm_file_t *retval = NULL; + drm_magic_entry_t *pt; + int hash = drm_hash_magic(magic); + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { + if (pt->priv->authenticated) continue; + if (pt->magic == magic) { + retval = pt->priv; + break; + } + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + return retval; +} + +int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) +{ + int hash; + drm_magic_entry_t *entry; + + DRM_DEBUG("%d\n", magic); + + hash = drm_hash_magic(magic); + entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); + if (!entry) return ENOMEM; + entry->magic = magic; + entry->priv = priv; + entry->next = NULL; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + if (dev->magiclist[hash].tail) { + dev->magiclist[hash].tail->next = entry; + dev->magiclist[hash].tail = entry; + } else { + dev->magiclist[hash].head = entry; + dev->magiclist[hash].tail = entry; + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + return 0; +} + +int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) +{ + drm_magic_entry_t *prev = NULL; + drm_magic_entry_t *pt; + int hash; + + DRM_DEBUG("%d\n", magic); + hash = drm_hash_magic(magic); + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { + if (pt->magic == magic) { + if (dev->magiclist[hash].head == pt) { + dev->magiclist[hash].head = pt->next; + } + if (dev->magiclist[hash].tail == pt) { + dev->magiclist[hash].tail = prev; + } + if (prev) { + prev->next = pt->next; + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return 0; + } + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + + return EINVAL; +} + +int drm_getmagic(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + static drm_magic_t sequence = 0; +#if 0 + static struct simplelock lock; /* XXX */ +#endif + drm_device_t *dev = kdev->si_drv1; + drm_file_t *priv; + drm_auth_t auth; + + /* Find unique magic */ + priv = drm_find_file_by_proc(dev, p); + if (!priv) { + DRM_DEBUG("can't find file structure\n"); + return EINVAL; + } + if (priv->magic) { + auth.magic = priv->magic; + } else { + simple_lock(&lock); + do { + if (!sequence) ++sequence; /* reserve 0 */ + auth.magic = sequence++; + } while (drm_find_file(dev, auth.magic)); + simple_unlock(&lock); + priv->magic = auth.magic; + drm_add_magic(dev, priv, auth.magic); + } + + DRM_DEBUG("%u\n", auth.magic); + *(drm_auth_t *) data = auth; + return 0; +} + +int drm_authmagic(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_auth_t auth; + drm_file_t *file; + + auth = *(drm_auth_t *) data; + DRM_DEBUG("%u\n", auth.magic); + if ((file = drm_find_file(dev, auth.magic))) { + file->authenticated = 1; + drm_remove_magic(dev, auth.magic); + return 0; + } + return EINVAL; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/bufs.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/bufs.c new file mode 100644 index 000000000..fc08b69d2 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/bufs.c @@ -0,0 +1,500 @@ +/* bufs.c -- IOCTLs to manage buffers -*- c -*- + * Created: Tue Feb 2 08:37:54 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 22:48:10 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/bufs.c,v 1.8 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/bufs.c,v 1.1 1999/09/25 14:37:57 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include <sys/mman.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> +#include <vm/vm_map.h> + + /* Compute order. Can be made faster. */ +int drm_order(unsigned long size) +{ + int order; + unsigned long tmp; + + for (order = 0, tmp = size; tmp >>= 1; ++order); + if (size & ~(1 << order)) ++order; + return order; +} + +int drm_addmap(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_map_t *map; + + if (!(dev->flags & (FREAD|FWRITE))) + return EACCES; /* Require read/write */ + + map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); + if (!map) return ENOMEM; + *map = *(drm_map_t *) data; + + DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", + map->offset, map->size, map->type); + if ((map->offset & (PAGE_SIZE-1)) || (map->size & (PAGE_SIZE-1))) { + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + DRM_DEBUG("offset or size not page aligned\n"); + return EINVAL; + } + map->mtrr = -1; + map->handle = 0; + + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: + if (map->offset + map->size < map->offset + /* || map->offset < virt_to_phys(high_memory) */) { + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + DRM_DEBUG("bad frame buffer size\n"); + return EINVAL; + } +#ifdef CONFIG_MTRR + if (map->type == _DRM_FRAME_BUFFER + || (map->flags & _DRM_WRITE_COMBINING)) { + map->mtrr = mtrr_add(map->offset, map->size, + MTRR_TYPE_WRCOMB, 1); + } +#endif + map->handle = drm_ioremap(map->offset, map->size); + break; + + + case _DRM_SHM: + DRM_DEBUG("%ld %d\n", map->size, drm_order(map->size)); + map->handle = (void *)drm_alloc_pages(drm_order(map->size) + - PAGE_SHIFT, + DRM_MEM_SAREA); + if (!map->handle) { + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + return ENOMEM; + } + map->offset = (unsigned long)map->handle; + if (map->flags & _DRM_CONTAINS_LOCK) { + dev->lock.hw_lock = map->handle; /* Pointer to lock */ + } + break; +#ifdef DRM_AGP + case _DRM_AGP: + map->offset = map->offset + dev->agp->base; + break; +#endif + default: + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + DRM_DEBUG("bad type\n"); + return EINVAL; + } + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + if (dev->maplist) { + ++dev->map_count; + dev->maplist = drm_realloc(dev->maplist, + (dev->map_count-1) + * sizeof(*dev->maplist), + dev->map_count + * sizeof(*dev->maplist), + DRM_MEM_MAPS); + } else { + dev->map_count = 1; + dev->maplist = drm_alloc(dev->map_count*sizeof(*dev->maplist), + DRM_MEM_MAPS); + } + dev->maplist[dev->map_count-1] = map; + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + *(drm_map_t *) data = *map; + if (map->type != _DRM_SHM) + ((drm_map_t *)data)->handle = (void *) map->offset; + + return 0; +} + +int drm_addbufs(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_device_dma_t *dma = dev->dma; + drm_buf_desc_t request; + int count; + int order; + int size; + int total; + int page_order; + drm_buf_entry_t *entry; + unsigned long page; + drm_buf_t *buf; + int alignment; + unsigned long offset; + int i; + int byte_count; + int page_count; + + if (!dma) return EINVAL; + + request = *(drm_buf_desc_t *) data; + + count = request.count; + order = drm_order(request.size); + size = 1 << order; + + DRM_DEBUG("count = %d, size = %d (%d), order = %d, queue_count = %d\n", + request.count, request.size, size, order, dev->queue_count); + + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return EINVAL; + if (dev->queue_count) return EBUSY; /* Not while in use */ + + alignment = (request.flags & _DRM_PAGE_ALIGN) ? round_page(size) :size; + page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; + total = PAGE_SIZE << page_order; + + simple_lock(&dev->count_lock); + if (dev->buf_use) { + simple_unlock(&dev->count_lock); + return EBUSY; + } + atomic_inc(&dev->buf_alloc); + simple_unlock(&dev->count_lock); + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + entry = &dma->bufs[order]; + if (entry->buf_count) { + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + atomic_dec(&dev->buf_alloc); + return ENOMEM; /* May only call once for each order */ + } + + entry->buflist = drm_alloc(count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + if (!entry->buflist) { + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + atomic_dec(&dev->buf_alloc); + return ENOMEM; + } + memset(entry->buflist, 0, count * sizeof(*entry->buflist)); + + entry->seglist = drm_alloc(count * sizeof(*entry->seglist), + DRM_MEM_SEGS); + if (!entry->seglist) { + drm_free(entry->buflist, + count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + atomic_dec(&dev->buf_alloc); + return ENOMEM; + } + memset(entry->seglist, 0, count * sizeof(*entry->seglist)); + + dma->pagelist = drm_realloc(dma->pagelist, + dma->page_count * sizeof(*dma->pagelist), + (dma->page_count + (count << page_order)) + * sizeof(*dma->pagelist), + DRM_MEM_PAGES); + DRM_DEBUG("pagelist: %d entries\n", + dma->page_count + (count << page_order)); + + + entry->buf_size = size; + entry->page_order = page_order; + byte_count = 0; + page_count = 0; + while (entry->buf_count < count) { + if (!(page = drm_alloc_pages(page_order, DRM_MEM_DMA))) break; + entry->seglist[entry->seg_count++] = page; + for (i = 0; i < (1 << page_order); i++) { + DRM_DEBUG("page %d @ 0x%08lx\n", + dma->page_count + page_count, + page + PAGE_SIZE * i); + dma->pagelist[dma->page_count + page_count++] + = page + PAGE_SIZE * i; + } + for (offset = 0; + offset + size <= total && entry->buf_count < count; + offset += alignment, ++entry->buf_count) { + buf = &entry->buflist[entry->buf_count]; + buf->idx = dma->buf_count + entry->buf_count; + buf->total = alignment; + buf->order = order; + buf->used = 0; + buf->offset = (dma->byte_count + byte_count + offset); + buf->address = (void *)(page + offset); + buf->next = NULL; + buf->waiting = 0; + buf->pending = 0; + buf->dma_wait = 0; + buf->pid = 0; +#if DRM_DMA_HISTOGRAM + timespecclear(&buf->time_queued); + timespecclear(&buf->time_dispatched); + timespecclear(&buf->time_completed); + timespecclear(&buf->time_freed); +#endif + DRM_DEBUG("buffer %d @ %p\n", + entry->buf_count, buf->address); + } + byte_count += PAGE_SIZE << page_order; + } + + dma->buflist = drm_realloc(dma->buflist, + dma->buf_count * sizeof(*dma->buflist), + (dma->buf_count + entry->buf_count) + * sizeof(*dma->buflist), + DRM_MEM_BUFS); + for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++) + dma->buflist[i] = &entry->buflist[i - dma->buf_count]; + + dma->buf_count += entry->buf_count; + dma->seg_count += entry->seg_count; + dma->page_count += entry->seg_count << page_order; + dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); + + drm_freelist_create(&entry->freelist, entry->buf_count); + for (i = 0; i < entry->buf_count; i++) { + drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]); + } + + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + request.count = entry->buf_count; + request.size = size; + + *(drm_buf_desc_t *) data = request; + + atomic_dec(&dev->buf_alloc); + return 0; +} + +int drm_infobufs(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_device_dma_t *dma = dev->dma; + drm_buf_info_t request; + int i; + int count; + + if (!dma) return EINVAL; + + simple_lock(&dev->count_lock); + if (atomic_read(&dev->buf_alloc)) { + simple_unlock(&dev->count_lock); + return EBUSY; + } + ++dev->buf_use; /* Can't allocate more after this call */ + simple_unlock(&dev->count_lock); + + request = *(drm_buf_info_t *) data; + + for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { + if (dma->bufs[i].buf_count) ++count; + } + + DRM_DEBUG("count = %d\n", count); + + if (request.count >= count) { + for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) { + if (dma->bufs[i].buf_count) { + int error; + error = copyout(&dma->bufs[i].buf_count, + &request.list[count].count, + sizeof(dma->bufs[0] + .buf_count)); + if (error) return error; + error = copyout(&dma->bufs[i].buf_size, + &request.list[count].size, + sizeof(dma->bufs[0].buf_size)); + if (error) return error; + error = copyout(&dma->bufs[i] + .freelist.low_mark, + &request.list[count].low_mark, + sizeof(dma->bufs[0] + .freelist.low_mark)); + if (error) return error; + error = copyout(&dma->bufs[i] + .freelist.high_mark, + &request.list[count].high_mark, + sizeof(dma->bufs[0] + .freelist.high_mark)); + if (error) return error; + DRM_DEBUG("%d %d %d %d %d\n", + i, + dma->bufs[i].buf_count, + dma->bufs[i].buf_size, + dma->bufs[i].freelist.low_mark, + dma->bufs[i].freelist.high_mark); + ++count; + } + } + } + request.count = count; + + *(drm_buf_info_t *) data = request; + + return 0; +} + +int drm_markbufs(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_device_dma_t *dma = dev->dma; + drm_buf_desc_t request; + int order; + drm_buf_entry_t *entry; + + if (!dma) return EINVAL; + + request = *(drm_buf_desc_t *) data; + + DRM_DEBUG("%d, %d, %d\n", + request.size, request.low_mark, request.high_mark); + order = drm_order(request.size); + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return EINVAL; + entry = &dma->bufs[order]; + + if (request.low_mark < 0 || request.low_mark > entry->buf_count) + return EINVAL; + if (request.high_mark < 0 || request.high_mark > entry->buf_count) + return EINVAL; + + entry->freelist.low_mark = request.low_mark; + entry->freelist.high_mark = request.high_mark; + + return 0; +} + +int drm_freebufs(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_device_dma_t *dma = dev->dma; + drm_buf_free_t request; + int i; + int idx; + int error; + drm_buf_t *buf; + + if (!dma) return EINVAL; + + request = *(drm_buf_free_t *) data; + + DRM_DEBUG("%d\n", request.count); + for (i = 0; i < request.count; i++) { + error = copyin(&request.list[i], &idx, sizeof(idx)); + if (error) + return error; + if (idx < 0 || idx >= dma->buf_count) { + DRM_ERROR("Index %d (of %d max)\n", + idx, dma->buf_count - 1); + return EINVAL; + } + buf = dma->buflist[idx]; + if (buf->pid != p->p_pid) { + DRM_ERROR("Process %d freeing buffer owned by %d\n", + p->p_pid, buf->pid); + return EINVAL; + } + drm_free_buffer(dev, buf); + } + + return 0; +} + +int drm_mapbufs(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + const int zero = 0; + vm_offset_t virtual; + vm_offset_t address; + drm_buf_map_t request; + int i; + + if (!dma) return EINVAL; + + DRM_DEBUG("\n"); + + simple_lock(&dev->count_lock); + if (atomic_read(&dev->buf_alloc)) { + simple_unlock(&dev->count_lock); + return EBUSY; + } + ++dev->buf_use; /* Can't allocate more after this call */ + simple_unlock(&dev->count_lock); + + request = *(drm_buf_map_t *) data; + + if (request.count >= dma->buf_count) { + virtual = 0; + retcode = vm_mmap(&p->p_vmspace->vm_map, + &virtual, + round_page(dma->byte_count), + PROT_READ|PROT_WRITE, VM_PROT_ALL, + MAP_SHARED, + SLIST_FIRST(&kdev->si_hlist), + 0); + if (retcode) + goto done; + + request.virtual = (void *)virtual; + + for (i = 0; i < dma->buf_count; i++) { + retcode = copyout(&dma->buflist[i]->idx, + &request.list[i].idx, + sizeof(request.list[0].idx)); + if (retcode) goto done; + retcode = copyout(&dma->buflist[i]->total, + &request.list[i].total, + sizeof(request.list[0].total)); + if (retcode) goto done; + retcode = copyout(&zero, + &request.list[i].used, + sizeof(request.list[0].used)); + if (retcode) goto done; + address = virtual + dma->buflist[i]->offset; + retcode = copyout(&address, + &request.list[i].address, + sizeof(address)); + if (retcode) goto done; + } + } +done: + request.count = dma->buf_count; + DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); + + *(drm_buf_map_t *) data = request; + + return retcode; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/context.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/context.c new file mode 100644 index 000000000..d79990f86 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/context.c @@ -0,0 +1,297 @@ +/* context.c -- IOCTLs for contexts and DMA queues -*- c -*- + * Created: Tue Feb 2 08:37:54 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 11:32:09 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/context.c,v 1.5 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/context.c,v 1.1 1999/09/25 14:37:58 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +static int drm_init_queue(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx) +{ + DRM_DEBUG("\n"); + + if (atomic_read(&q->use_count) != 1 + || atomic_read(&q->finalization) + || atomic_read(&q->block_count)) { + DRM_ERROR("New queue is already in use: u%d f%d b%d\n", + atomic_read(&q->use_count), + atomic_read(&q->finalization), + atomic_read(&q->block_count)); + } + + atomic_set(&q->finalization, 0); + atomic_set(&q->block_count, 0); + atomic_set(&q->block_read, 0); + atomic_set(&q->block_write, 0); + atomic_set(&q->total_queued, 0); + atomic_set(&q->total_flushed, 0); + atomic_set(&q->total_locks, 0); + + q->write_queue = 0; + q->read_queue = 0; + q->flush_queue = 0; + + q->flags = ctx->flags; + + drm_waitlist_create(&q->waitlist, dev->dma->buf_count); + + return 0; +} + + +/* drm_alloc_queue: +PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not + disappear (so all deallocation must be done after IOCTLs are off) + 2) dev->queue_count < dev->queue_slots + 3) dev->queuelist[i].use_count == 0 and + dev->queuelist[i].finalization == 0 if i not in use +POST: 1) dev->queuelist[i].use_count == 1 + 2) dev->queue_count < dev->queue_slots */ + +static int drm_alloc_queue(drm_device_t *dev) +{ + int i; + drm_queue_t *queue; + int oldslots; + int newslots; + /* Check for a free queue */ + for (i = 0; i < dev->queue_count; i++) { + atomic_inc(&dev->queuelist[i]->use_count); + if (atomic_read(&dev->queuelist[i]->use_count) == 1 + && !atomic_read(&dev->queuelist[i]->finalization)) { + DRM_DEBUG("%d (free)\n", i); + return i; + } + atomic_dec(&dev->queuelist[i]->use_count); + } + /* Allocate a new queue */ + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + + queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES); + memset(queue, 0, sizeof(*queue)); + atomic_set(&queue->use_count, 1); + + ++dev->queue_count; + if (dev->queue_count >= dev->queue_slots) { + oldslots = dev->queue_slots * sizeof(*dev->queuelist); + if (!dev->queue_slots) dev->queue_slots = 1; + dev->queue_slots *= 2; + newslots = dev->queue_slots * sizeof(*dev->queuelist); + + dev->queuelist = drm_realloc(dev->queuelist, + oldslots, + newslots, + DRM_MEM_QUEUES); + if (!dev->queuelist) { + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + DRM_DEBUG("out of memory\n"); + return -ENOMEM; + } + } + dev->queuelist[dev->queue_count-1] = queue; + + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + DRM_DEBUG("%d (new)\n", dev->queue_count - 1); + return dev->queue_count - 1; +} + +int drm_resctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_ctx_res_t res; + drm_ctx_t ctx; + int i; + int error; + + DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); + res = *(drm_ctx_res_t *) data; + if (res.count >= DRM_RESERVED_CONTEXTS) { + memset(&ctx, 0, sizeof(ctx)); + for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { + ctx.handle = i; + error = copyout(&i, &res.contexts[i], + sizeof(i)); + if (error) return error; + } + } + res.count = DRM_RESERVED_CONTEXTS; + *(drm_ctx_res_t *) data = res; + return 0; +} + + +int drm_addctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + if ((ctx.handle = drm_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { + /* Init kernel's context and get a new one. */ + drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx); + ctx.handle = drm_alloc_queue(dev); + } + drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx); + DRM_DEBUG("%d\n", ctx.handle); + *(drm_ctx_t *) data = ctx; + return 0; +} + +int drm_modctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + drm_queue_t *q; + + ctx = *(drm_ctx_t *) data; + + DRM_DEBUG("%d\n", ctx.handle); + + if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL; + q = dev->queuelist[ctx.handle]; + + atomic_inc(&q->use_count); + if (atomic_read(&q->use_count) == 1) { + /* No longer in use */ + atomic_dec(&q->use_count); + return -EINVAL; + } + + if (DRM_BUFCOUNT(&q->waitlist)) { + atomic_dec(&q->use_count); + return -EBUSY; + } + + q->flags = ctx.flags; + + atomic_dec(&q->use_count); + return 0; +} + +int drm_getctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + drm_queue_t *q; + + ctx = *(drm_ctx_t *) data; + + DRM_DEBUG("%d\n", ctx.handle); + + if (ctx.handle >= dev->queue_count) return -EINVAL; + q = dev->queuelist[ctx.handle]; + + atomic_inc(&q->use_count); + if (atomic_read(&q->use_count) == 1) { + /* No longer in use */ + atomic_dec(&q->use_count); + return -EINVAL; + } + + ctx.flags = q->flags; + atomic_dec(&q->use_count); + + *(drm_ctx_t *) data = ctx; + + return 0; +} + +int drm_switchctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + DRM_DEBUG("%d\n", ctx.handle); + return drm_context_switch(dev, dev->last_context, ctx.handle); +} + +int drm_newctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + DRM_DEBUG("%d\n", ctx.handle); + drm_context_switch_complete(dev, ctx.handle); + + return 0; +} + +int drm_rmctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + drm_queue_t *q; + drm_buf_t *buf; + + ctx = *(drm_ctx_t *) data; + DRM_DEBUG("%d\n", ctx.handle); + + if (ctx.handle >= dev->queue_count) return -EINVAL; + q = dev->queuelist[ctx.handle]; + + atomic_inc(&q->use_count); + if (atomic_read(&q->use_count) == 1) { + /* No longer in use */ + atomic_dec(&q->use_count); + return -EINVAL; + } + + atomic_inc(&q->finalization); /* Mark queue in finalization state */ + atomic_sub(2, &q->use_count); /* Mark queue as unused (pending + finalization) */ + + /* Wait while interrupt servicing is in progress */ + while (test_and_set_bit(0, &dev->interrupt_flag)) { + int never; + int error = tsleep(&never, PZERO|PCATCH, "drmrc", 1); + if (error) { + clear_bit(0, &dev->interrupt_flag); + return error; + } + } + /* Remove queued buffers */ + while ((buf = drm_waitlist_get(&q->waitlist))) { + drm_free_buffer(dev, buf); + } + clear_bit(0, &dev->interrupt_flag); + + /* Wakeup blocked processes */ + wakeup(&q->read_queue); + wakeup(&q->write_queue); + wakeup(&q->flush_queue); + + /* Finalization over. Queue is made + available when both use_count and + finalization become 0, which won't + happen until all the waiting processes + stop waiting. */ + atomic_dec(&q->finalization); + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/dma.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/dma.c new file mode 100644 index 000000000..149f45934 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/dma.c @@ -0,0 +1,534 @@ +/* dma.c -- DMA IOCTL and function support -*- c -*- + * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com + * Revised: Thu Sep 16 12:55:39 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/dma.c,v 1.7 1999/09/16 16:56:18 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/dma.c,v 1.1 1999/09/25 14:37:58 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +void drm_dma_setup(drm_device_t *dev) +{ + int i; + + dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER); + memset(dev->dma, 0, sizeof(*dev->dma)); + for (i = 0; i <= DRM_MAX_ORDER; i++) + memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0])); +} + +void drm_dma_takedown(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i, j; + + if (!dma) return; + + /* Clear dma buffers */ + for (i = 0; i <= DRM_MAX_ORDER; i++) { + if (dma->bufs[i].seg_count) { + DRM_DEBUG("order %d: buf_count = %d," + " seg_count = %d\n", + i, + dma->bufs[i].buf_count, + dma->bufs[i].seg_count); + for (j = 0; j < dma->bufs[i].seg_count; j++) { + drm_free_pages(dma->bufs[i].seglist[j], + dma->bufs[i].page_order, + DRM_MEM_DMA); + } + drm_free(dma->bufs[i].buflist, + dma->buf_count + * sizeof(*dma->bufs[0].buflist), + DRM_MEM_BUFS); + drm_free(dma->bufs[i].seglist, + dma->buf_count + * sizeof(*dma->bufs[0].seglist), + DRM_MEM_SEGS); + drm_freelist_destroy(&dma->bufs[i].freelist); + } + } + + if (dma->buflist) { + drm_free(dma->buflist, + dma->buf_count * sizeof(*dma->buflist), + DRM_MEM_BUFS); + } + + if (dma->pagelist) { + drm_free(dma->pagelist, + dma->page_count * sizeof(*dma->pagelist), + DRM_MEM_PAGES); + } + drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER); + dev->dma = NULL; +} + +#if DRM_DMA_HISTOGRAM +/* This is slow, but is useful for debugging. */ +int drm_histogram_slot(struct timespec *ts) +{ + long count = ts->tv_sec * 1000 + ts->tv_nsec / 1000000; + int value = DRM_DMA_HISTOGRAM_INITIAL; + int slot; + + for (slot = 0; + slot < DRM_DMA_HISTOGRAM_SLOTS; + ++slot, value = DRM_DMA_HISTOGRAM_NEXT(value)) { + if (count < value) return slot; + } + return DRM_DMA_HISTOGRAM_SLOTS - 1; +} + +void drm_histogram_compute(drm_device_t *dev, drm_buf_t *buf) +{ + struct timespec queued_to_dispatched; + struct timespec dispatched_to_completed; + struct timespec completed_to_freed; + int q2d, d2c, c2f, q2c, q2f; + + if (timespecisset(&buf->time_queued)) { + queued_to_dispatched = buf->time_dispatched; + timespecsub(&queued_to_dispatched, &buf->time_queued); + dispatched_to_completed = buf->time_completed; + timespecsub(&dispatched_to_completed, &buf->time_dispatched); + completed_to_freed = buf->time_freed; + timespecsub(&completed_to_freed, &buf->time_completed); + + q2d = drm_histogram_slot(&queued_to_dispatched); + d2c = drm_histogram_slot(&dispatched_to_completed); + c2f = drm_histogram_slot(&completed_to_freed); + + timespecadd(&queued_to_dispatched, &dispatched_to_completed); + q2c = drm_histogram_slot(&queued_to_dispatched); + timespecadd(&queued_to_dispatched, &completed_to_freed); + q2f = drm_histogram_slot(&queued_to_dispatched); + + atomic_inc(&dev->histo.total); + atomic_inc(&dev->histo.queued_to_dispatched[q2d]); + atomic_inc(&dev->histo.dispatched_to_completed[d2c]); + atomic_inc(&dev->histo.completed_to_freed[c2f]); + + atomic_inc(&dev->histo.queued_to_completed[q2c]); + atomic_inc(&dev->histo.queued_to_freed[q2f]); + + } + timespecclear(&buf->time_queued); + timespecclear(&buf->time_dispatched); + timespecclear(&buf->time_completed); + timespecclear(&buf->time_freed); +} +#endif + +void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf) +{ + drm_device_dma_t *dma = dev->dma; + + if (!buf) return; + + buf->waiting = 0; + buf->pending = 0; + buf->pid = 0; + buf->used = 0; +#if DRM_DMA_HISTOGRAMxx + buf->time_completed = get_cycles(); +#endif + if (buf->dma_wait) { + buf->dma_wait = 0; + wakeup(&buf->dma_wait); + } else { + /* If processes are waiting, the last one + to wake will put the buffer on the free + list. If no processes are waiting, we + put the buffer on the freelist here. */ + drm_freelist_put(dev, &dma->bufs[buf->order].freelist, buf); + } +} + +void drm_reclaim_buffers(drm_device_t *dev, pid_t pid) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + if (!dma) return; + for (i = 0; i < dma->buf_count; i++) { + if (dma->buflist[i]->pid == pid) { + switch (dma->buflist[i]->list) { + case DRM_LIST_NONE: + drm_free_buffer(dev, dma->buflist[i]); + break; + case DRM_LIST_WAIT: + dma->buflist[i]->list = DRM_LIST_RECLAIM; + break; + default: + /* Buffer already on hardware. */ + break; + } + } + } +} + +int drm_context_switch(drm_device_t *dev, int old, int new) +{ + char buf[64]; + drm_queue_t *q; + + atomic_inc(&dev->total_ctx); + + if (test_and_set_bit(0, &dev->context_flag)) { + DRM_ERROR("Reentering -- FIXME\n"); + return EBUSY; + } + +#if DRM_DMA_HISTOGRAM + getnanotime(&dev->ctx_start); +#endif + + DRM_DEBUG("Context switch from %d to %d\n", old, new); + + if (new >= dev->queue_count) { + clear_bit(0, &dev->context_flag); + return EINVAL; + } + + if (new == dev->last_context) { + clear_bit(0, &dev->context_flag); + return 0; + } + + q = dev->queuelist[new]; + atomic_inc(&q->use_count); + if (atomic_read(&q->use_count) == 1) { + atomic_dec(&q->use_count); + clear_bit(0, &dev->context_flag); + return EINVAL; + } + + if (drm_flags & DRM_FLAG_NOCTX) { + drm_context_switch_complete(dev, new); + } else { + sprintf(buf, "C %d %d\n", old, new); + drm_write_string(dev, buf); + } + + atomic_dec(&q->use_count); + + return 0; +} + +int drm_context_switch_complete(drm_device_t *dev, int new) +{ + drm_device_dma_t *dma = dev->dma; + + dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ + dev->last_switch = ticks; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("Lock isn't held after context switch\n"); + } + + if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("Cannot free lock\n"); + } + } + +#if DRM_DMA_HISTOGRAM + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &dev->ctx_start); + atomic_inc(&dev->histo.ctx[drm_histogram_slot(&ts)]); + } +#endif + clear_bit(0, &dev->context_flag); + wakeup(&dev->context_wait); + + return 0; +} + +void drm_clear_next_buffer(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + + dma->next_buffer = NULL; + if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) { + wakeup(&dma->next_queue->flush_queue); + } + dma->next_queue = NULL; +} + + +int drm_select_queue(drm_device_t *dev, void (*wrapper)(void *)) +{ + int i; + int candidate = -1; + int j = ticks; + + if (!dev) { + DRM_ERROR("No device\n"); + return -1; + } + if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) { + /* This only happens between the time the + interrupt is initialized and the time + the queues are initialized. */ + return -1; + } + + /* Doing "while locked" DMA? */ + if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) { + return DRM_KERNEL_CONTEXT; + } + + /* If there are buffers on the last_context + queue, and we have not been executing + this context very long, continue to + execute this context. */ + if (dev->last_switch <= j + && dev->last_switch + DRM_TIME_SLICE > j + && DRM_WAITCOUNT(dev, dev->last_context)) { + return dev->last_context; + } + + /* Otherwise, find a candidate */ + for (i = dev->last_checked + 1; i < dev->queue_count; i++) { + if (DRM_WAITCOUNT(dev, i)) { + candidate = dev->last_checked = i; + break; + } + } + + if (candidate < 0) { + for (i = 0; i < dev->queue_count; i++) { + if (DRM_WAITCOUNT(dev, i)) { + candidate = dev->last_checked = i; + break; + } + } + } + + if (wrapper + && candidate >= 0 + && candidate != dev->last_context + && dev->last_switch <= j + && dev->last_switch + DRM_TIME_SLICE > j) { + int s = splclock(); + if (dev->timer.c_time != dev->last_switch + DRM_TIME_SLICE) { + callout_reset(&dev->timer, + dev->last_switch + DRM_TIME_SLICE - j, + wrapper, + dev); + } + splx(s); + return -1; + } + + return candidate; +} + + +int drm_dma_enqueue(drm_device_t *dev, drm_dma_t *d) +{ + int i; + drm_queue_t *q; + drm_buf_t *buf; + int idx; + int while_locked = 0; + drm_device_dma_t *dma = dev->dma; + int error; + + DRM_DEBUG("%d\n", d->send_count); + + if (d->flags & _DRM_DMA_WHILE_LOCKED) { + int context = dev->lock.hw_lock->lock; + + if (!_DRM_LOCK_IS_HELD(context)) { + DRM_ERROR("No lock held during \"while locked\"" + " request\n"); + return EINVAL; + } + if (d->context != _DRM_LOCKING_CONTEXT(context) + && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) { + DRM_ERROR("Lock held by %d while %d makes" + " \"while locked\" request\n", + _DRM_LOCKING_CONTEXT(context), + d->context); + return EINVAL; + } + q = dev->queuelist[DRM_KERNEL_CONTEXT]; + while_locked = 1; + } else { + q = dev->queuelist[d->context]; + } + + + atomic_inc(&q->use_count); + if (atomic_read(&q->block_write)) { + atomic_inc(&q->block_count); + for (;;) { + if (!atomic_read(&q->block_write)) break; + error = tsleep(&q->block_write, PZERO|PCATCH, + "dmawr", 0); + if (error) { + atomic_dec(&q->use_count); + return error; + } + } + atomic_dec(&q->block_count); + } + + for (i = 0; i < d->send_count; i++) { + idx = d->send_indices[i]; + if (idx < 0 || idx >= dma->buf_count) { + atomic_dec(&q->use_count); + DRM_ERROR("Index %d (of %d max)\n", + d->send_indices[i], dma->buf_count - 1); + return EINVAL; + } + buf = dma->buflist[ idx ]; + if (buf->pid != curproc->p_pid) { + atomic_dec(&q->use_count); + DRM_ERROR("Process %d using buffer owned by %d\n", + curproc->p_pid, buf->pid); + return EINVAL; + } + if (buf->list != DRM_LIST_NONE) { + atomic_dec(&q->use_count); + DRM_ERROR("Process %d using buffer %d on list %d\n", + curproc->p_pid, buf->idx, buf->list); + } + buf->used = d->send_sizes[i]; + buf->while_locked = while_locked; + buf->context = d->context; + if (!buf->used) { + DRM_ERROR("Queueing 0 length buffer\n"); + } + if (buf->pending) { + atomic_dec(&q->use_count); + DRM_ERROR("Queueing pending buffer:" + " buffer %d, offset %d\n", + d->send_indices[i], i); + return EINVAL; + } + if (buf->waiting) { + atomic_dec(&q->use_count); + DRM_ERROR("Queueing waiting buffer:" + " buffer %d, offset %d\n", + d->send_indices[i], i); + return EINVAL; + } + buf->waiting = 1; + if (atomic_read(&q->use_count) == 1 + || atomic_read(&q->finalization)) { + drm_free_buffer(dev, buf); + } else { + drm_waitlist_put(&q->waitlist, buf); + atomic_inc(&q->total_queued); + } + } + atomic_dec(&q->use_count); + + return 0; +} + +static int drm_dma_get_buffers_of_order(drm_device_t *dev, drm_dma_t *d, + int order) +{ + int i; + int error; + drm_buf_t *buf; + drm_device_dma_t *dma = dev->dma; + + for (i = d->granted_count; i < d->request_count; i++) { + buf = drm_freelist_get(&dma->bufs[order].freelist, + d->flags & _DRM_DMA_WAIT); + if (!buf) break; + if (buf->pending || buf->waiting) { + DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n", + buf->idx, + buf->pid, + buf->waiting, + buf->pending); + } + buf->pid = curproc->p_pid; + error = copyout(&buf->idx, + &d->request_indices[i], + sizeof(buf->idx)); + if (error) + return error; + error = copyout(&buf->total, + &d->request_sizes[i], + sizeof(buf->total)); + if (error) + return error; + ++d->granted_count; + } + return 0; +} + + +int drm_dma_get_buffers(drm_device_t *dev, drm_dma_t *dma) +{ + int order; + int retcode = 0; + int tmp_order; + + order = drm_order(dma->request_size); + + dma->granted_count = 0; + retcode = drm_dma_get_buffers_of_order(dev, dma, order); + + if (dma->granted_count < dma->request_count + && (dma->flags & _DRM_DMA_SMALLER_OK)) { + for (tmp_order = order - 1; + !retcode + && dma->granted_count < dma->request_count + && tmp_order >= DRM_MIN_ORDER; + --tmp_order) { + + retcode = drm_dma_get_buffers_of_order(dev, dma, + tmp_order); + } + } + + if (dma->granted_count < dma->request_count + && (dma->flags & _DRM_DMA_LARGER_OK)) { + for (tmp_order = order + 1; + !retcode + && dma->granted_count < dma->request_count + && tmp_order <= DRM_MAX_ORDER; + ++tmp_order) { + + retcode = drm_dma_get_buffers_of_order(dev, dma, + tmp_order); + } + } + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/drawable.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/drawable.c new file mode 100644 index 000000000..d8005af6a --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/drawable.c @@ -0,0 +1,50 @@ +/* drawable.c -- IOCTLs for drawables -*- c -*- + * Created: Tue Feb 2 08:37:54 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 09:27:03 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drawable.c,v 1.3 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drawable.c,v 1.1 1999/09/25 14:37:58 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +int drm_adddraw(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_draw_t draw; + + draw.handle = 0; /* NOOP */ + DRM_DEBUG("%d\n", draw.handle); + *(drm_draw_t *) data = draw; + return 0; +} + +int drm_rmdraw(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + return 0; /* NOOP */ +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/drmstat.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/drmstat.c new file mode 100644 index 000000000..0ce76b01a --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/drmstat.c @@ -0,0 +1,418 @@ +/* drmstat.c -- DRM device status and testing program + * Created: Tue Jan 5 08:19:24 1999 by faith@precisioninsight.com + * Revised: Sun Aug 1 11:02:00 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmstat.c,v 1.28 1999/08/04 18:12:11 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmstat.c,v 1.1 1999/09/25 14:37:59 dawes Exp $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <strings.h> +#include <errno.h> +#include <signal.h> +#include <fcntl.h> +#include "xf86drm.h" + +int sigio_fd; + +static double usec(struct timeval *end, struct timeval *start) +{ + double e = end->tv_sec * 1000000 + end->tv_usec; + double s = start->tv_sec * 1000000 + start->tv_usec; + + return e - s; +} + +static void getversion(int fd) +{ + drmVersionPtr version; + + version = drmGetVersion(fd); + if (version) { + printf( "Name: %s\n", version->name ? version->name : "?" ); + printf( " Version: %d.%d.%d\n", + version->version_major, + version->version_minor, + version->version_patchlevel ); + printf( " Date: %s\n", version->date ? version->date : "?" ); + printf( " Desc: %s\n", version->desc ? version->desc : "?" ); + drmFreeVersion(version); + } else { + printf( "No driver available\n" ); + } +} + +void handler(int fd, void *oldctx, void *newctx) +{ + printf("Got fd %d\n", fd); +} + +void process_sigio(char *device) +{ + int fd; + +printf("%s\n", device); + if ((fd = open(device, 0)) < 0) { +printf("%d\n", errno); + drmError(-errno, __FUNCTION__); + exit(1); + } + + sigio_fd = fd; + drmInstallSIGIOHandler(fd, handler); + for (;;) sleep(60); +} + +int main(int argc, char **argv) +{ + int c; + int r = 0; + int fd = -1; + drmHandle handle; + void *address; + char *pt; + unsigned long count; + unsigned long offset; + unsigned long size; + drmContext context; + int loops; + char buf[1024]; + int i; + drmBufInfoPtr info; + drmBufMapPtr bufs; + drmLockPtr lock; + int secs; + + while ((c = getopt(argc, argv, + "lc:vo:O:f:s:w:W:b:r:R:P:L:C:XS:B:F:")) != EOF) + switch (c) { + case 'F': + count = strtoul(optarg, NULL, 0); + if (!fork()) { + dup(fd); + sleep(count); + } + close(fd); + break; + case 'v': getversion(fd); break; + case 'X': + if ((r = drmCreateContext(fd, &context))) { + drmError(r, argv[0]); + return 1; + } + printf( "Got %d\n", context); + break; + case 'S': + process_sigio(optarg); + break; + case 'C': + if ((r = drmSwitchToContext(fd, strtoul(optarg, NULL, 0)))) { + drmError(r, argv[0]); + return 1; + } + break; + case 'c': + if ((r = drmSetBusid(fd,optarg))) { + drmError(r, argv[0]); + return 1; + } + break; + case 'o': + if ((fd = drmOpen(optarg, NULL)) < 0) { + drmError(fd, argv[0]); + return 1; + } + break; + case 'O': + if ((fd = drmOpen(NULL, optarg)) < 0) { + drmError(fd, argv[0]); + return 1; + } + break; + case 'B': /* Test buffer allocation */ + count = strtoul(optarg, &pt, 0); + size = strtoul(pt+1, &pt, 0); + secs = strtoul(pt+1, NULL, 0); + { + drmDMAReq dma; + int *indices, *sizes; + + indices = alloca(sizeof(*indices) * count); + sizes = alloca(sizeof(*sizes) * count); + dma.context = context; + dma.send_count = 0; + dma.request_count = count; + dma.request_size = size; + dma.request_list = indices; + dma.request_sizes = sizes; + dma.flags = DRM_DMA_WAIT; + if ((r = drmDMA(fd, &dma))) { + drmError(r, argv[0]); + return 1; + } + for (i = 0; i < dma.granted_count; i++) { + printf("%5d: index = %d, size = %d\n", + i, dma.request_list[i], dma.request_sizes[i]); + } + sleep(secs); + drmFreeBufs(fd, dma.granted_count, indices); + } + break; + case 'b': + count = strtoul(optarg, &pt, 0); + size = strtoul(pt+1, NULL, 0); + if ((r = drmAddBufs(fd, count, size, 0, 0)) < 0) { + drmError(r, argv[0]); + return 1; + } + if (!(info = drmGetBufInfo(fd))) { + drmError(0, argv[0]); + return 1; + } + for (i = 0; i < info->count; i++) { + printf("%5d buffers of size %6d (low = %d, high = %d)\n", + info->list[i].count, + info->list[i].size, + info->list[i].low_mark, + info->list[i].high_mark); + } + if ((r = drmMarkBufs(fd, 0.50, 0.80))) { + drmError(r, argv[0]); + return 1; + } + if (!(info = drmGetBufInfo(fd))) { + drmError(0, argv[0]); + return 1; + } + for (i = 0; i < info->count; i++) { + printf("%5d buffers of size %6d (low = %d, high = %d)\n", + info->list[i].count, + info->list[i].size, + info->list[i].low_mark, + info->list[i].high_mark); + } + printf("===== /proc/drm/1/meminfo =====\n"); + sprintf(buf, "cat /proc/drm/1/meminfo"); + system(buf); +#if 1 + if (!(bufs = drmMapBufs(fd))) { + drmError(0, argv[0]); + return 1; + } + printf("===============================\n"); + printf( "%d bufs\n", bufs->count); + for (i = 0; i < bufs->count; i++) { + printf( " %4d: %8d bytes at %p\n", + i, + bufs->list[i].total, + bufs->list[i].address); + } + printf("===== /proc/drm/1/vmainfo =====\n"); + sprintf(buf, "cat /proc/drm/1/vmainfo"); + system(buf); +#endif + break; + case 'f': + offset = strtoul(optarg, &pt, 0); + size = strtoul(pt+1, NULL, 0); + handle = 0; + if ((r = drmAddMap(fd, offset, size, + DRM_FRAME_BUFFER, 0, &handle))) { + drmError(r, argv[0]); + return 1; + } + printf("0x%08lx:0x%04lx added\n", offset, size); + printf("===== /proc/drm/1/meminfo =====\n"); + sprintf(buf, "cat /proc/drm/1/meminfo"); + system(buf); + break; + case 'r': + case 'R': + offset = strtoul(optarg, &pt, 0); + size = strtoul(pt+1, NULL, 0); + handle = 0; + if ((r = drmAddMap(fd, offset, size, + DRM_REGISTERS, + c == 'R' ? DRM_READ_ONLY : 0, + &handle))) { + drmError(r, argv[0]); + return 1; + } + printf("0x%08lx:0x%04lx added\n", offset, size); + printf("===== /proc/drm/1/meminfo =====\n"); + sprintf(buf, "cat /proc/drm/1/meminfo"); + system(buf); + break; + case 's': + size = strtoul(optarg, &pt, 0); + handle = 0; + if ((r = drmAddMap(fd, 0, size, + DRM_SHM, DRM_CONTAINS_LOCK, + &handle))) { + drmError(r, argv[0]); + return 1; + } + printf("0x%04lx byte shm added at 0x%08lx\n", size, handle); + sprintf(buf, "sysctl hw.graphics.0.vm"); + system(buf); + break; + case 'P': + offset = strtoul(optarg, &pt, 0); + size = strtoul(pt+1, NULL, 0); + address = NULL; + if ((r = drmMap(fd, offset, size, &address))) { + drmError(r, argv[0]); + return 1; + } + printf("0x%08lx:0x%04lx mapped at %p for pid %d\n", + offset, size, address, getpid()); + printf("===== hw.graphics.0.vma =====\n"); + sprintf(buf, "sysctl hw.graphics.0.vma"); + system(buf); + mprotect((void *)offset, size, PROT_READ); + printf("===== hw.graphics.0.vma =====\n"); + sprintf(buf, "sysctl hw.graphics.0.vma"); + system(buf); + break; + case 'w': + case 'W': + offset = strtoul(optarg, &pt, 0); + size = strtoul(pt+1, NULL, 0); + address = NULL; + if ((r = drmMap(fd, offset, size, &address))) { + drmError(r, argv[0]); + return 1; + } + printf("0x%08lx:0x%04lx mapped at %p for pid %d\n", + offset, size, address, getpid()); + printf("===== /proc/%d/maps =====\n", getpid()); + sprintf(buf, "cat /proc/%d/maps", getpid()); + system(buf); + printf("===== /proc/drm/1/meminfo =====\n"); + sprintf(buf, "cat /proc/drm/1/meminfo"); + system(buf); + printf("===== /proc/drm/1/vmainfo =====\n"); + sprintf(buf, "cat /proc/drm/1/vmainfo"); + system(buf); + printf("===== READING =====\n"); + for (i = 0; i < 0x10; i++) + printf("%02x ", (unsigned int)((unsigned char *)address)[i]); + printf("\n"); + if (c == 'w') { + printf("===== WRITING =====\n"); + for (i = 0; i < size; i+=2) { + ((char *)address)[i] = i & 0xff; + ((char *)address)[i+1] = i & 0xff; + } + } + printf("===== READING =====\n"); + for (i = 0; i < 0x10; i++) + printf("%02x ", (unsigned int)((unsigned char *)address)[i]); + printf("\n"); + printf("===== /proc/drm/1/vmainfo =====\n"); + sprintf(buf, "cat /proc/drm/1/vmainfo"); + system(buf); + break; + case 'L': + context = strtoul(optarg, &pt, 0); + offset = strtoul(pt+1, &pt, 0); + size = strtoul(pt+1, &pt, 0); + loops = strtoul(pt+1, NULL, 0); + address = NULL; + if ((r = drmMap(fd, offset, size, &address))) { + drmError(r, argv[0]); + return 1; + } + lock = address; +#if 1 + { + int counter = 0; + struct timeval loop_start, loop_end; + struct timeval lock_start, lock_end; + double wt; +#define HISTOSIZE 9 + int histo[HISTOSIZE]; + int output = 0; + int fast = 0; + + if (loops < 0) { + loops = -loops; + ++output; + } + + for (i = 0; i < HISTOSIZE; i++) histo[i] = 0; + + gettimeofday(&loop_start, NULL); + for (i = 0; i < loops; i++) { + gettimeofday(&lock_start, NULL); + DRM_LIGHT_LOCK_COUNT(fd,lock,context,fast); + gettimeofday(&lock_end, NULL); + DRM_UNLOCK(fd,lock,context); + ++counter; + wt = usec(&lock_end, &lock_start); + if (wt <= 2.5) ++histo[8]; + if (wt < 5.0) ++histo[0]; + else if (wt < 50.0) ++histo[1]; + else if (wt < 500.0) ++histo[2]; + else if (wt < 5000.0) ++histo[3]; + else if (wt < 50000.0) ++histo[4]; + else if (wt < 500000.0) ++histo[5]; + else if (wt < 5000000.0) ++histo[6]; + else ++histo[7]; + if (output) printf( "%.2f uSec, %d fast\n", wt, fast); + } + gettimeofday(&loop_end, NULL); + printf( "Average wait time = %.2f usec, %d fast\n", + usec(&loop_end, &loop_start) / counter, fast); + printf( "%9d <= 2.5 uS\n", histo[8]); + printf( "%9d < 5 uS\n", histo[0]); + printf( "%9d < 50 uS\n", histo[1]); + printf( "%9d < 500 uS\n", histo[2]); + printf( "%9d < 5000 uS\n", histo[3]); + printf( "%9d < 50000 uS\n", histo[4]); + printf( "%9d < 500000 uS\n", histo[5]); + printf( "%9d < 5000000 uS\n", histo[6]); + printf( "%9d >= 5000000 uS\n", histo[7]); + } +#else + printf( "before lock: 0x%08x\n", lock->lock); + printf( "lock: 0x%08x\n", lock->lock); + sleep(5); + printf( "unlock: 0x%08x\n", lock->lock); +#endif + break; + default: + fprintf( stderr, "Usage: drmstat [options]\n" ); + return 1; + } + + return r; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/fops.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/fops.c new file mode 100644 index 000000000..837fc7db0 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/fops.c @@ -0,0 +1,260 @@ +/* fops.c -- File operations for DRM -*- c -*- + * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com + * Revised: Tue Oct 12 08:48:59 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/fops.c,v 1.3 1999/08/20 15:36:45 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/fops.c,v 1.1 1999/09/25 14:37:59 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include <sys/signalvar.h> +#include <sys/poll.h> + +drm_file_t *drm_find_file_by_proc(drm_device_t *dev, struct proc *p) +{ + uid_t uid = p->p_cred->p_svuid; + pid_t pid = p->p_pid; + drm_file_t *priv; + + TAILQ_FOREACH(priv, &dev->files, link) + if (priv->pid == pid && priv->uid == uid) + return priv; + return NULL; +} + + +/* drm_open is called whenever a process opens /dev/drm. */ + +int drm_open_helper(dev_t kdev, int flags, int fmt, struct proc *p, + drm_device_t *dev) +{ + int m = minor(kdev); + drm_file_t *priv; + + if (flags & O_EXCL) + return EBUSY; /* No exclusive opens */ + + dev->flags = flags; + + DRM_DEBUG("pid = %d, device = %p, minor = %d\n", + p->p_pid, dev->device, m); + + priv = drm_find_file_by_proc(dev, p); + if (priv) { + priv->refs++; + } else { + priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES); + memset(priv, 0, sizeof(*priv)); + priv->uid = p->p_cred->p_svuid; + priv->pid = p->p_pid; + priv->refs = 1; + priv->minor = m; + priv->devXX = dev; + priv->ioctl_count = 0; + priv->authenticated = !suser(p); + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, p); + TAILQ_INSERT_TAIL(&dev->files, priv, link); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, p); + } + + kdev->si_drv1 = dev; + + return 0; +} + +int drm_write(dev_t kdev, struct uio *uio, int ioflag) +{ + struct proc *p = curproc; + drm_device_t *dev = kdev->si_drv1; + + DRM_DEBUG("pid = %d, device = %p, open_count = %d\n", + p->p_pid, dev->device, dev->open_count); + return 0; +} + +/* drm_release is called whenever a process closes /dev/drm*. */ + +int drm_close(dev_t kdev, int fflag, int devtype, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_file_t *priv; + + DRM_DEBUG("pid = %d, device = %p, open_count = %d\n", + p->p_pid, dev->device, dev->open_count); + + priv = drm_find_file_by_proc(dev, p); + if (!priv) { + DRM_DEBUG("can't find authenticator\n"); + return EINVAL; + } + + if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) + && dev->lock.pid == p->p_pid) { + DRM_ERROR("Process %d dead, freeing lock for context %d\n", + p->p_pid, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + drm_lock_free(dev, + &dev->lock.hw_lock->lock, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + + /* FIXME: may require heavy-handed reset of + hardware at this point, possibly + processed via a callback to the X + server. */ + } + drm_reclaim_buffers(dev, priv->pid); + + funsetown(dev->buf_sigio); + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, p); + priv = drm_find_file_by_proc(dev, p); + if (priv) { + priv->refs--; + if (!priv->refs) { + TAILQ_REMOVE(&dev->files, priv, link); + drm_free(priv, sizeof(*priv), DRM_MEM_FILES); + } + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, p); + + return 0; +} + +/* The drm_read and drm_write_string code (especially that which manages + the circular buffer), is based on Alessandro Rubini's LINUX DEVICE + DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */ + +ssize_t drm_read(dev_t kdev, struct uio *uio, int ioflag) +{ + drm_device_t *dev = kdev->si_drv1; + int left; + int avail; + int send; + int cur; + int error = 0; + + DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp); + + while (dev->buf_rp == dev->buf_wp) { + DRM_DEBUG(" sleeping\n"); + if (dev->flags & FASYNC) { + return EWOULDBLOCK; + } + error = tsleep(&dev->buf_rp, PZERO|PCATCH, "drmrd", 0); + if (error) { + DRM_DEBUG(" interrupted\n"); + return error; + } + DRM_DEBUG(" awake\n"); + } + + left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ; + avail = DRM_BSZ - left; + send = DRM_MIN(avail, uio->uio_resid); + + while (send) { + if (dev->buf_wp > dev->buf_rp) { + cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp); + } else { + cur = DRM_MIN(send, dev->buf_end - dev->buf_rp); + } + error = uiomove(dev->buf_rp, cur, uio); + if (error) + break; + dev->buf_rp += cur; + if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf; + send -= cur; + } + + wakeup(&dev->buf_wp); + + return error; +} + +int drm_write_string(drm_device_t *dev, const char *s) +{ + int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ; + int send = strlen(s); + int count; + + DRM_DEBUG("%d left, %d to send (%p, %p)\n", + left, send, dev->buf_rp, dev->buf_wp); + + if (left == 1 || dev->buf_wp != dev->buf_rp) { + DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n", + left, + dev->buf_wp, + dev->buf_rp); + } + + while (send) { + if (dev->buf_wp >= dev->buf_rp) { + count = DRM_MIN(send, dev->buf_end - dev->buf_wp); + if (count == left) --count; /* Leave a hole */ + } else { + count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1); + } + strncpy(dev->buf_wp, s, count); + dev->buf_wp += count; + if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf; + send -= count; + } + + if (dev->buf_selecting) { + dev->buf_selecting = 0; + selwakeup(&dev->buf_sel); + } + + DRM_DEBUG("dev->buf_sigio=%p\n", dev->buf_sigio); + if (dev->buf_sigio) { + DRM_DEBUG("dev->buf_sigio->sio_pgid=%d\n", dev->buf_sigio->sio_pgid); + pgsigio(dev->buf_sigio, SIGIO, 0); + } + + DRM_DEBUG("waking\n"); + wakeup(&dev->buf_rp); + return 0; +} + +int drm_poll(dev_t kdev, int events, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + int s; + int revents = 0; + + s = spldrm(); + if (events & (POLLIN | POLLRDNORM)) { + int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ; + if (left > 0) + revents |= events & (POLLIN | POLLRDNORM); + else + selrecord(p, &dev->buf_sel); + } + splx(s); + + return revents; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/init.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/init.c new file mode 100644 index 000000000..44e9be995 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/init.c @@ -0,0 +1,101 @@ +/* init.c -- Setup/Cleanup for DRM -*- c -*- + * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 09:27:02 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/init.c,v 1.3 1999/08/20 15:07:01 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/init.c,v 1.1 1999/09/25 14:38:01 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +MODULE_VERSION(drm, 1); + +int drm_flags = 0; + +/* drm_parse_option parses a single option. See description for + drm_parse_drm for details. */ + +static void drm_parse_option(char *s) +{ + char *c, *r; + + DRM_DEBUG("\"%s\"\n", s); + if (!s || !*s) return; + for (c = s; *c && *c != ':'; c++); /* find : or \0 */ + if (*c) r = c + 1; else r = NULL; /* remember remainder */ + *c = '\0'; /* terminate */ + if (!strcmp(s, "noctx")) { + drm_flags |= DRM_FLAG_NOCTX; + DRM_INFO("Server-mediated context switching OFF\n"); + return; + } + if (!strcmp(s, "debug")) { + drm_flags |= DRM_FLAG_DEBUG; + DRM_INFO("Debug messages ON\n"); + return; + } + DRM_ERROR("\"%s\" is not a valid option\n", s); + return; +} + +/* drm_parse_options parse the insmod "drm=" options, or the command-line + * options passed to the kernel via LILO. The grammar of the format is as + * follows: + * + * drm ::= 'drm=' option_list + * option_list ::= option [ ';' option_list ] + * option ::= 'device:' major + * | 'debug' + * | 'noctx' + * major ::= INTEGER + * + * Note that 's' contains option_list without the 'drm=' part. + * + * device=major,minor specifies the device number used for /dev/drm + * if major == 0 then the misc device is used + * if major == 0 and minor == 0 then dynamic misc allocation is used + * debug=on specifies that debugging messages will be printk'd + * debug=trace specifies that each function call will be logged via printk + * debug=off turns off all debugging options + * + */ + +void drm_parse_options(char *s) +{ + char *h, *t, *n; + + DRM_DEBUG("\"%s\"\n", s ?: ""); + if (!s || !*s) return; + + for (h = t = n = s; h && *h; h = n) { + for (; *t && *t != ';'; t++); /* find ; or \0 */ + if (*t) n = t + 1; else n = NULL; /* remember next */ + *t = '\0'; /* terminate */ + drm_parse_option(h); /* parse */ + } +} + diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/ioctl.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/ioctl.c new file mode 100644 index 000000000..55bdeedac --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/ioctl.c @@ -0,0 +1,120 @@ +/* ioctl.c -- IOCTL processing for DRM -*- c -*- + * Created: Fri Jan 8 09:01:26 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 09:27:02 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/ioctl.c,v 1.3 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/ioctl.c,v 1.1 1999/09/25 14:38:01 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include <sys/bus.h> +#include <pci/pcivar.h> + +int +drm_irq_busid(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_irq_busid_t id; + devclass_t pci; + device_t bus, dev; + device_t *kids; + int error, i, num_kids; + + id = *(drm_irq_busid_t *) data; + pci = devclass_find("pci"); + if (!pci) + return ENOENT; + bus = devclass_get_device(pci, id.busnum); + if (!bus) + return ENOENT; + error = device_get_children(bus, &kids, &num_kids); + if (error) + return error; + + dev = 0; + for (i = 0; i < num_kids; i++) { + dev = kids[i]; + if (pci_get_slot(dev) == id.devnum + && pci_get_function(dev) == id.funcnum) + break; + } + + free(kids, M_TEMP); + + if (i != num_kids) + id.irq = pci_get_irq(dev); + else + id.irq = 0; + + DRM_DEBUG("%d:%d:%d => IRQ %d\n", + id.busnum, id.devnum, id.funcnum, id.irq); + *(drm_irq_busid_t *) data = id; + + return 0; +} + +int +drm_getunique(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_unique_t u; + int error; + + u = *(drm_unique_t *) data; + if (u.unique_len >= dev->unique_len) { + error = copyout(dev->unique, u.unique, dev->unique_len); + if (error) + return error; + } + u.unique_len = dev->unique_len; + *(drm_unique_t *) data = u; + return 0; +} + +int +drm_setunique(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_unique_t u; + int error; + + if (dev->unique_len || dev->unique) return EBUSY; + + u = *(drm_unique_t *) data; + + dev->unique_len = u.unique_len; + dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER); + error = copyin(u.unique, dev->unique, dev->unique_len); + if (error) + return error; + dev->unique[dev->unique_len] = '\0'; + + dev->devname = drm_alloc(strlen(dev->name) + strlen(dev->unique) + 2, + DRM_MEM_DRIVER); + sprintf(dev->devname, "%s@%s", dev->name, dev->unique); + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/lists.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/lists.c new file mode 100644 index 000000000..9f9b5f7ad --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/lists.c @@ -0,0 +1,258 @@ +/* lists.c -- Buffer list handling routines -*- c -*- + * Created: Mon Apr 19 20:54:22 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 09:27:01 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/lists.c,v 1.3 1999/08/20 15:07:02 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/lists.c,v 1.1 1999/09/25 14:38:01 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +int drm_waitlist_create(drm_waitlist_t *bl, int count) +{ + DRM_DEBUG("%d\n", count); + if (bl->count) return EINVAL; + + bl->count = count; + bl->bufs = drm_alloc((bl->count + 2) * sizeof(*bl->bufs), + DRM_MEM_BUFLISTS); + bl->rp = bl->bufs; + bl->wp = bl->bufs; + bl->end = &bl->bufs[bl->count+1]; + simple_lock_init(&bl->write_lock); + simple_lock_init(&bl->read_lock); + return 0; +} + +int drm_waitlist_destroy(drm_waitlist_t *bl) +{ + DRM_DEBUG("\n"); + if (bl->rp != bl->wp) return EINVAL; + if (bl->bufs) drm_free(bl->bufs, + (bl->count + 2) * sizeof(*bl->bufs), + DRM_MEM_BUFLISTS); + bl->count = 0; + bl->bufs = NULL; + bl->rp = NULL; + bl->wp = NULL; + bl->end = NULL; + return 0; +} + +int drm_waitlist_put(drm_waitlist_t *bl, drm_buf_t *buf) +{ + int left; + int s; + + left = DRM_LEFTCOUNT(bl); + DRM_DEBUG("put %d (%d left, rp = %p, wp = %p)\n", + buf->idx, left, bl->rp, bl->wp); + if (!left) { + DRM_ERROR("Overflow while adding buffer %d from pid %d\n", + buf->idx, buf->pid); + return EINVAL; + } +#if DRM_DMA_HISTOGRAM + getnanotime(&buf->time_queued); +#endif + buf->list = DRM_LIST_WAIT; + + simple_lock(&bl->write_lock); + s = spldrm(); + *bl->wp = buf; + if (++bl->wp >= bl->end) bl->wp = bl->bufs; + splx(s); + simple_unlock(&bl->write_lock); + + return 0; +} + +drm_buf_t *drm_waitlist_get(drm_waitlist_t *bl) +{ + drm_buf_t *buf; + int s; + + simple_lock(&bl->read_lock); + s = spldrm(); + buf = *bl->rp; + if (bl->rp == bl->wp) { + splx(s); + simple_unlock(&bl->read_lock); + return NULL; + } + if (++bl->rp >= bl->end) bl->rp = bl->bufs; + splx(s); + simple_unlock(&bl->read_lock); + + DRM_DEBUG("get %d\n", buf->idx); + return buf; +} + +int drm_freelist_create(drm_freelist_t *bl, int count) +{ + DRM_DEBUG("\n"); + atomic_set(&bl->count, 0); + bl->next = NULL; + bl->waiting = 0; + bl->low_mark = 0; + bl->high_mark = 0; + atomic_set(&bl->wfh, 0); + ++bl->initialized; + return 0; +} + +int drm_freelist_destroy(drm_freelist_t *bl) +{ + DRM_DEBUG("\n"); + atomic_set(&bl->count, 0); + bl->next = NULL; + return 0; +} + +int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf) +{ + unsigned int old; + unsigned int new; + char failed; + int count = 0; + drm_device_dma_t *dma = dev->dma; + + if (!dma) { + DRM_ERROR("No DMA support\n"); + return 1; + } + + if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) { + DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n", + buf->idx, buf->waiting, buf->pending, buf->list); + } + DRM_DEBUG("%d, count = %d, wfh = %d, w%d, p%d\n", + buf->idx, atomic_read(&bl->count), atomic_read(&bl->wfh), + buf->waiting, buf->pending); + if (!bl) return 1; +#if DRM_DMA_HISTOGRAM + getnanotime(&buf->time_freed); + drm_histogram_compute(dev, buf); +#endif + buf->list = DRM_LIST_FREE; + do { + old = (unsigned long)bl->next; + buf->next = (void *)old; + new = (unsigned long)buf; + _DRM_CAS(&bl->next, old, new, failed); + if (++count > DRM_LOOPING_LIMIT) { + DRM_ERROR("Looping\n"); + return 1; + } + } while (failed); + atomic_inc(&bl->count); + if (atomic_read(&bl->count) > dma->buf_count) { + DRM_ERROR("%d of %d buffers free after addition of %d\n", + atomic_read(&bl->count), dma->buf_count, buf->idx); + return 1; + } + /* Check for high water mark */ + if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) { + atomic_set(&bl->wfh, 0); + if (bl->waiting) + wakeup(&bl->waiting); + } + return 0; +} + +static drm_buf_t *drm_freelist_try(drm_freelist_t *bl) +{ + unsigned int old; + unsigned int new; + char failed; + drm_buf_t *buf; + int count = 0; + + if (!bl) return NULL; + + /* Get buffer */ + do { + old = (unsigned int)bl->next; + if (!old) { + return NULL; + } + new = (unsigned long)bl->next->next; + _DRM_CAS(&bl->next, old, new, failed); + if (++count > DRM_LOOPING_LIMIT) { + DRM_ERROR("Looping\n"); + return NULL; + } + } while (failed); + atomic_dec(&bl->count); + + buf = (drm_buf_t *)old; + buf->next = NULL; + buf->list = DRM_LIST_NONE; + DRM_DEBUG("%d, count = %d, wfh = %d, w%d, p%d\n", + buf->idx, atomic_read(&bl->count), atomic_read(&bl->wfh), + buf->waiting, buf->pending); + if (buf->waiting || buf->pending) { + DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n", + buf->idx, buf->waiting, buf->pending, buf->list); + } + + return buf; +} + +drm_buf_t *drm_freelist_get(drm_freelist_t *bl, int block) +{ + drm_buf_t *buf = NULL; + int error; + + if (!bl || !bl->initialized) return NULL; + + /* Check for low water mark */ + if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */ + atomic_set(&bl->wfh, 1); + if (atomic_read(&bl->wfh)) { + DRM_DEBUG("Block = %d, count = %d, wfh = %d\n", + block, atomic_read(&bl->count), + atomic_read(&bl->wfh)); + if (block) { + atomic_inc(&bl->waiting); + for (;;) { + if (!atomic_read(&bl->wfh) + && (buf = drm_freelist_try(bl))) break; + error = tsleep(&bl->waiting, PZERO|PCATCH, + "drmfg", 0); + if (error) + break; + } + atomic_dec(&bl->waiting); + } + return buf; + } + + DRM_DEBUG("Count = %d, wfh = %d\n", + atomic_read(&bl->count), atomic_read(&bl->wfh)); + return drm_freelist_try(bl); +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/lock.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/lock.c new file mode 100644 index 000000000..cd14a8825 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/lock.c @@ -0,0 +1,220 @@ +/* lock.c -- IOCTLs for locking -*- c -*- + * Created: Tue Feb 2 08:37:54 1999 by faith@precisioninsight.com + * Revised: Tue Oct 12 08:51:06 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/lock.c,v 1.5 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/lock.c,v 1.1 1999/09/25 14:38:01 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +int +drm_block(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + DRM_DEBUG("\n"); + return 0; +} + +int +drm_unblock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + DRM_DEBUG("\n"); + return 0; +} + +int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context) +{ + unsigned int old; + unsigned int new; + char failed; + + DRM_DEBUG("%d attempts\n", context); + do { + old = *lock; + if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT; + else new = context | _DRM_LOCK_HELD; + _DRM_CAS(lock, old, new, failed); + } while (failed); + if (_DRM_LOCKING_CONTEXT(old) == context) { + if (old & _DRM_LOCK_HELD) { + if (context != DRM_KERNEL_CONTEXT) { + DRM_ERROR("%d holds heavyweight lock\n", + context); + } + return 0; + } + } + if (new == (context | _DRM_LOCK_HELD)) { + /* Have lock */ + DRM_DEBUG("%d\n", context); + return 1; + } + DRM_DEBUG("%d unable to get lock held by %d\n", + context, _DRM_LOCKING_CONTEXT(old)); + return 0; +} + +/* This takes a lock forcibly and hands it to context. Should ONLY be used + inside *_unlock to give lock to kernel before calling *_dma_schedule. */ +int drm_lock_transfer(drm_device_t *dev, + __volatile__ unsigned int *lock, unsigned int context) +{ + unsigned int old; + unsigned int new; + char failed; + + dev->lock.pid = 0; + do { + old = *lock; + new = context | _DRM_LOCK_HELD; + _DRM_CAS(lock, old, new, failed); + } while (failed); + DRM_DEBUG("%d => %d\n", _DRM_LOCKING_CONTEXT(old), context); + return 1; +} + +int drm_lock_free(drm_device_t *dev, + __volatile__ unsigned int *lock, unsigned int context) +{ + unsigned int old; + unsigned int new; + char failed; + pid_t pid = dev->lock.pid; + + DRM_DEBUG("%d\n", context); + dev->lock.pid = 0; + do { + old = *lock; + new = 0; + _DRM_CAS(lock, old, new, failed); + } while (failed); + if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) { + DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n", + context, + _DRM_LOCKING_CONTEXT(old), + pid); + return 1; + } + wakeup(&dev->lock.lock_queue); + return 0; +} + +static int drm_flush_queue(drm_device_t *dev, int context) +{ + int ret = 0; + int error; + drm_queue_t *q = dev->queuelist[context]; + + DRM_DEBUG("\n"); + + atomic_inc(&q->use_count); + if (atomic_read(&q->use_count) > 1) { + atomic_inc(&q->block_write); + atomic_inc(&q->block_count); + error = tsleep(&q->flush_queue, PCATCH|PZERO, "drmfq", 0); + if (error) + return error; + atomic_dec(&q->block_count); + } + atomic_dec(&q->use_count); + atomic_inc(&q->total_flushed); + + /* NOTE: block_write is still incremented! + Use drm_flush_unlock_queue to decrement. */ + return ret; +} + +static int drm_flush_unblock_queue(drm_device_t *dev, int context) +{ + drm_queue_t *q = dev->queuelist[context]; + + DRM_DEBUG("\n"); + + atomic_inc(&q->use_count); + if (atomic_read(&q->use_count) > 1) { + if (atomic_read(&q->block_write)) { + atomic_dec(&q->block_write); + wakeup(&q->write_queue); + } + } + atomic_dec(&q->use_count); + return 0; +} + +int drm_flush_block_and_flush(drm_device_t *dev, int context, + drm_lock_flags_t flags) +{ + int ret = 0; + int i; + + DRM_DEBUG("\n"); + + if (flags & _DRM_LOCK_FLUSH) { + ret = drm_flush_queue(dev, DRM_KERNEL_CONTEXT); + if (!ret) ret = drm_flush_queue(dev, context); + } + if (flags & _DRM_LOCK_FLUSH_ALL) { + for (i = 0; !ret && i < dev->queue_count; i++) { + ret = drm_flush_queue(dev, i); + } + } + return ret; +} + +int drm_flush_unblock(drm_device_t *dev, int context, drm_lock_flags_t flags) +{ + int ret = 0; + int i; + + DRM_DEBUG("\n"); + + if (flags & _DRM_LOCK_FLUSH) { + ret = drm_flush_unblock_queue(dev, DRM_KERNEL_CONTEXT); + if (!ret) ret = drm_flush_unblock_queue(dev, context); + } + if (flags & _DRM_LOCK_FLUSH_ALL) { + for (i = 0; !ret && i < dev->queue_count; i++) { + ret = drm_flush_unblock_queue(dev, i); + } + } + + return ret; +} + +int drm_finish(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + int ret = 0; + drm_lock_t lock; + + DRM_DEBUG("\n"); + + lock = *(drm_lock_t *) data; + ret = drm_flush_block_and_flush(dev, lock.context, lock.flags); + drm_flush_unblock(dev, lock.context, lock.flags); + return ret; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/memory.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/memory.c new file mode 100644 index 000000000..a8a936df0 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/memory.c @@ -0,0 +1,458 @@ +/* memory.c -- Memory management wrappers for DRM -*- c -*- + * Created: Thu Feb 4 14:00:34 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 13:04:33 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/memory.c,v 1.4 1999/08/20 20:00:53 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/memory.c,v 1.1 1999/09/25 14:38:02 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +#include <vm/vm.h> +#include <vm/pmap.h> +#ifdef DRM_AGP +#include <sys/agpio.h> +#endif + +MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures"); + +typedef struct drm_mem_stats { + const char *name; + int succeed_count; + int free_count; + int fail_count; + unsigned long bytes_allocated; + unsigned long bytes_freed; +} drm_mem_stats_t; + +#ifdef SMP +static struct simplelock drm_mem_lock; +#endif +static unsigned long drm_ram_available = 0; +static unsigned long drm_ram_used = 0; +static drm_mem_stats_t drm_mem_stats[] = { + [DRM_MEM_DMA] = { "dmabufs" }, + [DRM_MEM_SAREA] = { "sareas" }, + [DRM_MEM_DRIVER] = { "driver" }, + [DRM_MEM_MAGIC] = { "magic" }, + [DRM_MEM_IOCTLS] = { "ioctltab" }, + [DRM_MEM_MAPS] = { "maplist" }, + [DRM_MEM_VMAS] = { "vmalist" }, + [DRM_MEM_BUFS] = { "buflist" }, + [DRM_MEM_SEGS] = { "seglist" }, + [DRM_MEM_PAGES] = { "pagelist" }, + [DRM_MEM_FILES] = { "files" }, + [DRM_MEM_QUEUES] = { "queues" }, + [DRM_MEM_CMDS] = { "commands" }, + [DRM_MEM_MAPPINGS] = { "mappings" }, + [DRM_MEM_BUFLISTS] = { "buflists" }, + [DRM_MEM_AGPLISTS] = { "agplist" }, + [DRM_MEM_TOTALAGP] = { "totalagp" }, + [DRM_MEM_BOUNDAGP] = { "boundagp" }, + [DRM_MEM_CTXBITMAP] = { "ctxbitmap"}, + { NULL, 0, } /* Last entry must be null */ +}; + +void drm_mem_init(void) +{ + drm_mem_stats_t *mem; + + for (mem = drm_mem_stats; mem->name; ++mem) { + mem->succeed_count = 0; + mem->free_count = 0; + mem->fail_count = 0; + mem->bytes_allocated = 0; + mem->bytes_freed = 0; + } + + drm_ram_available = 0; /* si.totalram; */ + drm_ram_used = 0; +} + +/* drm_mem_info is called whenever a process reads /dev/drm/mem. */ + +static int _drm_mem_info SYSCTL_HANDLER_ARGS +{ + drm_mem_stats_t *pt; + char buf[128]; + int error; + + DRM_SYSCTL_PRINT(" total counts " + " | outstanding \n"); + DRM_SYSCTL_PRINT("type alloc freed fail bytes freed" + " | allocs bytes\n\n"); + DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n", + "system", 0, 0, 0, drm_ram_available); + DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n", + "locked", 0, 0, 0, drm_ram_used); + DRM_SYSCTL_PRINT("\n"); + for (pt = drm_mem_stats; pt->name; pt++) { + DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n", + pt->name, + pt->succeed_count, + pt->free_count, + pt->fail_count, + pt->bytes_allocated, + pt->bytes_freed, + pt->succeed_count - pt->free_count, + (long)pt->bytes_allocated + - (long)pt->bytes_freed); + } + SYSCTL_OUT(req, "", 1); + + return 0; +} + +int drm_mem_info SYSCTL_HANDLER_ARGS +{ + int ret; + + simple_lock(&drm_mem_lock); + ret = _drm_mem_info(oidp, arg1, arg2, req); + simple_unlock(&drm_mem_lock); + return ret; +} + +void *drm_alloc(size_t size, int area) +{ + void *pt; + + if (!size) { + DRM_MEM_ERROR(area, "Allocating 0 bytes\n"); + return NULL; + } + + if (!(pt = malloc(size, M_DRM, M_NOWAIT))) { + simple_lock(&drm_mem_lock); + ++drm_mem_stats[area].fail_count; + simple_unlock(&drm_mem_lock); + return NULL; + } + simple_lock(&drm_mem_lock); + ++drm_mem_stats[area].succeed_count; + drm_mem_stats[area].bytes_allocated += size; + simple_unlock(&drm_mem_lock); + return pt; +} + +void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) +{ + void *pt; + + if (!(pt = drm_alloc(size, area))) return NULL; + if (oldpt && oldsize) { + memcpy(pt, oldpt, oldsize); + drm_free(oldpt, oldsize, area); + } + return pt; +} + +char *drm_strdup(const char *s, int area) +{ + char *pt; + int length = s ? strlen(s) : 0; + + if (!(pt = drm_alloc(length+1, area))) return NULL; + strcpy(pt, s); + return pt; +} + +void drm_strfree(char *s, int area) +{ + unsigned int size; + + if (!s) return; + + size = 1 + (s ? strlen(s) : 0); + drm_free((void *)s, size, area); +} + +void drm_free(void *pt, size_t size, int area) +{ + int alloc_count; + int free_count; + + if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n"); + else free(pt, M_DRM); + simple_lock(&drm_mem_lock); + drm_mem_stats[area].bytes_freed += size; + free_count = ++drm_mem_stats[area].free_count; + alloc_count = drm_mem_stats[area].succeed_count; + simple_unlock(&drm_mem_lock); + if (free_count > alloc_count) { + DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } +} + +unsigned long drm_alloc_pages(int order, int area) +{ + vm_offset_t address; + unsigned long bytes = PAGE_SIZE << order; + unsigned long addr; + unsigned int sz; + + simple_lock(&drm_mem_lock); + if (drm_ram_used > +(DRM_RAM_PERCENT * drm_ram_available) / 100) { + simple_unlock(&drm_mem_lock); + return 0; + } + simple_unlock(&drm_mem_lock); + + address = (vm_offset_t) contigmalloc(1<<order, M_DRM, M_WAITOK, 0, ~0, 1, 0); + if (!address) { + simple_lock(&drm_mem_lock); + ++drm_mem_stats[area].fail_count; + simple_unlock(&drm_mem_lock); + return 0; + } + simple_lock(&drm_mem_lock); + ++drm_mem_stats[area].succeed_count; + drm_mem_stats[area].bytes_allocated += bytes; + drm_ram_used += bytes; + simple_unlock(&drm_mem_lock); + + + /* Zero outside the lock */ + memset((void *)address, 0, bytes); + + /* Reserve */ + for (addr = address, sz = bytes; + sz > 0; + addr += PAGE_SIZE, sz -= PAGE_SIZE) { + /* mem_map_reserve(MAP_NR(addr));*/ + } + + return address; +} + +void drm_free_pages(unsigned long address, int order, int area) +{ + unsigned long bytes = PAGE_SIZE << order; + int alloc_count; + int free_count; + unsigned long addr; + unsigned int sz; + + if (!address) { + DRM_MEM_ERROR(area, "Attempt to free address 0\n"); + } else { + /* Unreserve */ + for (addr = address, sz = bytes; + sz > 0; + addr += PAGE_SIZE, sz -= PAGE_SIZE) { + /* mem_map_unreserve(MAP_NR(addr));*/ + } + contigfree((void *) address, bytes, M_DRM); + } + + simple_lock(&drm_mem_lock); + free_count = ++drm_mem_stats[area].free_count; + alloc_count = drm_mem_stats[area].succeed_count; + drm_mem_stats[area].bytes_freed += bytes; + drm_ram_used -= bytes; + simple_unlock(&drm_mem_lock); + if (free_count > alloc_count) { + DRM_MEM_ERROR(area, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } +} + +void *drm_ioremap(unsigned long offset, unsigned long size) +{ + void *pt; + + if (!size) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Mapping 0 bytes at 0x%08lx\n", offset); + return NULL; + } + + if (!(pt = pmap_mapdev(offset, size))) { + simple_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; + simple_unlock(&drm_mem_lock); + return NULL; + } + simple_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; + drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; + simple_unlock(&drm_mem_lock); + return pt; +} + +void drm_ioremapfree(void *pt, unsigned long size) +{ + int alloc_count; + int free_count; + + if (!pt) + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Attempt to free NULL pointer\n"); + else + pmap_unmapdev((vm_offset_t) pt, size); + + simple_lock(&drm_mem_lock); + drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size; + free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count; + alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; + simple_unlock(&drm_mem_lock); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } +} + +#ifdef DRM_AGP +void *drm_alloc_agp(int pages, u_int32_t type) +{ + device_t dev = agp_find_device(); + void *handle; + + if (!dev) + return NULL; + + if (!pages) { + DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n"); + return NULL; + } + + if ((handle = agp_alloc_memory(dev, type, pages << AGP_PAGE_SHIFT))) { + simple_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; + drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated + += pages << PAGE_SHIFT; + simple_unlock(&drm_mem_lock); + return handle; + } + simple_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count; + simple_unlock(&drm_mem_lock); + return NULL; +} + +int drm_free_agp(void *handle, int pages) +{ + device_t dev = agp_find_device(); + int alloc_count; + int free_count; + int retval = EINVAL; + + if (!dev) + return EINVAL; + + if (!handle) { + DRM_MEM_ERROR(DRM_MEM_TOTALAGP, + "Attempt to free NULL AGP handle\n"); + return retval; + } + + agp_free_memory(dev, handle); + simple_lock(&drm_mem_lock); + free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count; + alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; + drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed + += pages << PAGE_SHIFT; + simple_unlock(&drm_mem_lock); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_TOTALAGP, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } + return 0; +} + +int drm_bind_agp(void *handle, unsigned int start) +{ + device_t dev = agp_find_device(); + int retcode = EINVAL; + struct agp_memory_info info; + + DRM_DEBUG("drm_bind_agp called\n"); + + if (!dev) + return EINVAL; + + if (!handle) { + DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, + "Attempt to bind NULL AGP handle\n"); + return retcode; + } + + if (!(retcode = agp_bind_memory(dev, handle, + start << AGP_PAGE_SHIFT))) { + simple_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; + agp_memory_info(dev, handle, &info); + drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated + += info.ami_size; + simple_unlock(&drm_mem_lock); + DRM_DEBUG("drm_agp.bind_memory: retcode %d\n", retcode); + return retcode; + } + simple_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count; + simple_unlock(&drm_mem_lock); + return retcode; +} + +int drm_unbind_agp(void *handle) +{ + device_t dev = agp_find_device(); + int alloc_count; + int free_count; + int retcode = EINVAL; + struct agp_memory_info info; + + if (!dev) + return EINVAL; + + if (!handle) { + DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, + "Attempt to unbind NULL AGP handle\n"); + return retcode; + } + + + agp_memory_info(dev, handle, &info); + if ((retcode = agp_unbind_memory(dev, handle))) + return retcode; + simple_lock(&drm_mem_lock); + free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count; + alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; + drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed += info.ami_size; + simple_unlock(&drm_mem_lock); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } + return retcode; +} +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/proc.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/proc.c new file mode 100644 index 000000000..12168aa3d --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/proc.c @@ -0,0 +1,568 @@ +/* proc.c -- /proc support for DRM -*- c -*- + * Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 11:31:48 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c,v 1.4 1999/08/20 15:36:46 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c,v 1.1 1999/09/25 14:38:02 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +static struct proc_dir_entry *drm_root = NULL; +static struct proc_dir_entry *drm_dev_root = NULL; +static char drm_slot_name[64]; + +static int drm_name_info(char *buf, char **start, off_t offset, + int len, int *eof, void *data); +static int drm_vm_info(char *buf, char **start, off_t offset, + int len, int *eof, void *data); +static int drm_clients_info(char *buf, char **start, off_t offset, + int len, int *eof, void *data); +static int drm_queues_info(char *buf, char **start, off_t offset, + int len, int *eof, void *data); +static int drm_bufs_info(char *buf, char **start, off_t offset, + int len, int *eof, void *data); +#if DRM_DEBUG_CODE +static int drm_vma_info(char *buf, char **start, off_t offset, + int len, int *eof, void *data); +#endif +#if DRM_DMA_HISTOGRAM +static int drm_histo_info(char *buf, char **start, off_t offset, + int len, int *eof, void *data); +#endif + +struct drm_proc_list { + const char *name; + int (*f)(char *, char **, off_t, int, int *, void *); +} drm_proc_list[] = { + { "name", drm_name_info }, + { "mem", drm_mem_info }, + { "vm", drm_vm_info }, + { "clients", drm_clients_info }, + { "queues", drm_queues_info }, + { "bufs", drm_bufs_info }, +#if DRM_DEBUG_CODE + { "vma", drm_vma_info }, +#endif +#if DRM_DMA_HISTOGRAM + { "histo", drm_histo_info }, +#endif +}; +#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0])) + +int drm_proc_init(drm_device_t *dev) +{ + struct proc_dir_entry *ent; + int i, j; + + drm_root = create_proc_entry("graphics", S_IFDIR, NULL); + if (!drm_root) { + DRM_ERROR("Cannot create /proc/graphics\n"); + return -1; + } + + /* Instead of doing this search, we should + add some global support for /proc/graphics. */ + for (i = 0; i < 8; i++) { + sprintf(drm_slot_name, "graphics/%d", i); + drm_dev_root = create_proc_entry(drm_slot_name, S_IFDIR, NULL); + if (!drm_dev_root) { + DRM_ERROR("Cannot create /proc/%s\n", drm_slot_name); + remove_proc_entry("graphics", NULL); + } + if (drm_dev_root->nlink == 2) break; + drm_dev_root = NULL; + } + if (!drm_dev_root) { + DRM_ERROR("Cannot find slot in /proc/graphics\n"); + return -1; + } + + for (i = 0; i < DRM_PROC_ENTRIES; i++) { + ent = create_proc_entry(drm_proc_list[i].name, + S_IFREG|S_IRUGO, drm_dev_root); + if (!ent) { + DRM_ERROR("Cannot create /proc/%s/%s\n", + drm_slot_name, drm_proc_list[i].name); + for (j = 0; j < i; j++) + remove_proc_entry(drm_proc_list[i].name, + drm_dev_root); + remove_proc_entry(drm_slot_name, NULL); + remove_proc_entry("graphics", NULL); + return -1; + } + ent->read_proc = drm_proc_list[i].f; + ent->data = dev; + } + + return 0; +} + + +int drm_proc_cleanup(void) +{ + int i; + + if (drm_root) { + if (drm_dev_root) { + for (i = 0; i < DRM_PROC_ENTRIES; i++) { + remove_proc_entry(drm_proc_list[i].name, + drm_dev_root); + } + remove_proc_entry(drm_slot_name, NULL); + } + remove_proc_entry("graphics", NULL); + remove_proc_entry(DRM_NAME, NULL); + } + drm_root = drm_dev_root = NULL; + return 0; +} + +static int drm_name_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + + if (offset > 0) return 0; /* no partial requests */ + len = 0; + *eof = 1; + + if (dev->unique) { + DRM_PROC_PRINT("%s 0x%x %s\n", + dev->name, dev->device, dev->unique); + } else { + DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device); + } + return len; +} + +static int _drm_vm_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + drm_map_t *map; + const char *types[] = { "FB", "REG", "SHM" }; + const char *type; + int i; + + if (offset > 0) return 0; /* no partial requests */ + len = 0; + *eof = 1; + DRM_PROC_PRINT("slot offset size type flags " + "address mtrr\n\n"); + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + if (map->type < 0 || map->type > 2) type = "??"; + else type = types[map->type]; + DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", + i, + map->offset, + map->size, + type, + map->flags, + (unsigned long)map->handle); + if (map->mtrr < 0) { + DRM_PROC_PRINT("none\n"); + } else { + DRM_PROC_PRINT("%4d\n", map->mtrr); + } + } + + return len; +} + +static int drm_vm_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + int ret; + + down(&dev->struct_sem); + ret = _drm_vm_info(buf, start, offset, len, eof, data); + up(&dev->struct_sem); + return ret; +} + + +static int _drm_queues_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + int i; + drm_queue_t *q; + + if (offset > 0) return 0; /* no partial requests */ + len = 0; + *eof = 1; + DRM_PROC_PRINT(" ctx/flags use fin" + " blk/rw/rwf wait flushed queued" + " locks\n\n"); + for (i = 0; i < dev->queue_count; i++) { + q = dev->queuelist[i]; + atomic_inc(&q->use_count); + DRM_PROC_PRINT_RET(atomic_dec(&q->use_count), + "%5d/0x%03x %5d %5d" + " %5d/%c%c/%c%c%c %5d %10d %10d %10d\n", + i, + q->flags, + atomic_read(&q->use_count), + atomic_read(&q->finalization), + atomic_read(&q->block_count), + atomic_read(&q->block_read) ? 'r' : '-', + atomic_read(&q->block_write) ? 'w' : '-', + waitqueue_active(&q->read_queue) ? 'r':'-', + waitqueue_active(&q->write_queue) ? 'w':'-', + waitqueue_active(&q->flush_queue) ? 'f':'-', + DRM_BUFCOUNT(&q->waitlist), + atomic_read(&q->total_flushed), + atomic_read(&q->total_queued), + atomic_read(&q->total_locks)); + atomic_dec(&q->use_count); + } + + return len; +} + +static int drm_queues_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + int ret; + + down(&dev->struct_sem); + ret = _drm_queues_info(buf, start, offset, len, eof, data); + up(&dev->struct_sem); + return ret; +} + +/* drm_bufs_info is called whenever a process reads + /dev/drm/<dev>/bufs. */ + +static int _drm_bufs_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + drm_device_dma_t *dma = dev->dma; + int i; + + if (!dma) return 0; + if (offset > 0) return 0; /* no partial requests */ + len = 0; + *eof = 1; + DRM_PROC_PRINT(" o size count free segs pages kB\n\n"); + for (i = 0; i <= DRM_MAX_ORDER; i++) { + if (dma->bufs[i].buf_count) + DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n", + i, + dma->bufs[i].buf_size, + dma->bufs[i].buf_count, + atomic_read(&dma->bufs[i] + .freelist.count), + dma->bufs[i].seg_count, + dma->bufs[i].seg_count + *(1 << dma->bufs[i].page_order), + (dma->bufs[i].seg_count + * (1 << dma->bufs[i].page_order)) + * PAGE_SIZE / 1024); + } + DRM_PROC_PRINT("\n"); + for (i = 0; i < dma->buf_count; i++) { + if (i && !(i%32)) DRM_PROC_PRINT("\n"); + DRM_PROC_PRINT(" %d", dma->buflist[i]->list); + } + DRM_PROC_PRINT("\n"); + + return len; +} + +static int drm_bufs_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + int ret; + + down(&dev->struct_sem); + ret = _drm_bufs_info(buf, start, offset, len, eof, data); + up(&dev->struct_sem); + return ret; +} + + +static int _drm_clients_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + drm_file_t *priv; + + if (offset > 0) return 0; /* no partial requests */ + len = 0; + *eof = 1; + DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n"); + for (priv = dev->file_first; priv; priv = priv->next) { + DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", + priv->authenticated ? 'y' : 'n', + priv->minor, + priv->pid, + priv->uid, + priv->magic, + priv->ioctl_count); + } + + return len; +} + +static int drm_clients_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + int ret; + + down(&dev->struct_sem); + ret = _drm_clients_info(buf, start, offset, len, eof, data); + up(&dev->struct_sem); + return ret; +} + +#if DRM_DEBUG_CODE + +static int _drm_vma_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + drm_vma_entry_t *pt; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned long i; + struct vm_area_struct *vma; + unsigned long address; +#if defined(__i386__) + unsigned int pgprot; +#endif + + if (offset > 0) return 0; /* no partial requests */ + len = 0; + *eof = 1; + DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n", + atomic_read(&dev->vma_count), + high_memory, virt_to_phys(high_memory)); + for (pt = dev->vmalist; pt; pt = pt->next) { + if (!(vma = pt->vma)) continue; + DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx", + pt->pid, + vma->vm_start, + vma->vm_end, + vma->vm_flags & VM_READ ? 'r' : '-', + vma->vm_flags & VM_WRITE ? 'w' : '-', + vma->vm_flags & VM_EXEC ? 'x' : '-', + vma->vm_flags & VM_MAYSHARE ? 's' : 'p', + vma->vm_flags & VM_LOCKED ? 'l' : '-', + vma->vm_flags & VM_IO ? 'i' : '-', + vma->vm_offset ); +#if defined(__i386__) + pgprot = pgprot_val(vma->vm_page_prot); + DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c", + pgprot & _PAGE_PRESENT ? 'p' : '-', + pgprot & _PAGE_RW ? 'w' : 'r', + pgprot & _PAGE_USER ? 'u' : 's', + pgprot & _PAGE_PWT ? 't' : 'b', + pgprot & _PAGE_PCD ? 'u' : 'c', + pgprot & _PAGE_ACCESSED ? 'a' : '-', + pgprot & _PAGE_DIRTY ? 'd' : '-', + pgprot & _PAGE_4M ? 'm' : 'k', + pgprot & _PAGE_GLOBAL ? 'g' : 'l' ); +#endif + DRM_PROC_PRINT("\n"); + for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) { + pgd = pgd_offset(vma->vm_mm, i); + pmd = pmd_offset(pgd, i); + pte = pte_offset(pmd, i); + if (pte_present(*pte)) { + address = __pa(pte_page(*pte)) + + (i & (PAGE_SIZE-1)); + DRM_PROC_PRINT(" 0x%08lx -> 0x%08lx" + " %c%c%c%c%c\n", + i, + address, + pte_read(*pte) ? 'r' : '-', + pte_write(*pte) ? 'w' : '-', + pte_exec(*pte) ? 'x' : '-', + pte_dirty(*pte) ? 'd' : '-', + pte_young(*pte) ? 'a' : '-' ); + } else { + DRM_PROC_PRINT(" 0x%08lx\n", i); + } + } + } + + return len; +} + +static int drm_vma_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + int ret; + + down(&dev->struct_sem); + ret = _drm_vma_info(buf, start, offset, len, eof, data); + up(&dev->struct_sem); + return ret; +} +#endif + + +#if DRM_DMA_HISTOGRAM +static int _drm_histo_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + drm_device_dma_t *dma = dev->dma; + int i; + unsigned long slot_value = DRM_DMA_HISTOGRAM_INITIAL; + unsigned long prev_value = 0; + drm_buf_t *buffer; + + if (offset > 0) return 0; /* no partial requests */ + len = 0; + *eof = 1; + + DRM_PROC_PRINT("general statistics:\n"); + DRM_PROC_PRINT("total %10u\n", atomic_read(&dev->histo.total)); + DRM_PROC_PRINT("open %10u\n", atomic_read(&dev->total_open)); + DRM_PROC_PRINT("close %10u\n", atomic_read(&dev->total_close)); + DRM_PROC_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl)); + DRM_PROC_PRINT("irq %10u\n", atomic_read(&dev->total_irq)); + DRM_PROC_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx)); + + DRM_PROC_PRINT("\nlock statistics:\n"); + DRM_PROC_PRINT("locks %10u\n", atomic_read(&dev->total_locks)); + DRM_PROC_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks)); + DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends)); + DRM_PROC_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps)); + + + if (dma) { + DRM_PROC_PRINT("\ndma statistics:\n"); + DRM_PROC_PRINT("prio %10u\n", + atomic_read(&dma->total_prio)); + DRM_PROC_PRINT("bytes %10u\n", + atomic_read(&dma->total_bytes)); + DRM_PROC_PRINT("dmas %10u\n", + atomic_read(&dma->total_dmas)); + DRM_PROC_PRINT("missed:\n"); + DRM_PROC_PRINT(" dma %10u\n", + atomic_read(&dma->total_missed_dma)); + DRM_PROC_PRINT(" lock %10u\n", + atomic_read(&dma->total_missed_lock)); + DRM_PROC_PRINT(" free %10u\n", + atomic_read(&dma->total_missed_free)); + DRM_PROC_PRINT(" sched %10u\n", + atomic_read(&dma->total_missed_sched)); + DRM_PROC_PRINT("tried %10u\n", + atomic_read(&dma->total_tried)); + DRM_PROC_PRINT("hit %10u\n", + atomic_read(&dma->total_hit)); + DRM_PROC_PRINT("lost %10u\n", + atomic_read(&dma->total_lost)); + + buffer = dma->next_buffer; + if (buffer) { + DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx); + } else { + DRM_PROC_PRINT("next_buffer none\n"); + } + buffer = dma->this_buffer; + if (buffer) { + DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx); + } else { + DRM_PROC_PRINT("this_buffer none\n"); + } + } + + + DRM_PROC_PRINT("\nvalues:\n"); + if (dev->lock.hw_lock) { + DRM_PROC_PRINT("lock 0x%08x\n", + dev->lock.hw_lock->lock); + } else { + DRM_PROC_PRINT("lock none\n"); + } + DRM_PROC_PRINT("context_flag 0x%08x\n", dev->context_flag); + DRM_PROC_PRINT("interrupt_flag 0x%08x\n", dev->interrupt_flag); + DRM_PROC_PRINT("dma_flag 0x%08x\n", dev->dma_flag); + + DRM_PROC_PRINT("queue_count %10d\n", dev->queue_count); + DRM_PROC_PRINT("last_context %10d\n", dev->last_context); + DRM_PROC_PRINT("last_switch %10lu\n", dev->last_switch); + DRM_PROC_PRINT("last_checked %10d\n", dev->last_checked); + + + DRM_PROC_PRINT("\n q2d d2c c2f" + " q2c q2f dma sch" + " ctx lacq lhld\n\n"); + for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) { + DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u" + " %10u %10u %10u %10u %10u\n", + i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ", + i == DRM_DMA_HISTOGRAM_SLOTS - 1 + ? prev_value : slot_value , + + atomic_read(&dev->histo + .queued_to_dispatched[i]), + atomic_read(&dev->histo + .dispatched_to_completed[i]), + atomic_read(&dev->histo + .completed_to_freed[i]), + + atomic_read(&dev->histo + .queued_to_completed[i]), + atomic_read(&dev->histo + .queued_to_freed[i]), + atomic_read(&dev->histo.dma[i]), + atomic_read(&dev->histo.schedule[i]), + atomic_read(&dev->histo.ctx[i]), + atomic_read(&dev->histo.lacq[i]), + atomic_read(&dev->histo.lhld[i])); + prev_value = slot_value; + slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value); + } + return len; +} + +static int drm_histo_info(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + drm_device_t *dev = (drm_device_t *)data; + int ret; + + down(&dev->struct_sem); + ret = _drm_histo_info(buf, start, offset, len, eof, data); + up(&dev->struct_sem); + return ret; +} +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/sysctl.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/sysctl.c new file mode 100644 index 000000000..7c736abff --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/sysctl.c @@ -0,0 +1,554 @@ +/* proc.c -- /proc support for DRM -*- c -*- + * Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 11:31:48 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI$ + * $XFree86$ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include <sys/sysctl.h> + +SYSCTL_NODE(_hw, OID_AUTO, dri, CTLFLAG_RW, 0, "DRI Graphics"); + +static int drm_name_info SYSCTL_HANDLER_ARGS; +static int drm_vm_info SYSCTL_HANDLER_ARGS; +static int drm_clients_info SYSCTL_HANDLER_ARGS; +static int drm_queues_info SYSCTL_HANDLER_ARGS; +static int drm_bufs_info SYSCTL_HANDLER_ARGS; +#if DRM_DEBUG_CODExx +static int drm_vma_info SYSCTL_HANDLER_ARGS; +#endif +#if DRM_DMA_HISTOGRAM +static int drm_histo_info SYSCTL_HANDLER_ARGS; +#endif + +struct drm_sysctl_list { + const char *name; + int (*f) SYSCTL_HANDLER_ARGS; +} drm_sysctl_list[] = { + { "name", drm_name_info }, + { "mem", drm_mem_info }, + { "vm", drm_vm_info }, + { "clients", drm_clients_info }, + { "queues", drm_queues_info }, + { "bufs", drm_bufs_info }, +#if DRM_DEBUG_CODExx + { "vma", drm_vma_info }, +#endif +#if DRM_DMA_HISTOGRAM + { "histo", drm_histo_info }, +#endif +}; +#define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0])) + +struct drm_sysctl_info { + struct sysctl_oid oids[DRM_SYSCTL_ENTRIES + 1]; + struct sysctl_oid_list list; + char name[2]; +}; + +int drm_sysctl_init(drm_device_t *dev) +{ + struct drm_sysctl_info *info; + struct sysctl_oid *oid; + struct sysctl_oid *top; + int i; + + /* Find the next free slot under hw.graphics */ + i = 0; + SLIST_FOREACH(oid, &sysctl__hw_dri_children, oid_link) { + if (i <= oid->oid_arg2) + i = oid->oid_arg2 + 1; + } + + info = drm_alloc(sizeof *info, DRM_MEM_DRIVER); + dev->sysctl = info; + + /* Construct the node under hw.graphics */ + info->name[0] = '0' + i; + info->name[1] = 0; + oid = &info->oids[DRM_SYSCTL_ENTRIES]; + bzero(oid, sizeof(*oid)); + oid->oid_parent = &sysctl__hw_dri_children; + oid->oid_number = OID_AUTO; + oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW; + oid->oid_arg1 = &info->list; + oid->oid_arg2 = i; + oid->oid_name = info->name; + oid->oid_handler = 0; + oid->oid_fmt = "N"; + SLIST_INIT(&info->list); + sysctl_register_oid(oid); + top = oid; + + for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) { + oid = &info->oids[i]; + bzero(oid, sizeof(*oid)); + oid->oid_parent = top->oid_arg1; + oid->oid_number = OID_AUTO; + oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD; + oid->oid_arg1 = dev; + oid->oid_arg2 = 0; + oid->oid_name = drm_sysctl_list[i].name; + oid->oid_handler = drm_sysctl_list[i].f; + oid->oid_fmt = "A"; + sysctl_register_oid(oid); + } + + return 0; +} + +int drm_sysctl_cleanup(drm_device_t *dev) +{ + int i; + + DRM_DEBUG("dev->sysctl=%p\n", dev->sysctl); + for (i = 0; i < DRM_SYSCTL_ENTRIES + 1; i++) + sysctl_unregister_oid(&dev->sysctl->oids[i]); + + drm_free(dev->sysctl, sizeof *dev->sysctl, DRM_MEM_DRIVER); + dev->sysctl = NULL; + + return 0; +} + +static int drm_name_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + char buf[128]; + int error; + + if (dev->unique) { + DRM_SYSCTL_PRINT("%s 0x%x %s\n", + dev->name, dev2udev(dev->devnode), dev->unique); + } else { + DRM_SYSCTL_PRINT("%s 0x%x\n", dev->name, dev2udev(dev->devnode)); + } + + SYSCTL_OUT(req, "", 1); + + return 0; +} + +static int _drm_vm_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + drm_map_t *map; + const char *types[] = { "FB", "REG", "SHM" }; + const char *type; + int i; + char buf[128]; + int error; + + DRM_SYSCTL_PRINT("slot offset size type flags " + "address mtrr\n\n"); + error = SYSCTL_OUT(req, buf, strlen(buf)); + if (error) return error; + + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + if (map->type < 0 || map->type > 2) type = "??"; + else type = types[map->type]; + DRM_SYSCTL_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", + i, + map->offset, + map->size, + type, + map->flags, + (unsigned long)map->handle); + if (map->mtrr < 0) { + DRM_SYSCTL_PRINT("none\n"); + } else { + DRM_SYSCTL_PRINT("%4d\n", map->mtrr); + } + } + SYSCTL_OUT(req, "", 1); + + return 0; +} + +static int drm_vm_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + int ret; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + ret = _drm_vm_info(oidp, arg1, arg2, req); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + return ret; +} + + +static int _drm_queues_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + int i; + drm_queue_t *q; + char buf[128]; + int error; + + DRM_SYSCTL_PRINT(" ctx/flags use fin" + " blk/rw/rwf wait flushed queued" + " locks\n\n"); + for (i = 0; i < dev->queue_count; i++) { + q = dev->queuelist[i]; + atomic_inc(&q->use_count); + DRM_SYSCTL_PRINT_RET(atomic_dec(&q->use_count), + "%5d/0x%03x %5d %5d" + " %5d/%c%c/%c%c%c %5d %10d %10d %10d\n", + i, + q->flags, + atomic_read(&q->use_count), + atomic_read(&q->finalization), + atomic_read(&q->block_count), + atomic_read(&q->block_read) ? 'r' : '-', + atomic_read(&q->block_write) ? 'w' : '-', + q->read_queue ? 'r':'-', + q->write_queue ? 'w':'-', + q->flush_queue ? 'f':'-', + DRM_BUFCOUNT(&q->waitlist), + atomic_read(&q->total_flushed), + atomic_read(&q->total_queued), + atomic_read(&q->total_locks)); + atomic_dec(&q->use_count); + } + + SYSCTL_OUT(req, "", 1); + return 0; +} + +static int drm_queues_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + int ret; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + ret = _drm_queues_info(oidp, arg1, arg2, req); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return ret; +} + +/* drm_bufs_info is called whenever a process reads + hw.dri.0.bufs. */ + +static int _drm_bufs_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + drm_device_dma_t *dma = dev->dma; + int i; + char buf[128]; + int error; + + if (!dma) return 0; + DRM_SYSCTL_PRINT(" o size count free segs pages kB\n\n"); + for (i = 0; i <= DRM_MAX_ORDER; i++) { + if (dma->bufs[i].buf_count) + DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n", + i, + dma->bufs[i].buf_size, + dma->bufs[i].buf_count, + atomic_read(&dma->bufs[i] + .freelist.count), + dma->bufs[i].seg_count, + dma->bufs[i].seg_count + *(1 << dma->bufs[i].page_order), + (dma->bufs[i].seg_count + * (1 << dma->bufs[i].page_order)) + * PAGE_SIZE / 1024); + } + DRM_SYSCTL_PRINT("\n"); + for (i = 0; i < dma->buf_count; i++) { + if (i && !(i%32)) DRM_SYSCTL_PRINT("\n"); + DRM_SYSCTL_PRINT(" %d", dma->buflist[i]->list); + } + DRM_SYSCTL_PRINT("\n"); + + SYSCTL_OUT(req, "", 1); + return 0; +} + +static int drm_bufs_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + int ret; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + ret = _drm_bufs_info(oidp, arg1, arg2, req); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return ret; +} + + +static int _drm_clients_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + drm_file_t *priv; + char buf[128]; + int error; + + DRM_SYSCTL_PRINT("a dev pid uid magic ioctls\n\n"); + TAILQ_FOREACH(priv, &dev->files, link) { + DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n", + priv->authenticated ? 'y' : 'n', + priv->minor, + priv->pid, + priv->uid, + priv->magic, + priv->ioctl_count); + } + + SYSCTL_OUT(req, "", 1); + return 0; +} + +static int drm_clients_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + int ret; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + ret = _drm_clients_info(oidp, arg1, arg2, req); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return ret; +} + +#if DRM_DEBUG_CODExx + +static int _drm_vma_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + drm_vma_entry_t *pt; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned long i; + struct vm_area_struct *vma; + unsigned long address; +#if defined(__i386__) + unsigned int pgprot; +#endif + char buf[128]; + int error; + + DRM_SYSCTL_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n", + atomic_read(&dev->vma_count), + high_memory, virt_to_phys(high_memory)); + for (pt = dev->vmalist; pt; pt = pt->next) { + if (!(vma = pt->vma)) continue; + DRM_SYSCTL_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx", + pt->pid, + vma->vm_start, + vma->vm_end, + vma->vm_flags & VM_READ ? 'r' : '-', + vma->vm_flags & VM_WRITE ? 'w' : '-', + vma->vm_flags & VM_EXEC ? 'x' : '-', + vma->vm_flags & VM_MAYSHARE ? 's' : 'p', + vma->vm_flags & VM_LOCKED ? 'l' : '-', + vma->vm_flags & VM_IO ? 'i' : '-', + vma->vm_offset ); +#if defined(__i386__) + pgprot = pgprot_val(vma->vm_page_prot); + DRM_SYSCTL_PRINT(" %c%c%c%c%c%c%c%c%c", + pgprot & _PAGE_PRESENT ? 'p' : '-', + pgprot & _PAGE_RW ? 'w' : 'r', + pgprot & _PAGE_USER ? 'u' : 's', + pgprot & _PAGE_PWT ? 't' : 'b', + pgprot & _PAGE_PCD ? 'u' : 'c', + pgprot & _PAGE_ACCESSED ? 'a' : '-', + pgprot & _PAGE_DIRTY ? 'd' : '-', + pgprot & _PAGE_4M ? 'm' : 'k', + pgprot & _PAGE_GLOBAL ? 'g' : 'l' ); +#endif + DRM_SYSCTL_PRINT("\n"); + for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) { + pgd = pgd_offset(vma->vm_mm, i); + pmd = pmd_offset(pgd, i); + pte = pte_offset(pmd, i); + if (pte_present(*pte)) { + address = __pa(pte_page(*pte)) + + (i & (PAGE_SIZE-1)); + DRM_SYSCTL_PRINT(" 0x%08lx -> 0x%08lx" + " %c%c%c%c%c\n", + i, + address, + pte_read(*pte) ? 'r' : '-', + pte_write(*pte) ? 'w' : '-', + pte_exec(*pte) ? 'x' : '-', + pte_dirty(*pte) ? 'd' : '-', + pte_young(*pte) ? 'a' : '-' ); + } else { + DRM_SYSCTL_PRINT(" 0x%08lx\n", i); + } + } + } + + SYSCTL_OUT(req, "", 1); + return 0; +} + +static int drm_vma_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + int ret; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + ret = _drm_vma_info(oidp, arg1, arg2, req); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return ret; +} +#endif + + +#if DRM_DMA_HISTOGRAM +static int _drm_histo_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + drm_device_dma_t *dma = dev->dma; + int i; + unsigned long slot_value = DRM_DMA_HISTOGRAM_INITIAL; + unsigned long prev_value = 0; + drm_buf_t *buffer; + char buf[128]; + int error; + + DRM_SYSCTL_PRINT("general statistics:\n"); + DRM_SYSCTL_PRINT("total %10u\n", atomic_read(&dev->histo.total)); + DRM_SYSCTL_PRINT("open %10u\n", atomic_read(&dev->total_open)); + DRM_SYSCTL_PRINT("close %10u\n", atomic_read(&dev->total_close)); + DRM_SYSCTL_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl)); + DRM_SYSCTL_PRINT("irq %10u\n", atomic_read(&dev->total_irq)); + DRM_SYSCTL_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx)); + + DRM_SYSCTL_PRINT("\nlock statistics:\n"); + DRM_SYSCTL_PRINT("locks %10u\n", atomic_read(&dev->total_locks)); + DRM_SYSCTL_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks)); + DRM_SYSCTL_PRINT("contends %10u\n", atomic_read(&dev->total_contends)); + DRM_SYSCTL_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps)); + + + if (dma) { + DRM_SYSCTL_PRINT("\ndma statistics:\n"); + DRM_SYSCTL_PRINT("prio %10u\n", + atomic_read(&dma->total_prio)); + DRM_SYSCTL_PRINT("bytes %10u\n", + atomic_read(&dma->total_bytes)); + DRM_SYSCTL_PRINT("dmas %10u\n", + atomic_read(&dma->total_dmas)); + DRM_SYSCTL_PRINT("missed:\n"); + DRM_SYSCTL_PRINT(" dma %10u\n", + atomic_read(&dma->total_missed_dma)); + DRM_SYSCTL_PRINT(" lock %10u\n", + atomic_read(&dma->total_missed_lock)); + DRM_SYSCTL_PRINT(" free %10u\n", + atomic_read(&dma->total_missed_free)); + DRM_SYSCTL_PRINT(" sched %10u\n", + atomic_read(&dma->total_missed_sched)); + DRM_SYSCTL_PRINT("tried %10u\n", + atomic_read(&dma->total_tried)); + DRM_SYSCTL_PRINT("hit %10u\n", + atomic_read(&dma->total_hit)); + DRM_SYSCTL_PRINT("lost %10u\n", + atomic_read(&dma->total_lost)); + + buffer = dma->next_buffer; + if (buffer) { + DRM_SYSCTL_PRINT("next_buffer %7d\n", buffer->idx); + } else { + DRM_SYSCTL_PRINT("next_buffer none\n"); + } + buffer = dma->this_buffer; + if (buffer) { + DRM_SYSCTL_PRINT("this_buffer %7d\n", buffer->idx); + } else { + DRM_SYSCTL_PRINT("this_buffer none\n"); + } + } + + + DRM_SYSCTL_PRINT("\nvalues:\n"); + if (dev->lock.hw_lock) { + DRM_SYSCTL_PRINT("lock 0x%08x\n", + dev->lock.hw_lock->lock); + } else { + DRM_SYSCTL_PRINT("lock none\n"); + } + DRM_SYSCTL_PRINT("context_flag 0x%08x\n", dev->context_flag); + DRM_SYSCTL_PRINT("interrupt_flag 0x%08x\n", dev->interrupt_flag); + DRM_SYSCTL_PRINT("dma_flag 0x%08x\n", dev->dma_flag); + + DRM_SYSCTL_PRINT("queue_count %10d\n", dev->queue_count); + DRM_SYSCTL_PRINT("last_context %10d\n", dev->last_context); + DRM_SYSCTL_PRINT("last_switch %10u\n", dev->last_switch); + DRM_SYSCTL_PRINT("last_checked %10d\n", dev->last_checked); + + + DRM_SYSCTL_PRINT("\n q2d d2c c2f" + " q2c q2f dma sch" + " ctx lacq lhld\n\n"); + for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) { + DRM_SYSCTL_PRINT("%s %10lu %10u %10u %10u %10u %10u" + " %10u %10u %10u %10u %10u\n", + i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ", + i == DRM_DMA_HISTOGRAM_SLOTS - 1 + ? prev_value : slot_value , + + atomic_read(&dev->histo + .queued_to_dispatched[i]), + atomic_read(&dev->histo + .dispatched_to_completed[i]), + atomic_read(&dev->histo + .completed_to_freed[i]), + + atomic_read(&dev->histo + .queued_to_completed[i]), + atomic_read(&dev->histo + .queued_to_freed[i]), + atomic_read(&dev->histo.dma[i]), + atomic_read(&dev->histo.schedule[i]), + atomic_read(&dev->histo.ctx[i]), + atomic_read(&dev->histo.lacq[i]), + atomic_read(&dev->histo.lhld[i])); + prev_value = slot_value; + slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value); + } + SYSCTL_OUT(req, "", 1); + return 0; +} + +static int drm_histo_info SYSCTL_HANDLER_ARGS +{ + drm_device_t *dev = arg1; + int ret; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + ret = _drm_histo_info(oidp, arg1, arg2, req); + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return ret; +} +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/vm.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/vm.c new file mode 100644 index 000000000..9c457fca3 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm/vm.c @@ -0,0 +1,104 @@ +/* vm.c -- Memory mapping for DRM -*- c -*- + * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 22:48:11 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c,v 1.7 1999/08/21 02:48:34 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c,v 1.1 1999/09/25 14:38:02 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" + +#include <vm/vm.h> +#include <vm/pmap.h> + +static int drm_dma_mmap(dev_t kdev, vm_offset_t offset, int prot) +{ + drm_device_t *dev = kdev->si_drv1; + drm_device_dma_t *dma = dev->dma; + unsigned long physical; + unsigned long page; + + if (!dma) return -1; /* Error */ + if (!dma->pagelist) return -1; /* Nothing allocated */ + + page = offset >> PAGE_SHIFT; + physical = dma->pagelist[page]; + + DRM_DEBUG("0x%08x (page %lu) => 0x%08lx\n", offset, page, physical); + return atop(physical); +} + +int drm_mmap(dev_t kdev, vm_offset_t offset, int prot) +{ + drm_device_t *dev = kdev->si_drv1; + drm_map_t *map = NULL; + int i; + + /* DRM_DEBUG("offset = 0x%x\n", offset); */ + + if (dev->dma + && offset >= 0 + && offset < ptoa(dev->dma->page_count)) + return drm_dma_mmap(kdev, offset, prot); + + /* A sequential search of a linked list is + fine here because: 1) there will only be + about 5-10 entries in the list and, 2) a + DRI client only has to do this mapping + once, so it doesn't have to be optimized + for performance, even if the list was a + bit longer. */ + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + /* DRM_DEBUG("considering 0x%x..0x%x\n", map->offset, map->offset + map->size - 1); */ + if (offset >= map->offset + && offset < map->offset + map->size) break; + } + + if (i >= dev->map_count) { + DRM_DEBUG("can't find map\n"); + return -1; + } + if (!map || ((map->flags&_DRM_RESTRICTED) && suser(curproc))) { + DRM_DEBUG("restricted map\n"); + return -1; + } + + switch (map->type) { + case _DRM_FRAME_BUFFER: + case _DRM_REGISTERS: + case _DRM_AGP: + return atop(offset); + case _DRM_SHM: + return atop(vtophys(offset)); + default: + return -1; /* This should never happen. */ + } + DRM_DEBUG("bailing out\n"); + + return -1; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h new file mode 100644 index 000000000..863836a66 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h @@ -0,0 +1,708 @@ +/* drmP.h -- Private header for Direct Rendering Manager -*- c -*- + * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com + * Revised: Tue Oct 12 08:51:07 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v 1.58 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v 1.1 1999/09/25 14:37:59 dawes Exp $ + * + */ + +#ifndef _DRM_P_H_ +#define _DRM_P_H_ + +#ifdef _KERNEL +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/lock.h> +#include <sys/fcntl.h> +#include <sys/uio.h> +#include <sys/filio.h> +#include <sys/sysctl.h> +#include <sys/select.h> +#include <sys/bus.h> +#include <sys/taskqueue.h> + +#ifdef DRM_AGP +#include <pci/agpvar.h> +#endif + +#include "drm.h" + +typedef u_int32_t atomic_t; +typedef u_int32_t cycles_t; +typedef u_int32_t spinlock_t; +#define atomic_set(p, v) (*(p) = (v)) +#define atomic_read(p) (*(p)) +#define atomic_inc(p) atomic_add_int(p, 1) +#define atomic_dec(p) atomic_subtract_int(p, 1) +#define atomic_add(n, p) atomic_add_int(p, n) +#define atomic_sub(n, p) atomic_subtract_int(p, n) + +/* Fake this */ +static __inline u_int32_t +test_and_set_bit(int b, volatile u_int32_t *p) +{ + u_int32_t m = 1<<b; + u_int32_t r = *p & m; + *p |= m; + return r; +} + +static __inline void +clear_bit(int b, volatile u_int32_t *p) +{ + atomic_clear_int(p + (b >> 5), 1 << (b & 0x1f)); +} + +static __inline void +set_bit(int b, volatile u_int32_t *p) +{ + atomic_set_int(p + (b >> 5), 1 << (b & 0x1f)); +} + +static __inline int +test_bit(int b, volatile u_int32_t *p) +{ + return p[b >> 5] & (1 << (b & 0x1f)); +} + +static __inline int +find_first_zero_bit(volatile u_int32_t *p, int max) +{ + int b; + + for (b = 0; b < max; b += 32) { + if (p[b >> 5]) { + for (;;) { + if (p[b >> 5] & (1 << (b & 0x1f))) + return b; + b++; + } + } + } + return max; +} + +#define spldrm() spltty() + +#define memset(p, v, s) bzero(p, s) + +/* + * Software interrupts for DMA pipe feeding. The FreeBSD kernel apis + * are severely lacking here. + */ +#define SWI_DRI (SWI_VM+2) + +#define DRM_DEBUG_CODE 2 /* Include debugging code (if > 1, then + also include looping detection. */ +#define DRM_DMA_HISTOGRAM 1 /* Make histogram of DMA latency. */ + +#define DRM_HASH_SIZE 16 /* Size of key hash table */ +#define DRM_KERNEL_CONTEXT 0 /* Change drm_resctx if changed */ +#define DRM_RESERVED_CONTEXTS 1 /* Change drm_resctx if changed */ +#define DRM_LOOPING_LIMIT 5000000 +#define DRM_BSZ 1024 /* Buffer size for /dev/drm? output */ +#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */ +#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */ + +#define DRM_FLAG_DEBUG 0x01 +#define DRM_FLAG_NOCTX 0x02 + +#define DRM_MEM_DMA 0 +#define DRM_MEM_SAREA 1 +#define DRM_MEM_DRIVER 2 +#define DRM_MEM_MAGIC 3 +#define DRM_MEM_IOCTLS 4 +#define DRM_MEM_MAPS 5 +#define DRM_MEM_VMAS 6 +#define DRM_MEM_BUFS 7 +#define DRM_MEM_SEGS 8 +#define DRM_MEM_PAGES 9 +#define DRM_MEM_FILES 10 +#define DRM_MEM_QUEUES 11 +#define DRM_MEM_CMDS 12 +#define DRM_MEM_MAPPINGS 13 +#define DRM_MEM_BUFLISTS 14 +#define DRM_MEM_AGPLISTS 15 +#define DRM_MEM_TOTALAGP 16 +#define DRM_MEM_BOUNDAGP 17 +#define DRM_MEM_CTXBITMAP 18 + +#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) + + /* Backward compatibility section */ +#ifndef _PAGE_PWT + /* The name of _PAGE_WT was changed to + _PAGE_PWT in Linux 2.2.6 */ +#define _PAGE_PWT _PAGE_WT +#endif + +#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) +#define _DRM_CAS(lock,old,new,__ret) \ + do { \ + int __dummy; /* Can't mark eax as clobbered */ \ + __asm__ __volatile__( \ + "lock ; cmpxchg %4,%1\n\t" \ + "setnz %0" \ + : "=d" (__ret), \ + "=m" (__drm_dummy_lock(lock)), \ + "=a" (__dummy) \ + : "2" (old), \ + "r" (new)); \ + } while (0) + + + + /* Macros to make printk easier */ +#define DRM_ERROR(fmt, arg...) \ + printf("error: " "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg) +#define DRM_MEM_ERROR(area, fmt, arg...) \ + printf("error: " "[" DRM_NAME ":" __FUNCTION__ ":%s] *ERROR* " fmt , \ + drm_mem_stats[area].name , ##arg) +#define DRM_INFO(fmt, arg...) printf("info: " "[" DRM_NAME "] " fmt , ##arg) + +#if DRM_DEBUG_CODE +#define DRM_DEBUG(fmt, arg...) \ + do { \ + if (drm_flags&DRM_FLAG_DEBUG) \ + printf("[" DRM_NAME ":" __FUNCTION__ "] " fmt , \ + ##arg); \ + } while (0) +#else +#define DRM_DEBUG(fmt, arg...) do { } while (0) +#endif + +#define DRM_PROC_LIMIT (PAGE_SIZE-80) + +#define DRM_SYSCTL_PRINT(fmt, arg...) \ + snprintf(buf, sizeof(buf), fmt, ##arg); \ + error = SYSCTL_OUT(req, buf, strlen(buf)); \ + if (error) return error; + +#define DRM_SYSCTL_PRINT_RET(ret, fmt, arg...) \ + snprintf(buf, sizeof(buf), fmt, ##arg); \ + error = SYSCTL_OUT(req, buf, strlen(buf)); \ + if (error) { ret; return error; } + + /* Internal types and structures */ +#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#define DRM_MIN(a,b) ((a)<(b)?(a):(b)) +#define DRM_MAX(a,b) ((a)>(b)?(a):(b)) + +#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1)) +#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) +#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist) + +typedef struct drm_ioctl_desc { + d_ioctl_t *func; + int auth_needed; + int root_only; +} drm_ioctl_desc_t; + +typedef struct drm_devstate { + pid_t owner; /* X server pid holding x_lock */ + +} drm_devstate_t; + +typedef struct drm_magic_entry { + drm_magic_t magic; + struct drm_file *priv; + struct drm_magic_entry *next; +} drm_magic_entry_t; + +typedef struct drm_magic_head { + struct drm_magic_entry *head; + struct drm_magic_entry *tail; +} drm_magic_head_t; + +typedef struct drm_vma_entry { + struct vm_area_struct *vma; + struct drm_vma_entry *next; + pid_t pid; +} drm_vma_entry_t; + +typedef struct drm_buf { + int idx; /* Index into master buflist */ + int total; /* Buffer size */ + int order; /* log-base-2(total) */ + int used; /* Amount of buffer in use (for DMA) */ + unsigned long offset; /* Byte offset (used internally) */ + void *address; /* Address of buffer */ + unsigned long bus_address; /* Bus address of buffer */ + struct drm_buf *next; /* Kernel-only: used for free list */ + __volatile__ int waiting; /* On kernel DMA queue */ + __volatile__ int pending; /* On hardware DMA queue */ + int dma_wait; /* Processes waiting */ + pid_t pid; /* PID of holding process */ + int context; /* Kernel queue for this buffer */ + int while_locked;/* Dispatch this buffer while locked */ + enum { + DRM_LIST_NONE = 0, + DRM_LIST_FREE = 1, + DRM_LIST_WAIT = 2, + DRM_LIST_PEND = 3, + DRM_LIST_PRIO = 4, + DRM_LIST_RECLAIM = 5 + } list; /* Which list we're on */ + + void *dev_private; + int dev_priv_size; + +#if DRM_DMA_HISTOGRAM + struct timespec time_queued; /* Queued to kernel DMA queue */ + struct timespec time_dispatched; /* Dispatched to hardware */ + struct timespec time_completed; /* Completed by hardware */ + struct timespec time_freed; /* Back on freelist */ +#endif +} drm_buf_t; + +#if DRM_DMA_HISTOGRAM +#define DRM_DMA_HISTOGRAM_SLOTS 9 +#define DRM_DMA_HISTOGRAM_INITIAL 10 +#define DRM_DMA_HISTOGRAM_NEXT(current) ((current)*10) +typedef struct drm_histogram { + atomic_t total; + + atomic_t queued_to_dispatched[DRM_DMA_HISTOGRAM_SLOTS]; + atomic_t dispatched_to_completed[DRM_DMA_HISTOGRAM_SLOTS]; + atomic_t completed_to_freed[DRM_DMA_HISTOGRAM_SLOTS]; + + atomic_t queued_to_completed[DRM_DMA_HISTOGRAM_SLOTS]; + atomic_t queued_to_freed[DRM_DMA_HISTOGRAM_SLOTS]; + + atomic_t dma[DRM_DMA_HISTOGRAM_SLOTS]; + atomic_t schedule[DRM_DMA_HISTOGRAM_SLOTS]; + atomic_t ctx[DRM_DMA_HISTOGRAM_SLOTS]; + atomic_t lacq[DRM_DMA_HISTOGRAM_SLOTS]; + atomic_t lhld[DRM_DMA_HISTOGRAM_SLOTS]; +} drm_histogram_t; +#endif + + /* bufs is one longer than it has to be */ +typedef struct drm_waitlist { + int count; /* Number of possible buffers */ + drm_buf_t **bufs; /* List of pointers to buffers */ + drm_buf_t **rp; /* Read pointer */ + drm_buf_t **wp; /* Write pointer */ + drm_buf_t **end; /* End pointer */ + spinlock_t read_lock; + spinlock_t write_lock; +} drm_waitlist_t; + +typedef struct drm_freelist { + int initialized; /* Freelist in use */ + atomic_t count; /* Number of free buffers */ + drm_buf_t *next; /* End pointer */ + + int waiting; /* Processes waiting on free bufs */ + int low_mark; /* Low water mark */ + int high_mark; /* High water mark */ + atomic_t wfh; /* If waiting for high mark */ +} drm_freelist_t; + +typedef struct drm_buf_entry { + int buf_size; + int buf_count; + drm_buf_t *buflist; + int seg_count; + int page_order; + unsigned long *seglist; + + drm_freelist_t freelist; +} drm_buf_entry_t; + +typedef struct drm_hw_lock { + __volatile__ unsigned int lock; + char padding[60]; /* Pad to cache line */ +} drm_hw_lock_t; + +typedef TAILQ_HEAD(drm_file_list, drm_file) drm_file_list_t; +typedef struct drm_file { + TAILQ_ENTRY(drm_file) link; + int authenticated; + int minor; + pid_t pid; + uid_t uid; + int refs; + drm_magic_t magic; + unsigned long ioctl_count; + struct drm_device *devXX; +} drm_file_t; + + +typedef struct drm_queue { + atomic_t use_count; /* Outstanding uses (+1) */ + atomic_t finalization; /* Finalization in progress */ + atomic_t block_count; /* Count of processes waiting */ + atomic_t block_read; /* Queue blocked for reads */ + int read_queue; /* Processes waiting on block_read */ + atomic_t block_write; /* Queue blocked for writes */ + int write_queue; /* Processes waiting on block_write */ + atomic_t total_queued; /* Total queued statistic */ + atomic_t total_flushed;/* Total flushes statistic */ + atomic_t total_locks; /* Total locks statistics */ + drm_ctx_flags_t flags; /* Context preserving and 2D-only */ + drm_waitlist_t waitlist; /* Pending buffers */ + int flush_queue; /* Processes waiting until flush */ +} drm_queue_t; + +typedef struct drm_lock_data { + drm_hw_lock_t *hw_lock; /* Hardware lock */ + pid_t pid; /* PID of lock holder (0=kernel) */ + int lock_queue; /* Queue of blocked processes */ + unsigned long lock_time; /* Time of last lock in jiffies */ +} drm_lock_data_t; + +typedef struct drm_device_dma { + /* Performance Counters */ + atomic_t total_prio; /* Total DRM_DMA_PRIORITY */ + atomic_t total_bytes; /* Total bytes DMA'd */ + atomic_t total_dmas; /* Total DMA buffers dispatched */ + + atomic_t total_missed_dma; /* Missed drm_do_dma */ + atomic_t total_missed_lock; /* Missed lock in drm_do_dma */ + atomic_t total_missed_free; /* Missed drm_free_this_buffer */ + atomic_t total_missed_sched;/* Missed drm_dma_schedule */ + + atomic_t total_tried; /* Tried next_buffer */ + atomic_t total_hit; /* Sent next_buffer */ + atomic_t total_lost; /* Lost interrupt */ + + drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; + int buf_count; + drm_buf_t **buflist; /* Vector of pointers info bufs */ + int seg_count; + int page_count; + vm_offset_t *pagelist; + unsigned long byte_count; + enum { + _DRM_DMA_USE_AGP = 0x01 + } flags; + + /* DMA support */ + drm_buf_t *this_buffer; /* Buffer being sent */ + drm_buf_t *next_buffer; /* Selected buffer to send */ + drm_queue_t *next_queue; /* Queue from which buffer selected*/ + int waiting; /* Processes waiting on free bufs */ +} drm_device_dma_t; + +#ifdef DRM_AGP + +typedef struct drm_agp_mem { + void *handle; + unsigned long bound; /* address */ + int pages; + struct drm_agp_mem *prev; + struct drm_agp_mem *next; +} drm_agp_mem_t; + +typedef struct drm_agp_head { + device_t agpdev; + struct agp_info info; + const char *chipset; + drm_agp_mem_t *memory; + unsigned long mode; + int enabled; + int acquired; + unsigned long base; + int agp_mtrr; +} drm_agp_head_t; + +#endif + +typedef struct drm_device { + const char *name; /* Simple driver name */ + char *unique; /* Unique identifier: e.g., busid */ + int unique_len; /* Length of unique field */ + device_t device; /* Device instance from newbus */ + dev_t devnode; /* Device number for mknod */ + char *devname; /* For /proc/interrupts */ + + int blocked; /* Blocked due to VC switch? */ + int flags; /* Flags to open(2) */ + int writable; /* Opened with FWRITE */ + struct proc_dir_entry *root; /* Root for this device's entries */ + + /* Locks */ + struct simplelock count_lock; /* For inuse, open_count, buf_use */ + struct lock dev_lock; /* For others */ + + /* Usage Counters */ + int open_count; /* Outstanding files open */ + atomic_t ioctl_count; /* Outstanding IOCTLs pending */ + atomic_t vma_count; /* Outstanding vma areas open */ + int buf_use; /* Buffers in use -- cannot alloc */ + atomic_t buf_alloc; /* Buffer allocation in progress */ + + /* Performance Counters */ + atomic_t total_open; + atomic_t total_close; + atomic_t total_ioctl; + atomic_t total_irq; /* Total interruptions */ + atomic_t total_ctx; /* Total context switches */ + + atomic_t total_locks; + atomic_t total_unlocks; + atomic_t total_contends; + atomic_t total_sleeps; + + /* Authentication */ + drm_file_list_t files; + drm_magic_head_t magiclist[DRM_HASH_SIZE]; + + /* Memory management */ + drm_map_t **maplist; /* Vector of pointers to regions */ + int map_count; /* Number of mappable regions */ + + drm_vma_entry_t *vmalist; /* List of vmas (for debugging) */ + drm_lock_data_t lock; /* Information on hardware lock */ + + /* DMA queues (contexts) */ + int queue_count; /* Number of active DMA queues */ + int queue_reserved; /* Number of reserved DMA queues */ + int queue_slots; /* Actual length of queuelist */ + drm_queue_t **queuelist; /* Vector of pointers to DMA queues */ + drm_device_dma_t *dma; /* Optional pointer for DMA support */ + + /* Context support */ + struct resource *irq; /* Interrupt used by board */ + void *irqh; /* Handle from bus_setup_intr */ + __volatile__ int context_flag; /* Context swapping flag */ + __volatile__ int interrupt_flag;/* Interruption handler flag */ + __volatile__ int dma_flag; /* DMA dispatch flag */ + struct callout timer; /* Timer for delaying ctx switch */ + int context_wait; /* Processes waiting on ctx switch */ + int last_checked; /* Last context checked for DMA */ + int last_context; /* Last current context */ + int last_switch; /* Time at last context switch */ + struct task task; + struct timespec ctx_start; + struct timespec lck_start; +#if DRM_DMA_HISTOGRAM + drm_histogram_t histo; +#endif + + /* Callback to X server for context switch + and for heavy-handed reset. */ + char buf[DRM_BSZ]; /* Output buffer */ + char *buf_rp; /* Read pointer */ + char *buf_wp; /* Write pointer */ + char *buf_end; /* End pointer */ + struct sigio *buf_sigio; /* Processes waiting for SIGIO */ + struct selinfo buf_sel; /* Workspace for select/poll */ + int buf_readers; /* Processes waiting to read */ + int buf_writers; /* Processes waiting to ctx switch */ + int buf_selecting; /* True if poll sleeper */ + + /* Sysctl support */ + struct drm_sysctl_info *sysctl; + +#ifdef DRM_AGP + drm_agp_head_t *agp; +#endif + u_int32_t *ctx_bitmap; + void *dev_private; +} drm_device_t; + + + /* Internal function definitions */ + + /* Misc. support (init.c) */ +extern int drm_flags; +extern void drm_parse_options(char *s); + + + /* Device support (fops.c) */ +extern drm_file_t *drm_find_file_by_proc(drm_device_t *dev, struct proc *p); +extern int drm_open_helper(dev_t kdev, int flags, int fmt, struct proc *p, + drm_device_t *dev); +extern d_close_t drm_close; +extern d_read_t drm_read; +extern d_write_t drm_write; +extern d_poll_t drm_poll; +extern int drm_fsetown(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p); +extern int drm_fgetown(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p); +extern int drm_write_string(drm_device_t *dev, const char *s); + +#if 0 + /* Mapping support (vm.c) */ +extern unsigned long drm_vm_nopage(struct vm_area_struct *vma, + unsigned long address, + int write_access); +extern unsigned long drm_vm_shm_nopage(struct vm_area_struct *vma, + unsigned long address, + int write_access); +extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma, + unsigned long address, + int write_access); +extern void drm_vm_open(struct vm_area_struct *vma); +extern void drm_vm_close(struct vm_area_struct *vma); +extern int drm_mmap_dma(struct file *filp, + struct vm_area_struct *vma); +#endif +extern d_mmap_t drm_mmap; + + /* Proc support (proc.c) */ +extern int drm_sysctl_init(drm_device_t *dev); +extern int drm_sysctl_cleanup(drm_device_t *dev); + + /* Memory management support (memory.c) */ +extern void drm_mem_init(void); +extern int drm_mem_info SYSCTL_HANDLER_ARGS; +extern void *drm_alloc(size_t size, int area); +extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, + int area); +extern char *drm_strdup(const char *s, int area); +extern void drm_strfree(char *s, int area); +extern void drm_free(void *pt, size_t size, int area); +extern unsigned long drm_alloc_pages(int order, int area); +extern void drm_free_pages(unsigned long address, int order, + int area); +extern void *drm_ioremap(unsigned long offset, unsigned long size); +extern void drm_ioremapfree(void *pt, unsigned long size); + +#ifdef DRM_AGP +extern void *drm_alloc_agp(int pages, u_int32_t type); +extern int drm_free_agp(void *handle, int pages); +extern int drm_bind_agp(void *handle, unsigned int start); +extern int drm_unbind_agp(void *handle); +#endif + + /* Buffer management support (bufs.c) */ +extern int drm_order(unsigned long size); +extern d_ioctl_t drm_addmap; +extern d_ioctl_t drm_addbufs; +extern d_ioctl_t drm_infobufs; +extern d_ioctl_t drm_markbufs; +extern d_ioctl_t drm_freebufs; +extern d_ioctl_t drm_mapbufs; + + + /* Buffer list management support (lists.c) */ +extern int drm_waitlist_create(drm_waitlist_t *bl, int count); +extern int drm_waitlist_destroy(drm_waitlist_t *bl); +extern int drm_waitlist_put(drm_waitlist_t *bl, drm_buf_t *buf); +extern drm_buf_t *drm_waitlist_get(drm_waitlist_t *bl); + +extern int drm_freelist_create(drm_freelist_t *bl, int count); +extern int drm_freelist_destroy(drm_freelist_t *bl); +extern int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, + drm_buf_t *buf); +extern drm_buf_t *drm_freelist_get(drm_freelist_t *bl, int block); + + /* DMA support (gen_dma.c) */ +extern void drm_dma_setup(drm_device_t *dev); +extern void drm_dma_takedown(drm_device_t *dev); +extern void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf); +extern void drm_reclaim_buffers(drm_device_t *dev, pid_t pid); +extern int drm_context_switch(drm_device_t *dev, int old, int new); +extern int drm_context_switch_complete(drm_device_t *dev, int new); +extern void drm_wakeup(drm_device_t *dev, drm_buf_t *buf); +extern void drm_clear_next_buffer(drm_device_t *dev); +extern int drm_select_queue(drm_device_t *dev, + void (*wrapper)(void *)); +extern int drm_dma_enqueue(drm_device_t *dev, drm_dma_t *dma); +extern int drm_dma_get_buffers(drm_device_t *dev, drm_dma_t *dma); +#if DRM_DMA_HISTOGRAM +extern int drm_histogram_slot(struct timespec *ts); +extern void drm_histogram_compute(drm_device_t *dev, drm_buf_t *buf); +#endif + + + /* Misc. IOCTL support (ioctl.c) */ +extern d_ioctl_t drm_irq_busid; +extern d_ioctl_t drm_getunique; +extern d_ioctl_t drm_setunique; + + + /* Context IOCTL support (context.c) */ +extern d_ioctl_t drm_resctx; +extern d_ioctl_t drm_addctx; +extern d_ioctl_t drm_modctx; +extern d_ioctl_t drm_getctx; +extern d_ioctl_t drm_switchctx; +extern d_ioctl_t drm_newctx; +extern d_ioctl_t drm_rmctx; + + + /* Drawable IOCTL support (drawable.c) */ +extern d_ioctl_t drm_adddraw; +extern d_ioctl_t drm_rmdraw; + + + /* Authentication IOCTL support (auth.c) */ +extern int drm_add_magic(drm_device_t *dev, drm_file_t *priv, + drm_magic_t magic); +extern int drm_remove_magic(drm_device_t *dev, drm_magic_t magic); +extern d_ioctl_t drm_getmagic; +extern d_ioctl_t drm_authmagic; + + + /* Locking IOCTL support (lock.c) */ +extern d_ioctl_t drm_block; +extern d_ioctl_t drm_unblock; +extern int drm_lock_take(__volatile__ unsigned int *lock, + unsigned int context); +extern int drm_lock_transfer(drm_device_t *dev, + __volatile__ unsigned int *lock, + unsigned int context); +extern int drm_lock_free(drm_device_t *dev, + __volatile__ unsigned int *lock, + unsigned int context); +extern d_ioctl_t drm_finish; +extern int drm_flush_unblock(drm_device_t *dev, int context, + drm_lock_flags_t flags); +extern int drm_flush_block_and_flush(drm_device_t *dev, int context, + drm_lock_flags_t flags); + + /* Context Bitmap support (ctxbitmap.c) */ +extern int drm_ctxbitmap_init(drm_device_t *dev); +extern void drm_ctxbitmap_cleanup(drm_device_t *dev); +extern int drm_ctxbitmap_next(drm_device_t *dev); +extern void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle); + +#ifdef DRM_AGP + /* AGP/GART support (agpsupport.c) */ +extern drm_agp_head_t *drm_agp_init(void); +extern d_ioctl_t drm_agp_acquire; +extern d_ioctl_t drm_agp_release; +extern d_ioctl_t drm_agp_enable; +extern d_ioctl_t drm_agp_info; +extern d_ioctl_t drm_agp_alloc; +extern d_ioctl_t drm_agp_free; +extern d_ioctl_t drm_agp_unbind; +extern d_ioctl_t drm_agp_bind; +#endif +#endif +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/Makefile b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/Makefile new file mode 100644 index 000000000..dd6110382 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +KMOD = gamma +SRCS = gamma_drv.c gamma_dma.c +SRCS += device_if.h bus_if.h pci_if.h +CFLAGS += ${DEBUG_FLAGS} -I.. +KERN = /usr/src/sys + +@: + ln -sf /sys @ + +machine: + ln -sf /sys/i386/include machine + +.include "/usr/src/sys/conf/kmod.mk" diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_dma.c new file mode 100644 index 000000000..177440db8 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_dma.c @@ -0,0 +1,802 @@ +/* gamma_dma.c -- DMA support for GMX 2000 -*- c -*- + * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com + * Revised: Thu Sep 16 12:55:37 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c,v 1.9 1999/09/16 16:56:18 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c,v 1.1 1999/09/25 14:38:00 dawes Exp $ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include "gamma_drv.h" + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +/* WARNING!!! MAGIC NUMBER!!! The number of regions already added to the + kernel must be specified here. Currently, the number is 2. This must + match the order the X server uses for instantiating register regions , + or must be passed in a new ioctl. */ +#define GAMMA_REG(reg) \ + (2 \ + + ((reg < 0x1000) \ + ? 0 \ + : ((reg < 0x10000) ? 1 : ((reg < 0x11000) ? 2 : 3)))) + +#define GAMMA_OFF(reg) \ + ((reg < 0x1000) \ + ? reg \ + : ((reg < 0x10000) \ + ? (reg - 0x1000) \ + : ((reg < 0x11000) \ + ? (reg - 0x10000) \ + : (reg - 0x11000)))) + +#define GAMMA_BASE(reg) ((unsigned long)dev->maplist[GAMMA_REG(reg)]->handle) +#define GAMMA_ADDR(reg) (GAMMA_BASE(reg) + GAMMA_OFF(reg)) +#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg) +#define GAMMA_READ(reg) GAMMA_DEREF(reg) +#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0) + +#define GAMMA_BROADCASTMASK 0x9378 +#define GAMMA_COMMANDINTENABLE 0x0c48 +#define GAMMA_DMAADDRESS 0x0028 +#define GAMMA_DMACOUNT 0x0030 +#define GAMMA_FILTERMODE 0x8c00 +#define GAMMA_GCOMMANDINTFLAGS 0x0c50 +#define GAMMA_GCOMMANDMODE 0x0c40 +#define GAMMA_GCOMMANDSTATUS 0x0c60 +#define GAMMA_GDELAYTIMER 0x0c38 +#define GAMMA_GDMACONTROL 0x0060 +#define GAMMA_GINTENABLE 0x0808 +#define GAMMA_GINTFLAGS 0x0810 +#define GAMMA_INFIFOSPACE 0x0018 +#define GAMMA_OUTFIFOWORDS 0x0020 +#define GAMMA_OUTPUTFIFO 0x2000 +#define GAMMA_SYNC 0x8c40 +#define GAMMA_SYNC_TAG 0x0188 + +static __inline void gamma_dma_dispatch(drm_device_t *dev, + vm_offset_t address, + vm_size_t length) +{ + GAMMA_WRITE(GAMMA_DMAADDRESS, vtophys(address)); + while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4) + ; + GAMMA_WRITE(GAMMA_DMACOUNT, length / 4); +} + +static __inline void gamma_dma_quiescent(drm_device_t *dev) +{ + while (GAMMA_READ(GAMMA_DMACOUNT)) + ; + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) + ; + GAMMA_WRITE(GAMMA_BROADCASTMASK, 3); + GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); + GAMMA_WRITE(GAMMA_SYNC, 0); + + /* Read from first MX */ + do { + while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) + ; + } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); + + + /* Read from second MX */ + do { + while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000)) + ; + } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG); +} + +static __inline void gamma_dma_ready(drm_device_t *dev) +{ + while (GAMMA_READ(GAMMA_DMACOUNT)) + ; +} + +static __inline int gamma_dma_is_ready(drm_device_t *dev) +{ + return !GAMMA_READ(GAMMA_DMACOUNT); +} + +static void gamma_dma_service(void *arg) +{ + drm_device_t *dev = (drm_device_t *)arg; + drm_device_dma_t *dma = dev->dma; + + atomic_inc(&dev->total_irq); + GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */ + GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8); + GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001); + if (gamma_dma_is_ready(dev)) { + /* Free previous buffer */ + if (test_and_set_bit(0, &dev->dma_flag)) { + atomic_inc(&dma->total_missed_free); + return; + } + if (dma->this_buffer) { + drm_free_buffer(dev, dma->this_buffer); + dma->this_buffer = NULL; + } + clear_bit(0, &dev->dma_flag); + +#if 0 + /* Dispatch new buffer */ + queue_task(&dev->tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); +#endif + } +} + +/* Only called by gamma_dma_schedule. */ +static int gamma_do_dma(drm_device_t *dev, int locked) +{ + unsigned long address; + unsigned long length; + drm_buf_t *buf; + int retcode = 0; + drm_device_dma_t *dma = dev->dma; +#if DRM_DMA_HISTOGRAM + struct timespec dma_start, dma_stop; +#endif + + if (test_and_set_bit(0, &dev->dma_flag)) { + atomic_inc(&dma->total_missed_dma); + return EBUSY; + } + +#if DRM_DMA_HISTOGRAM + getnanotime(&dma_start); +#endif + + if (!dma->next_buffer) { + DRM_ERROR("No next_buffer\n"); + clear_bit(0, &dev->dma_flag); + return EINVAL; + } + + buf = dma->next_buffer; + address = (unsigned long)buf->address; + length = buf->used; + + DRM_DEBUG("context %d, buffer %d (%ld bytes)\n", + buf->context, buf->idx, length); + + if (buf->list == DRM_LIST_RECLAIM) { + drm_clear_next_buffer(dev); + drm_free_buffer(dev, buf); + clear_bit(0, &dev->dma_flag); + return EINVAL; + } + + if (!length) { + DRM_ERROR("0 length buffer\n"); + drm_clear_next_buffer(dev); + drm_free_buffer(dev, buf); + clear_bit(0, &dev->dma_flag); + return 0; + } + + if (!gamma_dma_is_ready(dev)) { + clear_bit(0, &dev->dma_flag); + return EBUSY; + } + + if (buf->while_locked) { + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("Dispatching buffer %d from pid %d" + " \"while locked\", but no lock held\n", + buf->idx, buf->pid); + } + } else { + if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + atomic_inc(&dma->total_missed_lock); + clear_bit(0, &dev->dma_flag); + return EBUSY; + } + } + + if (dev->last_context != buf->context + && !(dev->queuelist[buf->context]->flags + & _DRM_CONTEXT_PRESERVED)) { + /* PRE: dev->last_context != buf->context */ + if (drm_context_switch(dev, dev->last_context, buf->context)) { + drm_clear_next_buffer(dev); + drm_free_buffer(dev, buf); + } + retcode = EBUSY; + goto cleanup; + + /* POST: we will wait for the context + switch and will dispatch on a later call + when dev->last_context == buf->context. + NOTE WE HOLD THE LOCK THROUGHOUT THIS + TIME! */ + } + + drm_clear_next_buffer(dev); + buf->pending = 1; + buf->waiting = 0; + buf->list = DRM_LIST_PEND; +#if DRM_DMA_HISTOGRAM + getnanotime(&buf->time_dispatched); +#endif + + gamma_dma_dispatch(dev, address, length); + drm_free_buffer(dev, dma->this_buffer); + dma->this_buffer = buf; + + atomic_add(length, &dma->total_bytes); + atomic_inc(&dma->total_dmas); + + if (!buf->while_locked && !dev->context_flag && !locked) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("\n"); + } + } +cleanup: + + clear_bit(0, &dev->dma_flag); + +#if DRM_DMA_HISTOGRAM + getnanotime(&dma_stop); + timespecsub(&dma_stop, &dma_start); + atomic_inc(&dev->histo.ctx[drm_histogram_slot(&dma_stop)]); +#endif + + return retcode; +} + +static void gamma_dma_schedule_wrapper(void *dev) +{ + gamma_dma_schedule(dev, 0); +} + +int gamma_dma_schedule(drm_device_t *dev, int locked) +{ + int next; + drm_queue_t *q; + drm_buf_t *buf; + int retcode = 0; + int processed = 0; + int missed; + int expire = 20; + drm_device_dma_t *dma = dev->dma; +#if DRM_DMA_HISTOGRAM + struct timespec schedule_start; +#endif + + if (test_and_set_bit(0, &dev->interrupt_flag)) { + /* Not reentrant */ + atomic_inc(&dma->total_missed_sched); + return EBUSY; + } + missed = atomic_read(&dma->total_missed_sched); + +#if DRM_DMA_HISTOGRAM + getnanotime(&schedule_start); +#endif + +again: + if (dev->context_flag) { + clear_bit(0, &dev->interrupt_flag); + return EBUSY; + } + if (dma->next_buffer) { + /* Unsent buffer that was previously + selected, but that couldn't be sent + because the lock could not be obtained + or the DMA engine wasn't ready. Try + again. */ + atomic_inc(&dma->total_tried); + if (!(retcode = gamma_do_dma(dev, locked))) { + atomic_inc(&dma->total_hit); + ++processed; + } + } else { + do { + next = drm_select_queue(dev, + gamma_dma_schedule_wrapper); + if (next >= 0) { + q = dev->queuelist[next]; + buf = drm_waitlist_get(&q->waitlist); + dma->next_buffer = buf; + dma->next_queue = q; + if (buf && buf->list == DRM_LIST_RECLAIM) { + drm_clear_next_buffer(dev); + drm_free_buffer(dev, buf); + } + } + } while (next >= 0 && !dma->next_buffer); + if (dma->next_buffer) { + if (!(retcode = gamma_do_dma(dev, locked))) { + ++processed; + } + } + } + + if (--expire) { + if (missed != atomic_read(&dma->total_missed_sched)) { + atomic_inc(&dma->total_lost); + if (gamma_dma_is_ready(dev)) goto again; + } + if (processed && gamma_dma_is_ready(dev)) { + atomic_inc(&dma->total_lost); + processed = 0; + goto again; + } + } + + clear_bit(0, &dev->interrupt_flag); + +#if DRM_DMA_HISTOGRAM + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &schedule_start); + atomic_inc(&dev->histo.schedule[drm_histogram_slot(&ts)]); + } +#endif + return retcode; +} + +static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) +{ + struct proc *p = curproc; + unsigned long address; + unsigned long length; + int must_free = 0; + int retcode = 0; + int i; + int idx; + drm_buf_t *buf; + drm_buf_t *last_buf = NULL; + drm_device_dma_t *dma = dev->dma; + static int never; + + /* Turn off interrupt handling */ + while (test_and_set_bit(0, &dev->interrupt_flag)) { + retcode = tsleep(&never, PZERO|PCATCH, "gamp1", 1); + if (retcode) + return retcode; + } + if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) { + while (!drm_lock_take(&dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + retcode = tsleep(&never, PZERO|PCATCH, "gamp2", 1); + if (retcode) + return retcode; + } + ++must_free; + } + atomic_inc(&dma->total_prio); + + for (i = 0; i < d->send_count; i++) { + idx = d->send_indices[i]; + if (idx < 0 || idx >= dma->buf_count) { + DRM_ERROR("Index %d (of %d max)\n", + d->send_indices[i], dma->buf_count - 1); + continue; + } + buf = dma->buflist[ idx ]; + if (buf->pid != p->p_pid) { + DRM_ERROR("Process %d using buffer owned by %d\n", + p->p_pid, buf->pid); + retcode = EINVAL; + goto cleanup; + } + if (buf->list != DRM_LIST_NONE) { + DRM_ERROR("Process %d using %d's buffer on list %d\n", + p->p_pid, buf->pid, buf->list); + retcode = EINVAL; + goto cleanup; + } + /* This isn't a race condition on + buf->list, since our concern is the + buffer reclaim during the time the + process closes the /dev/drm? handle, so + it can't also be doing DMA. */ + buf->list = DRM_LIST_PRIO; + buf->used = d->send_sizes[i]; + buf->context = d->context; + buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED; + address = (unsigned long)buf->address; + length = buf->used; + if (!length) { + DRM_ERROR("0 length buffer\n"); + } + if (buf->pending) { + DRM_ERROR("Sending pending buffer:" + " buffer %d, offset %d\n", + d->send_indices[i], i); + retcode = EINVAL; + goto cleanup; + } + if (buf->waiting) { + DRM_ERROR("Sending waiting buffer:" + " buffer %d, offset %d\n", + d->send_indices[i], i); + retcode = EINVAL; + goto cleanup; + } + buf->pending = 1; + + if (dev->last_context != buf->context + && !(dev->queuelist[buf->context]->flags + & _DRM_CONTEXT_PRESERVED)) { + atomic_inc(&dev->context_wait); + /* PRE: dev->last_context != buf->context */ + drm_context_switch(dev, dev->last_context, + buf->context); + /* POST: we will wait for the context + switch and will dispatch on a later call + when dev->last_context == buf->context. + NOTE WE HOLD THE LOCK THROUGHOUT THIS + TIME! */ + retcode = tsleep(&dev->context_wait, PZERO|PCATCH, + "gamctx", 0); + atomic_dec(&dev->context_wait); + if (retcode) + goto cleanup; + if (dev->last_context != buf->context) { + DRM_ERROR("Context mismatch: %d %d\n", + dev->last_context, + buf->context); + } + } + +#if DRM_DMA_HISTOGRAM + getnanotime(&buf->time_queued); + buf->time_dispatched = buf->time_queued; +#endif + gamma_dma_dispatch(dev, address, length); + atomic_add(length, &dma->total_bytes); + atomic_inc(&dma->total_dmas); + + if (last_buf) { + drm_free_buffer(dev, last_buf); + } + last_buf = buf; + } + + +cleanup: + if (last_buf) { + gamma_dma_ready(dev); + drm_free_buffer(dev, last_buf); + } + + if (must_free && !dev->context_flag) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("\n"); + } + } + clear_bit(0, &dev->interrupt_flag); + return retcode; +} + +static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d) +{ + struct proc *p = curproc; + drm_buf_t *last_buf = NULL; + int retcode = 0; + drm_device_dma_t *dma = dev->dma; + + + if ((retcode = drm_dma_enqueue(dev, d))) { + return retcode; + } + + gamma_dma_schedule(dev, 0); + + if (d->flags & _DRM_DMA_BLOCK) { + last_buf = dma->buflist[d->send_indices[d->send_count-1]]; + atomic_inc(&last_buf->dma_wait); + } + + if (d->flags & _DRM_DMA_BLOCK) { + DRM_DEBUG("%d waiting\n", p->p_pid); + for (;;) { + retcode = tsleep(&last_buf->dma_wait, PZERO|PCATCH, + "gamdw", 0); + if (!last_buf->waiting + && !last_buf->pending) + break; /* finished */ + if (retcode) + break; + } + + DRM_DEBUG("%d running\n", p->p_pid); + atomic_dec(&last_buf->dma_wait); + if (!retcode + || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) { + if (!last_buf->dma_wait) { + drm_free_buffer(dev, last_buf); + } + } + if (retcode) { + DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n", + d->context, + last_buf->waiting, + last_buf->pending, + DRM_WAITCOUNT(dev, d->context), + last_buf->idx, + last_buf->list, + last_buf->pid, + p->p_pid); + } + } + return retcode; +} + +int gamma_dma(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + drm_dma_t d; + + d = *(drm_dma_t *) data; + DRM_DEBUG("%d %d: %d send, %d req\n", + p->p_pid, d.context, d.send_count, d.request_count); + + if (d.context == DRM_KERNEL_CONTEXT || d.context >= dev->queue_slots) { + DRM_ERROR("Process %d using context %d\n", + p->p_pid, d.context); + return EINVAL; + } + if (d.send_count < 0 || d.send_count > dma->buf_count) { + DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n", + p->p_pid, d.send_count, dma->buf_count); + return EINVAL; + } + if (d.request_count < 0 || d.request_count > dma->buf_count) { + DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", + p->p_pid, d.request_count, dma->buf_count); + return EINVAL; + } + + if (d.send_count) { + if (d.flags & _DRM_DMA_PRIORITY) + retcode = gamma_dma_priority(dev, &d); + else + retcode = gamma_dma_send_buffers(dev, &d); + } + + d.granted_count = 0; + + if (!retcode && d.request_count) { + retcode = drm_dma_get_buffers(dev, &d); + } + + DRM_DEBUG("%d returning, granted = %d\n", + p->p_pid, d.granted_count); + *(drm_dma_t *) data = d; + + return retcode; +} + +int gamma_irq_install(drm_device_t *dev, int irq) +{ + int rid; + int retcode; + + if (!irq) return EINVAL; + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + if (dev->irq) { + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return EBUSY; + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + DRM_DEBUG("%d\n", irq); + + dev->context_flag = 0; + dev->interrupt_flag = 0; + dev->dma_flag = 0; + + dev->dma->next_buffer = NULL; + dev->dma->next_queue = NULL; + dev->dma->this_buffer = NULL; + +#if 0 + dev->tq.next = NULL; + dev->tq.sync = 0; + dev->tq.routine = gamma_dma_schedule_tq_wrapper; + dev->tq.data = dev; +#endif + /* Before installing handler */ + GAMMA_WRITE(GAMMA_GCOMMANDMODE, 0); + GAMMA_WRITE(GAMMA_GDMACONTROL, 0); + + /* Install handler */ + rid = 0; + dev->irq = bus_alloc_resource(dev->device, SYS_RES_IRQ, &rid, + 0, ~0, 1, RF_SHAREABLE); + if (!dev->irq) + return ENOENT; + + retcode = bus_setup_intr(dev->device, dev->irq, INTR_TYPE_TTY, + gamma_dma_service, dev, &dev->irqh); + if (retcode) { + bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irq); + dev->irq = 0; + return retcode; + } + + /* After installing handler */ + GAMMA_WRITE(GAMMA_GINTENABLE, 0x2001); + GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0x0008); + GAMMA_WRITE(GAMMA_GDELAYTIMER, 0x39090); + + return 0; +} + +int gamma_irq_uninstall(drm_device_t *dev) +{ + if (!dev->irq) + return EINVAL; + + DRM_DEBUG("%ld\n", rman_get_start(dev->irq)); + + GAMMA_WRITE(GAMMA_GDELAYTIMER, 0); + GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0); + GAMMA_WRITE(GAMMA_GINTENABLE, 0); + + bus_teardown_intr(dev->device, dev->irq, dev->irqh); + bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irq); + dev->irq = 0; + + return 0; +} + + +int gamma_control(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_control_t ctl; + int retcode; + + ctl = *(drm_control_t *) data; + + switch (ctl.func) { + case DRM_INST_HANDLER: + if ((retcode = gamma_irq_install(dev, ctl.irq))) + return retcode; + break; + case DRM_UNINST_HANDLER: + if ((retcode = gamma_irq_uninstall(dev))) + return retcode; + break; + default: + return EINVAL; + } + return 0; +} + +int gamma_lock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + int ret = 0; + drm_lock_t lock; + drm_queue_t *q; +#if DRM_DMA_HISTOGRAM + struct timespec start; + + getnanotime(&start); + dev->lck_start = start; +#endif + + lock = *(drm_lock_t *) data; + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + p->p_pid, lock.context); + return EINVAL; + } + + DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", + lock.context, p->p_pid, dev->lock.hw_lock->lock, + lock.flags); + + if (lock.context < 0 || lock.context >= dev->queue_count) + return EINVAL; + q = dev->queuelist[lock.context]; + + ret = drm_flush_block_and_flush(dev, lock.context, lock.flags); + + if (!ret) { + if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) + != lock.context) { + long j = ticks - dev->lock.lock_time; + + if (j > 0 && j <= DRM_LOCK_SLICE) { + /* Can't take lock if we just had it and + there is contention. */ + static int never; + ret = tsleep(&never, PZERO|PCATCH, + "gaml1", j); + if (ret) + return ret; + } + } + atomic_inc(&dev->lock.lock_queue); + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + ret = EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + lock.context)) { + dev->lock.pid = p->p_pid; + dev->lock.lock_time = ticks; + atomic_inc(&dev->total_locks); + atomic_inc(&q->total_locks); + break; /* Got lock */ + } + + /* Contention */ + atomic_inc(&dev->total_sleeps); + ret = tsleep(&dev->lock.lock_queue, PZERO|PCATCH, + "gaml2", 0); + if (ret) + break; + } + atomic_dec(&dev->lock.lock_queue); + } + + drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */ + + if (!ret) { + if (lock.flags & _DRM_LOCK_READY) + gamma_dma_ready(dev); + if (lock.flags & _DRM_LOCK_QUIESCENT) + gamma_dma_quiescent(dev); + } + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); + +#if DRM_DMA_HISTOGRAM + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &start); + atomic_inc(&dev->histo.lacq[drm_histogram_slot(&ts)]); + } +#endif + + return ret; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_drv.c new file mode 100644 index 000000000..fe71737a5 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_drv.c @@ -0,0 +1,574 @@ +/* gamma.c -- 3dlabs GMX 2000 driver -*- c -*- + * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com + * Revised: Tue Oct 12 08:51:36 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.c,v 1.17 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.c,v 1.1 1999/09/25 14:38:00 dawes Exp $ + * + */ + +#include "drmP.h" +#include "gamma_drv.h" + +#include <pci/pcivar.h> + +MODULE_DEPEND(gamma, drm, 1, 1, 1); + +static int gamma_init(device_t nbdev); +static void gamma_cleanup(device_t nbdev); + +static int gamma_probe(device_t dev) +{ + const char *s = 0; + + switch (pci_get_devid(dev)) { + case 0x00083d3d: + s = "3D Labs Gamma graphics accelerator"; + break; + } + + if (s) { + device_set_desc(dev, s); + return 0; + } + + return ENXIO; +} + +static int gamma_attach(device_t dev) +{ + gamma_init(dev); + return 0; +} + +static int gamma_detach(device_t dev) +{ + gamma_cleanup(dev); + return 0; +} + +static device_method_t gamma_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, gamma_probe), + DEVMETHOD(device_attach, gamma_attach), + DEVMETHOD(device_detach, gamma_detach), + + { 0, 0 } +}; + +static driver_t gamma_driver = { + "drm", + gamma_methods, + sizeof(drm_device_t), +}; + +static devclass_t gamma_devclass; +#define GAMMA_SOFTC(unit) \ + ((drm_device_t *) devclass_get_softc(gamma_devclass, unit)) + +DRIVER_MODULE(if_gamma, pci, gamma_driver, gamma_devclass, 0, 0); + +#define GAMMA_NAME "gamma" +#define GAMMA_DESC "3dlabs GMX 2000" +#define GAMMA_DATE "19990830" +#define GAMMA_MAJOR 0 +#define GAMMA_MINOR 0 +#define GAMMA_PATCHLEVEL 5 + +#define CDEV_MAJOR 200 + +static struct cdevsw gamma_cdevsw = { + /* open */ gamma_open, + /* close */ gamma_close, + /* read */ drm_read, + /* write */ drm_write, + /* ioctl */ gamma_ioctl, + /* poll */ nopoll, + /* mmap */ drm_mmap, + /* strategy */ nostrategy, + /* name */ "gamma", + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ D_TTY | D_TRACKCLOSE, + /* bmaj */ -1 +}; + +static drm_ioctl_desc_t gamma_ioctls[] = { + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { gamma_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { gamma_control, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { gamma_dma, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { gamma_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { gamma_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, +}; +#define GAMMA_IOCTL_COUNT DRM_ARRAY_SIZE(gamma_ioctls) + +static int gamma_setup(drm_device_t *dev) +{ + int i; + + device_busy(dev->device); + + atomic_set(&dev->ioctl_count, 0); + atomic_set(&dev->vma_count, 0); + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + + drm_dma_setup(dev); + + atomic_set(&dev->total_open, 0); + atomic_set(&dev->total_close, 0); + atomic_set(&dev->total_ioctl, 0); + atomic_set(&dev->total_irq, 0); + atomic_set(&dev->total_ctx, 0); + atomic_set(&dev->total_locks, 0); + atomic_set(&dev->total_unlocks, 0); + atomic_set(&dev->total_contends, 0); + atomic_set(&dev->total_sleeps, 0); + + for (i = 0; i < DRM_HASH_SIZE; i++) { + dev->magiclist[i].head = NULL; + dev->magiclist[i].tail = NULL; + } + dev->maplist = NULL; + dev->map_count = 0; + dev->vmalist = NULL; + dev->lock.hw_lock = NULL; + dev->lock.lock_queue = 0; + dev->queue_count = 0; + dev->queue_reserved = 0; + dev->queue_slots = 0; + dev->queuelist = NULL; + dev->irq = 0; + dev->context_flag = 0; + dev->interrupt_flag = 0; + dev->dma_flag = 0; + dev->last_context = 0; + dev->last_switch = 0; + dev->last_checked = 0; + callout_init(&dev->timer); + dev->context_wait = 0; +#if DRM_DMA_HISTO + memset(&dev->histo, 0, sizeof(dev->histo)); +#endif + timespecclear(&dev->ctx_start); + timespecclear(&dev->lck_start); + + dev->buf_rp = dev->buf; + dev->buf_wp = dev->buf; + dev->buf_end = dev->buf + DRM_BSZ; + dev->buf_sigio = NULL; + + DRM_DEBUG("\n"); + + /* The kernel's context could be created here, but is now created + in drm_dma_enqueue. This is more resource-efficient for + hardware that does not do DMA, but may mean that + drm_select_queue fails between the time the interrupt is + initialized and the time the queues are initialized. */ + + return 0; +} + + +static int +gamma_takedown(drm_device_t *dev) +{ + int i; + drm_magic_entry_t *pt, *next; + drm_map_t *map; + drm_vma_entry_t *vma, *vma_next; + + DRM_DEBUG("\n"); + + if (dev->irq) gamma_irq_uninstall(dev); + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + callout_stop(&dev->timer); + + if (dev->devname) { + drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); + dev->devname = NULL; + } + + if (dev->unique) { + drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); + dev->unique = NULL; + dev->unique_len = 0; + } + /* Clear pid list */ + for (i = 0; i < DRM_HASH_SIZE; i++) { + for (pt = dev->magiclist[i].head; pt; pt = next) { + next = pt->next; + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + } + dev->magiclist[i].head = dev->magiclist[i].tail = NULL; + } + + /* Clear vma list (only built for debugging) */ + if (dev->vmalist) { + for (vma = dev->vmalist; vma; vma = vma_next) { + vma_next = vma->next; + drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); + } + dev->vmalist = NULL; + } + + /* Clear map area and mtrr information */ + if (dev->maplist) { + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#ifdef CONFIG_MTRR + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } +#endif + drm_ioremapfree(map->handle, map->size); + break; + case _DRM_SHM: + drm_free_pages((unsigned long)map->handle, + drm_order(map->size) + - PAGE_SHIFT, + DRM_MEM_SAREA); + break; + } + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + drm_free(dev->maplist, + dev->map_count * sizeof(*dev->maplist), + DRM_MEM_MAPS); + dev->maplist = NULL; + dev->map_count = 0; + } + + if (dev->queuelist) { + for (i = 0; i < dev->queue_count; i++) { + drm_waitlist_destroy(&dev->queuelist[i]->waitlist); + if (dev->queuelist[i]) { + drm_free(dev->queuelist[i], + sizeof(*dev->queuelist[0]), + DRM_MEM_QUEUES); + dev->queuelist[i] = NULL; + } + } + drm_free(dev->queuelist, + dev->queue_slots * sizeof(*dev->queuelist), + DRM_MEM_QUEUES); + dev->queuelist = NULL; + } + + drm_dma_takedown(dev); + + dev->queue_count = 0; + if (dev->lock.hw_lock) { + dev->lock.hw_lock = NULL; /* SHM removed */ + dev->lock.pid = 0; + wakeup(&dev->lock.lock_queue); + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + device_unbusy(dev->device); + + return 0; +} + +/* gamma_init is called via gamma_attach at module load time */ + +static int +gamma_init(device_t nbdev) +{ + drm_device_t *dev = device_get_softc(nbdev); + + DRM_DEBUG("\n"); + + memset((void *)dev, 0, sizeof(*dev)); + simple_lock_init(&dev->count_lock); + lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0); + +#if 0 /* XXX use getenv I guess */ + drm_parse_options(gamma); +#endif + +#if 0 + if ((retcode = misc_register(&gamma_misc))) { + DRM_ERROR("Cannot register \"%s\"\n", GAMMA_NAME); + return retcode; + } +#endif + dev->device = nbdev; + dev->devnode = make_dev(&gamma_cdevsw, + device_get_unit(nbdev), + DRM_DEV_UID, + DRM_DEV_GID, + DRM_DEV_MODE, + GAMMA_NAME); + dev->name = GAMMA_NAME; + + drm_mem_init(); + drm_sysctl_init(dev); + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + GAMMA_NAME, + GAMMA_MAJOR, + GAMMA_MINOR, + GAMMA_PATCHLEVEL, + GAMMA_DATE, + device_get_unit(nbdev)); + + return 0; +} + +/* gamma_cleanup is called via gamma_detach at module unload time. */ + +static void +gamma_cleanup(device_t nbdev) +{ + drm_device_t *dev = device_get_softc(nbdev); + + DRM_DEBUG("\n"); + + drm_sysctl_cleanup(dev); +#if 0 + if (misc_deregister(&gamma_misc)) { + DRM_ERROR("Cannot unload module\n"); + } else { + DRM_INFO("Module unloaded\n"); + } +#endif + device_busy(dev->device); + gamma_takedown(dev); +} + +SYSUNINIT(gamma_cleanup, SI_SUB_DRIVERS, SI_ORDER_ANY, gamma_cleanup, 0); + +#if 0 +int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_version_t version; + int len; + + copy_from_user_ret(&version, + (drm_version_t *)arg, + sizeof(version), + -EFAULT); + +#define DRM_COPY(name,value) \ + len = strlen(value); \ + if (len > name##_len) len = name##_len; \ + name##_len = strlen(value); \ + if (len && name) { \ + copy_to_user_ret(name, value, len, -EFAULT); \ + } + + version.version_major = GAMMA_MAJOR; + version.version_minor = GAMMA_MINOR; + version.version_patchlevel = GAMMA_PATCHLEVEL; + + DRM_COPY(version.name, GAMMA_NAME); + DRM_COPY(version.date, GAMMA_DATE); + DRM_COPY(version.desc, GAMMA_DESC); + + copy_to_user_ret((drm_version_t *)arg, + &version, + sizeof(version), + -EFAULT); + return 0; +} +#endif + +int +gamma_open(dev_t kdev, int flags, int fmt, struct proc *p) +{ + drm_device_t *dev = GAMMA_SOFTC(minor(kdev)); + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + + device_busy(dev->device); + if (!(retcode = drm_open_helper(kdev, flags, fmt, p, dev))) { + atomic_inc(&dev->total_open); + simple_lock(&dev->count_lock); + if (!dev->open_count++) { + simple_unlock(&dev->count_lock); + retcode = gamma_setup(dev); + } + simple_unlock(&dev->count_lock); + } + device_unbusy(dev->device); + + return retcode; +} + +int +gamma_close(dev_t kdev, int flags, int fmt, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_close(kdev, flags, fmt, p))) { + atomic_inc(&dev->total_close); + simple_lock(&dev->count_lock); + if (!--dev->open_count) { + if (atomic_read(&dev->ioctl_count) || dev->blocked) { + DRM_ERROR("Device busy: %d %d\n", + atomic_read(&dev->ioctl_count), + dev->blocked); + simple_unlock(&dev->count_lock); + return EBUSY; + } + simple_unlock(&dev->count_lock); + return gamma_takedown(dev); + } + simple_unlock(&dev->count_lock); + } + return retcode; +} + +/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */ + +int +gamma_ioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + int nr = DRM_IOCTL_NR(cmd); + drm_device_t *dev = kdev->si_drv1; + drm_file_t *priv; + int retcode = 0; + drm_ioctl_desc_t *ioctl; + d_ioctl_t *func; + + priv = drm_find_file_by_proc(dev, p); + if (!priv) { + DRM_DEBUG("can't find authenticator\n"); + return EINVAL; + } + + atomic_inc(&dev->ioctl_count); + atomic_inc(&dev->total_ioctl); + ++priv->ioctl_count; + + DRM_DEBUG("pid = %d, cmd = 0x%02lx, nr = 0x%02x, auth = %d\n", + p->p_pid, cmd, nr, priv->authenticated); + + switch (cmd) { + case FIOSETOWN: + return fsetown(*(int *)data, &dev->buf_sigio); + + case FIOGETOWN: + *(int *) data = fgetown(dev->buf_sigio); + return 0; + } + + if (nr >= GAMMA_IOCTL_COUNT) { + retcode = EINVAL; + } else { + ioctl = &gamma_ioctls[nr]; + func = ioctl->func; + + if (!func) { + DRM_DEBUG("no function\n"); + retcode = EINVAL; + } else if ((ioctl->root_only && suser(p)) + || (ioctl->auth_needed && !priv->authenticated)) { + retcode = EACCES; + } else { + retcode = (func)(kdev, cmd, data, flags, p); + } + } + + atomic_dec(&dev->ioctl_count); + return retcode; +} + +int gamma_unlock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_lock_t *lockp = (drm_lock_t *) data; + + if (lockp->context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + p->p_pid, lockp->context); + return -EINVAL; + } + + DRM_DEBUG("%d frees lock (%d holds)\n", + lockp->context, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + atomic_inc(&dev->total_unlocks); + if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) + atomic_inc(&dev->total_contends); + drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); + gamma_dma_schedule(dev, 1); + if (!dev->context_flag) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("\n"); + } + } + +#if DRM_DMA_HISTOGRAM + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &dev->lck_start); + atomic_inc(&dev->histo.lhld[drm_histogram_slot(&ts)]); + } +#endif + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_drv.h new file mode 100644 index 000000000..e48882207 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/gamma/gamma_drv.h @@ -0,0 +1,50 @@ +/* gamma_drv.h -- Private header for 3dlabs GMX 2000 driver -*- c -*- + * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com + * Revised: Fri Aug 20 09:24:27 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.h,v 1.4 1999/08/30 13:05:00 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.h,v 1.1 1999/09/25 14:38:00 dawes Exp $ + * + */ + +#ifndef _GAMMA_DRV_H_ +#define _GAMMA_DRV_H_ + + /* gamma_drv.c */ +extern d_open_t gamma_open; +extern d_close_t gamma_close; +extern d_ioctl_t gamma_ioctl; +extern d_ioctl_t gamma_version; +extern d_ioctl_t gamma_dma; +extern d_ioctl_t gamma_lock; +extern d_ioctl_t gamma_unlock; +extern d_ioctl_t gamma_control; + + /* gamma_dma.c */ +extern int gamma_dma_schedule(drm_device_t *dev, int locked); +extern int gamma_irq_install(drm_device_t *dev, int irq); +extern int gamma_irq_uninstall(drm_device_t *dev); + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h new file mode 100644 index 000000000..4c8e09f6a --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/i810_drm.h @@ -0,0 +1,188 @@ +#ifndef _I810_DRM_H_ +#define _I810_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _I810_DEFINES_ +#define _I810_DEFINES_ + +#define I810_DMA_BUF_ORDER 12 +#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER) +#define I810_DMA_BUF_NR 256 +#define I810_NR_SAREA_CLIPRECTS 8 + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define I810_NR_TEX_REGIONS 64 +#define I810_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define I810_UPLOAD_CTX 0x4 +#define I810_UPLOAD_BUFFERS 0x8 +#define I810_UPLOAD_TEX0 0x10 +#define I810_UPLOAD_TEX1 0x20 +#define I810_UPLOAD_CLIPRECTS 0x40 + + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +/* Destbuffer state + * - backbuffer linear offset and pitch -- invarient in the current dri + * - zbuffer linear offset and pitch -- also invarient + * - drawing origin in back and depth buffers. + * + * Keep the depth/back buffer state here to acommodate private buffers + * in the future. + */ +#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */ +#define I810_DESTREG_DI1 1 +#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */ +#define I810_DESTREG_DV1 3 +#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */ +#define I810_DESTREG_DR1 5 +#define I810_DESTREG_DR2 6 +#define I810_DESTREG_DR3 7 +#define I810_DESTREG_DR4 8 +#define I810_DEST_SETUP_SIZE 10 + +/* Context state + */ +#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */ +#define I810_CTXREG_CF1 1 +#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */ +#define I810_CTXREG_ST1 3 +#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */ +#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */ +#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */ +#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */ +#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */ +#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */ +#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */ +#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */ +#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */ +#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */ +#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */ +#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */ +#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */ +#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */ +#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */ +#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */ +#define I810_CTX_SETUP_SIZE 20 + +/* Texture state (per tex unit) + */ +#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */ +#define I810_TEXREG_MI1 1 +#define I810_TEXREG_MI2 2 +#define I810_TEXREG_MI3 3 +#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */ +#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */ +#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */ +#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */ +#define I810_TEX_SETUP_SIZE 8 + +#define I810_FRONT 0x1 +#define I810_BACK 0x2 +#define I810_DEPTH 0x4 + + +typedef struct _drm_i810_init { + enum { + I810_INIT_DMA = 0x01, + I810_CLEANUP_DMA = 0x02 + } func; + int ring_map_idx; + int buffer_map_idx; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; +} drm_i810_init_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_i810_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char in_use; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_i810_tex_region_t; + +typedef struct _drm_i810_sarea { + unsigned int ContextState[I810_CTX_SETUP_SIZE]; + unsigned int BufferState[I810_DEST_SETUP_SIZE]; + unsigned int TexState[2][I810_TEX_SETUP_SIZE]; + unsigned int dirty; + + unsigned int nbox; + drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS]; + + /* Maintain an LRU of contiguous regions of texture space. If + * you think you own a region of texture memory, and it has an + * age different to the one you set, then you are mistaken and + * it has been stolen by another client. If global texAge + * hasn't changed, there is no need to walk the list. + * + * These regions can be used as a proxy for the fine-grained + * texture information of other clients - by maintaining them + * in the same lru which is used to age their own textures, + * clients have an approximate lru for the whole of global + * texture space, and can make informed decisions as to which + * areas to kick out. There is no need to choose whether to + * kick out your own texture or someone else's - simply eject + * them all in LRU order. + */ + + drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1]; + /* Last elt is sentinal */ + int texAge; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int last_quiescent; /* */ + int ctxOwner; /* last context to upload state */ + + int vertex_prim; + +} drm_i810_sarea_t; + +typedef struct _drm_i810_clear { + int clear_color; + int clear_depth; + int flags; +} drm_i810_clear_t; + + + +/* These may be placeholders if we have more cliprects than + * I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to + * false, indicating that the buffer will be dispatched again with a + * new set of cliprects. + */ +typedef struct _drm_i810_vertex { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + int discard; /* client is finished with the buffer? */ +} drm_i810_vertex_t; + +typedef struct drm_i810_dma { + void *virtual; + int request_idx; + int request_size; + int granted; +} drm_i810_dma_t; + +#endif /* _I810_DRM_H_ */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/mga_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/mga_drm.h new file mode 100644 index 000000000..8bfa2b974 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/mga_drm.h @@ -0,0 +1,269 @@ +/* mga_drm.h -- Public header for the Matrox g200/g400 driver + * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Jeff Hartmann <jhartmann@precisioninsight.com> + * Keith Whitwell <keithw@precisioninsight.com> + * + * $XFree86$ + */ + +#ifndef _MGA_DRM_H_ +#define _MGA_DRM_H_ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmMga.h) + */ +#ifndef _MGA_DEFINES_ +#define _MGA_DEFINES_ + +#define MGA_F 0x1 /* fog */ +#define MGA_A 0x2 /* alpha */ +#define MGA_S 0x4 /* specular */ +#define MGA_T2 0x8 /* multitexture */ + +#define MGA_WARP_TGZ 0 +#define MGA_WARP_TGZF (MGA_F) +#define MGA_WARP_TGZA (MGA_A) +#define MGA_WARP_TGZAF (MGA_F|MGA_A) +#define MGA_WARP_TGZS (MGA_S) +#define MGA_WARP_TGZSF (MGA_S|MGA_F) +#define MGA_WARP_TGZSA (MGA_S|MGA_A) +#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) +#define MGA_WARP_T2GZ (MGA_T2) +#define MGA_WARP_T2GZF (MGA_T2|MGA_F) +#define MGA_WARP_T2GZA (MGA_T2|MGA_A) +#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) +#define MGA_WARP_T2GZS (MGA_T2|MGA_S) +#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) +#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) +#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) + +#define MGA_MAX_G400_PIPES 16 +#define MGA_MAX_G200_PIPES 8 /* no multitex */ +#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES + +#define MGA_CARD_TYPE_G200 1 +#define MGA_CARD_TYPE_G400 2 + +#define MGA_FRONT 0x1 +#define MGA_BACK 0x2 +#define MGA_DEPTH 0x4 + +/* 3d state excluding texture units: + */ +#define MGA_CTXREG_DSTORG 0 /* validated */ +#define MGA_CTXREG_MACCESS 1 +#define MGA_CTXREG_PLNWT 2 +#define MGA_CTXREG_DWGCTL 3 +#define MGA_CTXREG_ALPHACTRL 4 +#define MGA_CTXREG_FOGCOLOR 5 +#define MGA_CTXREG_WFLAG 6 +#define MGA_CTXREG_TDUAL0 7 +#define MGA_CTXREG_TDUAL1 8 +#define MGA_CTXREG_FCOL 9 +#define MGA_CTX_SETUP_SIZE 10 + +/* 2d state + */ +#define MGA_2DREG_PITCH 0 +#define MGA_2D_SETUP_SIZE 1 + +/* Each texture unit has a state: + */ +#define MGA_TEXREG_CTL 0 +#define MGA_TEXREG_CTL2 1 +#define MGA_TEXREG_FILTER 2 +#define MGA_TEXREG_BORDERCOL 3 +#define MGA_TEXREG_ORG 4 /* validated */ +#define MGA_TEXREG_ORG1 5 +#define MGA_TEXREG_ORG2 6 +#define MGA_TEXREG_ORG3 7 +#define MGA_TEXREG_ORG4 8 +#define MGA_TEXREG_WIDTH 9 +#define MGA_TEXREG_HEIGHT 10 +#define MGA_TEX_SETUP_SIZE 11 + +/* What needs to be changed for the current vertex dma buffer? + */ +#define MGA_UPLOAD_CTX 0x1 +#define MGA_UPLOAD_TEX0 0x2 +#define MGA_UPLOAD_TEX1 0x4 +#define MGA_UPLOAD_PIPE 0x8 +#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ +#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ +#define MGA_UPLOAD_2D 0x40 +#define MGA_WAIT_AGE 0x80 /* handled client-side */ +#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ +#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock + quiescent */ + +/* 32 buffers of 64k each, total 2 meg. + */ +#define MGA_DMA_BUF_ORDER 16 +#define MGA_DMA_BUF_SZ (1<<MGA_DMA_BUF_ORDER) +#define MGA_DMA_BUF_NR 31 + +/* Keep these small for testing. + */ +#define MGA_NR_SAREA_CLIPRECTS 8 + +/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define MGA_CARD_HEAP 0 +#define MGA_AGP_HEAP 1 +#define MGA_NR_TEX_HEAPS 2 +#define MGA_NR_TEX_REGIONS 16 +#define MGA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +typedef struct _drm_mga_warp_index { + int installed; + unsigned long phys_addr; + int size; +} drm_mga_warp_index_t; + +typedef struct drm_mga_init { + enum { + MGA_INIT_DMA = 0x01, + MGA_CLEANUP_DMA = 0x02 + } func; + int reserved_map_agpstart; + int reserved_map_idx; + int buffer_map_idx; + int sarea_priv_offset; + int primary_size; + int warp_ucode_size; + unsigned int frontOffset; + unsigned int backOffset; + unsigned int depthOffset; + unsigned int textureOffset; + unsigned int textureSize; + unsigned int agpTextureOffset; + unsigned int agpTextureSize; + unsigned int cpp; + unsigned int stride; + int sgram; + int chipset; + drm_mga_warp_index_t WarpIndex[MGA_MAX_WARP_PIPES]; + unsigned int mAccess; +} drm_mga_init_t; + +/* Warning: if you change the sarea structure, you must change the Xserver + * structures as well */ + +typedef struct _drm_mga_tex_region { + unsigned char next, prev; + unsigned char in_use; + unsigned int age; +} drm_mga_tex_region_t; + +typedef struct _drm_mga_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + unsigned int ContextState[MGA_CTX_SETUP_SIZE]; + unsigned int ServerState[MGA_2D_SETUP_SIZE]; + unsigned int TexState[2][MGA_TEX_SETUP_SIZE]; + unsigned int WarpPipe; + unsigned int dirty; + + unsigned int nbox; + drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS]; + + + /* Information about the most recently used 3d drawable. The + * client fills in the req_* fields, the server fills in the + * exported_ fields and puts the cliprects into boxes, above. + * + * The client clears the exported_drawable field before + * clobbering the boxes data. + */ + unsigned int req_drawable; /* the X drawable id */ + unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ + + unsigned int exported_drawable; + unsigned int exported_index; + unsigned int exported_stamp; + unsigned int exported_buffers; + unsigned int exported_nfront; + unsigned int exported_nback; + int exported_back_x, exported_front_x, exported_w; + int exported_back_y, exported_front_y, exported_h; + drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS]; + + /* Counters for aging textures and for client-side throttling. + */ + unsigned int last_enqueue; /* last time a buffer was enqueued */ + unsigned int last_dispatch; /* age of the most recently dispatched buffer */ + unsigned int last_quiescent; /* */ + + + /* LRU lists for texture memory in agp space and on the card + */ + drm_mga_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1]; + unsigned int texAge[MGA_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; +} drm_mga_sarea_t; + +/* Device specific ioctls: + */ +typedef struct _drm_mga_clear { + unsigned int clear_color; + unsigned int clear_depth; + unsigned int flags; +} drm_mga_clear_t; + +typedef struct _drm_mga_swap { + int dummy; +} drm_mga_swap_t; + +typedef struct _drm_mga_iload { + int idx; + int length; + unsigned int destOrg; +} drm_mga_iload_t; + +typedef struct _drm_mga_vertex { + int idx; /* buffer to queue */ + int used; /* bytes in use */ + int discard; /* client finished with buffer? */ +} drm_mga_vertex_t; + +typedef struct _drm_mga_indices { + int idx; /* buffer to queue */ + unsigned int start; + unsigned int end; + int discard; /* client finished with buffer? */ +} drm_mga_indices_t; + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/r128_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/r128_drm.h new file mode 100644 index 000000000..0379a5fae --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/r128_drm.h @@ -0,0 +1,111 @@ +/* r128_drm.h -- Public header for the r128 driver + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + */ + +#ifndef _R128_DRM_H_ +#define _R128_DRM_H_ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmR128.h) + */ +typedef struct drm_r128_init { + enum { + R128_INIT_CCE = 0x01, + R128_CLEANUP_CCE = 0x02 + } func; + int sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_fifo_size; + int cce_secure; + int ring_size; + int usec_timeout; + + int fb_offset; + int agp_ring_offset; + int agp_read_ptr_offset; + int agp_vertbufs_offset; + int agp_indbufs_offset; + int agp_textures_offset; + int mmio_offset; +} drm_r128_init_t; + +typedef struct drm_r128_packet { + unsigned long *buffer; + int count; + int flags; +} drm_r128_packet_t; + +typedef enum drm_r128_prim { + _DRM_R128_PRIM_NONE = 0x0001, + _DRM_R128_PRIM_POINT = 0x0002, + _DRM_R128_PRIM_LINE = 0x0004, + _DRM_R128_PRIM_POLY_LINE = 0x0008, + _DRM_R128_PRIM_TRI_LIST = 0x0010, + _DRM_R128_PRIM_TRI_FAN = 0x0020, + _DRM_R128_PRIM_TRI_STRIP = 0x0040, + _DRM_R128_PRIM_TRI_TYPE2 = 0x0080 +} drm_r128_prim_t; + +typedef struct drm_r128_vertex { + /* Indices here refer to the offset into + buflist in drm_buf_get_t. */ + int send_count; /* Number of buffers to send */ + int *send_indices; /* List of handles to buffers */ + int *send_sizes; /* Lengths of data to send */ + drm_r128_prim_t prim; /* Primitive type */ + int request_count; /* Number of buffers requested */ + int *request_indices; /* Buffer information */ + int *request_sizes; + int granted_count; /* Number of buffers granted */ +} drm_r128_vertex_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (r128_sarea.h) + */ +#define R128_LOCAL_TEX_HEAP 0 +#define R128_AGP_TEX_HEAP 1 +#define R128_NR_TEX_HEAPS 2 +#define R128_NR_TEX_REGIONS 64 +#define R128_LOG_TEX_GRANULARITY 16 + +typedef struct drm_tex_region { + unsigned char next, prev; + unsigned char in_use; + int age; +} drm_tex_region_t; + +typedef struct drm_r128_sarea { + drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; + int tex_age[R128_NR_TEX_HEAPS]; + int ctx_owner; + int ring_write; +} drm_r128_sarea_t; + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/Makefile b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/Makefile new file mode 100644 index 000000000..e0ff8ffa4 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +KMOD = tdfx +SRCS = tdfx_drv.c tdfx_context.c +SRCS += device_if.h bus_if.h pci_if.h +CFLAGS += ${DEBUG_FLAGS} -I.. +KERN = /usr/src/sys + +@: + ln -sf /sys @ + +machine: + ln -sf /sys/i386/include machine + +.include "/usr/src/sys/conf/kmod.mk" diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_context.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_context.c new file mode 100644 index 000000000..0aecf762a --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_context.c @@ -0,0 +1,201 @@ +/* tdfx_context.c -- IOCTLs for tdfx contexts -*- c -*- + * Created: Thu Oct 7 10:50:22 1999 by faith@precisioninsight.com + * Revised: Sat Oct 9 23:39:56 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI$ + * $XFree86$ + * + */ + +#include "drmP.h" +#include "tdfx_drv.h" + +extern drm_ctx_t tdfx_res_ctx; + +static int tdfx_alloc_queue(drm_device_t *dev) +{ + static int context = 0; + + return ++context; /* Should this reuse contexts in the future? */ +} + +int tdfx_context_switch(drm_device_t *dev, int old, int new) +{ + char buf[64]; + + atomic_inc(&dev->total_ctx); + + if (test_and_set_bit(0, &dev->context_flag)) { + DRM_ERROR("Reentering -- FIXME\n"); + return -EBUSY; + } + +#if DRM_DMA_HISTOGRAM + getnanotime(&dev->ctx_start); +#endif + + DRM_DEBUG("Context switch from %d to %d\n", old, new); + + if (new == dev->last_context) { + clear_bit(0, &dev->context_flag); + return 0; + } + + if (drm_flags & DRM_FLAG_NOCTX) { + tdfx_context_switch_complete(dev, new); + } else { + sprintf(buf, "C %d %d\n", old, new); + drm_write_string(dev, buf); + } + + return 0; +} + +int tdfx_context_switch_complete(drm_device_t *dev, int new) +{ + dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ + dev->last_switch = ticks; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("Lock isn't held after context switch\n"); + } + + /* If a context switch is ever initiated + when the kernel holds the lock, release + that lock here. */ +#if DRM_DMA_HISTOGRAM + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &dev->lck_start); + atomic_inc(&dev->histo.ctx[drm_histogram_slot(&ts)]); + } +#endif + clear_bit(0, &dev->context_flag); + wakeup(&dev->context_wait); + + return 0; +} + + +int +tdfx_resctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_ctx_res_t res; + drm_ctx_t ctx; + int i, error; + + DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); + res = *(drm_ctx_res_t *) data; + if (res.count >= DRM_RESERVED_CONTEXTS) { + memset(&ctx, 0, sizeof(ctx)); + for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { + ctx.handle = i; + error = copyout(&i, &res.contexts[i], sizeof(i)); + if (error) return error; + } + } + res.count = DRM_RESERVED_CONTEXTS; + *(drm_ctx_res_t *) data = res; + return 0; +} + + +int +tdfx_addctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + if ((ctx.handle = tdfx_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { + /* Skip kernel's context and get a new one. */ + ctx.handle = tdfx_alloc_queue(dev); + } + DRM_DEBUG("%d\n", ctx.handle); + *(drm_ctx_t *) data = ctx; + return 0; +} + +int +tdfx_modctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + if (ctx.flags==_DRM_CONTEXT_PRESERVED) + tdfx_res_ctx.handle=ctx.handle; + return 0; +} + +int +tdfx_getctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + /* This is 0, because we don't hanlde any context flags */ + ctx.flags = 0; + *(drm_ctx_t *) data = ctx; + return 0; +} + +int +tdfx_switchctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + DRM_DEBUG("%d\n", ctx.handle); + return tdfx_context_switch(dev, dev->last_context, ctx.handle); +} + +int +tdfx_newctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + DRM_DEBUG("%d\n", ctx.handle); + tdfx_context_switch_complete(dev, ctx.handle); + + return 0; +} + +int +tdfx_rmctx(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_ctx_t ctx; + + ctx = *(drm_ctx_t *) data; + DRM_DEBUG("%d\n", ctx.handle); + /* This is currently a noop because we + don't reuse context values. Perhaps we + should? */ + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_drv.c new file mode 100644 index 000000000..573cfcf14 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_drv.c @@ -0,0 +1,694 @@ +/* tdfx.c -- tdfx driver -*- c -*- + * Created: Thu Oct 7 10:38:32 1999 by faith@precisioninsight.com + * Revised: Tue Oct 12 08:51:35 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI$ + * $XFree86$ + * + */ + +#include "drmP.h" +#include "tdfx_drv.h" + +#include <pci/pcivar.h> + +MODULE_DEPEND(tdfx, drm, 1, 1, 1); + +#define TDFX_NAME "tdfx" +#define TDFX_DESC "tdfx" +#define TDFX_DATE "19991009" +#define TDFX_MAJOR 0 +#define TDFX_MINOR 0 +#define TDFX_PATCHLEVEL 1 + +static int tdfx_init(device_t nbdev); +static void tdfx_cleanup(device_t nbdev); + +drm_ctx_t tdfx_res_ctx; + +static int tdfx_probe(device_t dev) +{ + const char *s = 0; + + switch (pci_get_devid(dev)) { + case 0x0003121a: + s = "3Dfx Voodoo Banshee graphics accelerator"; + break; + + case 0x0005121a: + s = "3Dfx Voodoo 3 graphics accelerator"; + break; + } + + if (s) { + device_set_desc(dev, s); + return 0; + } + + return ENXIO; +} + +static int tdfx_attach(device_t dev) +{ + tdfx_init(dev); + return 0; +} + +static int tdfx_detach(device_t dev) +{ + tdfx_cleanup(dev); + return 0; +} + +static device_method_t tdfx_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, tdfx_probe), + DEVMETHOD(device_attach, tdfx_attach), + DEVMETHOD(device_detach, tdfx_detach), + + { 0, 0 } +}; + +static driver_t tdfx_driver = { + "drm", + tdfx_methods, + sizeof(drm_device_t), +}; + +static devclass_t tdfx_devclass; +#define TDFX_SOFTC(unit) \ + ((drm_device_t *) devclass_get_softc(tdfx_devclass, unit)) + +DRIVER_MODULE(if_tdfx, pci, tdfx_driver, tdfx_devclass, 0, 0); + +#define CDEV_MAJOR 145 + /* tdfx_drv.c */ +static d_open_t tdfx_open; +static d_close_t tdfx_close; +static d_ioctl_t tdfx_version; +static d_ioctl_t tdfx_ioctl; +static d_ioctl_t tdfx_lock; +static d_ioctl_t tdfx_unlock; + +static struct cdevsw tdfx_cdevsw = { + /* open */ tdfx_open, + /* close */ tdfx_close, + /* read */ drm_read, + /* write */ drm_write, + /* ioctl */ tdfx_ioctl, + /* poll */ drm_poll, + /* mmap */ drm_mmap, + /* strategy */ nostrategy, + /* name */ "tdfx", + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ D_TTY | D_TRACKCLOSE, + /* bmaj */ -1 +}; + +static drm_ioctl_desc_t tdfx_ioctls[] = { + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { tdfx_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { tdfx_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { tdfx_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { tdfx_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { tdfx_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { tdfx_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { tdfx_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { tdfx_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { tdfx_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { tdfx_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, +}; +#define TDFX_IOCTL_COUNT DRM_ARRAY_SIZE(tdfx_ioctls) + +static int +tdfx_setup(drm_device_t *dev) +{ + int i; + + device_busy(dev->device); + + atomic_set(&dev->ioctl_count, 0); + atomic_set(&dev->vma_count, 0); + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + + atomic_set(&dev->total_open, 0); + atomic_set(&dev->total_close, 0); + atomic_set(&dev->total_ioctl, 0); + atomic_set(&dev->total_irq, 0); + atomic_set(&dev->total_ctx, 0); + atomic_set(&dev->total_locks, 0); + atomic_set(&dev->total_unlocks, 0); + atomic_set(&dev->total_contends, 0); + atomic_set(&dev->total_sleeps, 0); + + for (i = 0; i < DRM_HASH_SIZE; i++) { + dev->magiclist[i].head = NULL; + dev->magiclist[i].tail = NULL; + } + dev->maplist = NULL; + dev->map_count = 0; + dev->vmalist = NULL; + dev->lock.hw_lock = NULL; + dev->lock.lock_queue = 0; + dev->queue_count = 0; + dev->queue_reserved = 0; + dev->queue_slots = 0; + dev->queuelist = NULL; + dev->irq = 0; + dev->context_flag = 0; + dev->interrupt_flag = 0; + dev->dma = 0; + dev->dma_flag = 0; + dev->last_context = 0; + dev->last_switch = 0; + dev->last_checked = 0; + callout_init(&dev->timer); + dev->context_wait = 0; + + timespecclear(&dev->ctx_start); + timespecclear(&dev->lck_start); + + dev->buf_rp = dev->buf; + dev->buf_wp = dev->buf; + dev->buf_end = dev->buf + DRM_BSZ; + bzero(&dev->buf_sel, sizeof dev->buf_sel); + dev->buf_sigio = NULL; + dev->buf_readers = 0; + dev->buf_writers = 0; + dev->buf_selecting = 0; + + tdfx_res_ctx.handle=-1; + + DRM_DEBUG("\n"); + + /* The kernel's context could be created here, but is now created + in drm_dma_enqueue. This is more resource-efficient for + hardware that does not do DMA, but may mean that + drm_select_queue fails between the time the interrupt is + initialized and the time the queues are initialized. */ + + return 0; +} + + +static int +tdfx_takedown(drm_device_t *dev) +{ + int i; + drm_magic_entry_t *pt, *next; + drm_map_t *map; + drm_vma_entry_t *vma, *vma_next; + + DRM_DEBUG("\n"); + + lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); + callout_stop(&dev->timer); + + if (dev->devname) { + drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); + dev->devname = NULL; + } + + if (dev->unique) { + drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); + dev->unique = NULL; + dev->unique_len = 0; + } + /* Clear pid list */ + for (i = 0; i < DRM_HASH_SIZE; i++) { + for (pt = dev->magiclist[i].head; pt; pt = next) { + next = pt->next; + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + } + dev->magiclist[i].head = dev->magiclist[i].tail = NULL; + } + + /* Clear vma list (only built for debugging) */ + if (dev->vmalist) { + for (vma = dev->vmalist; vma; vma = vma_next) { + vma_next = vma->next; + drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); + } + dev->vmalist = NULL; + } + + /* Clear map area and mtrr information */ + if (dev->maplist) { + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#ifdef CONFIG_MTRR + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } +#endif + drm_ioremapfree(map->handle, map->size); + break; + case _DRM_SHM: + drm_free_pages((unsigned long)map->handle, + drm_order(map->size) + - PAGE_SHIFT, + DRM_MEM_SAREA); + break; + case _DRM_AGP: + break; /* XXX */ + } + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + drm_free(dev->maplist, + dev->map_count * sizeof(*dev->maplist), + DRM_MEM_MAPS); + dev->maplist = NULL; + dev->map_count = 0; + } + + if (dev->lock.hw_lock) { + dev->lock.hw_lock = NULL; /* SHM removed */ + dev->lock.pid = 0; + wakeup(&dev->lock.lock_queue); + } + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + + device_unbusy(dev->device); + + return 0; +} + +/* tdfx_init is called via tdfx_attach at module load time, */ + +static int +tdfx_init(device_t nbdev) +{ + drm_device_t *dev = device_get_softc(nbdev); + + DRM_DEBUG("\n"); + + memset((void *)dev, 0, sizeof(*dev)); + simple_lock_init(&dev->count_lock); + lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0); + +#if 0 + drm_parse_options(tdfx); +#endif + + dev->device = nbdev; + dev->devnode = make_dev(&tdfx_cdevsw, + device_get_unit(nbdev), + DRM_DEV_UID, + DRM_DEV_GID, + DRM_DEV_MODE, + TDFX_NAME); + dev->name = TDFX_NAME; + + drm_mem_init(); + drm_sysctl_init(dev); + TAILQ_INIT(&dev->files); + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + TDFX_NAME, + TDFX_MAJOR, + TDFX_MINOR, + TDFX_PATCHLEVEL, + TDFX_DATE, + device_get_unit(nbdev)); + + return 0; +} + +/* tdfx_cleanup is called via tdfx_detach at module unload time. */ + +static void +tdfx_cleanup(device_t nbdev) +{ + drm_device_t *dev = device_get_softc(nbdev); + + DRM_DEBUG("\n"); + + drm_sysctl_cleanup(dev); + destroy_dev(dev->devnode); + + DRM_INFO("Module unloaded\n"); + + device_busy(dev->device); + tdfx_takedown(dev); +} + +static int +tdfx_version(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_version_t version; + int len; + + version = *(drm_version_t *) data; + +#define DRM_COPY(name,value) \ + len = strlen(value); \ + if (len > name##_len) len = name##_len; \ + name##_len = strlen(value); \ + if (len && name) { \ + int error = copyout(value, name, len); \ + if (error) return error; \ + } + + version.version_major = TDFX_MAJOR; + version.version_minor = TDFX_MINOR; + version.version_patchlevel = TDFX_PATCHLEVEL; + + DRM_COPY(version.name, TDFX_NAME); + DRM_COPY(version.date, TDFX_DATE); + DRM_COPY(version.desc, TDFX_DESC); + + *(drm_version_t *) data = version; + return 0; +} + +static int +tdfx_open(dev_t kdev, int flags, int fmt, struct proc *p) +{ + drm_device_t *dev = TDFX_SOFTC(minor(kdev)); + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + + device_busy(dev->device); + if (!(retcode = drm_open_helper(kdev, flags, fmt, p, dev))) { + atomic_inc(&dev->total_open); + simple_lock(&dev->count_lock); + if (!dev->open_count++) { + simple_unlock(&dev->count_lock); + retcode = tdfx_setup(dev); + } + simple_unlock(&dev->count_lock); + } + device_unbusy(dev->device); + + return retcode; +} + +static int +tdfx_close(dev_t kdev, int flags, int fmt, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_close(kdev, flags, fmt, p))) { + atomic_inc(&dev->total_close); + simple_lock(&dev->count_lock); + if (!--dev->open_count) { + if (atomic_read(&dev->ioctl_count) || dev->blocked) { + DRM_ERROR("Device busy: %d %d\n", + atomic_read(&dev->ioctl_count), + dev->blocked); + simple_unlock(&dev->count_lock); + return EBUSY; + } + simple_unlock(&dev->count_lock); + return tdfx_takedown(dev); + } + simple_unlock(&dev->count_lock); + } + + return retcode; +} + +/* tdfx_ioctl is called whenever a process performs an ioctl on /dev/drm. */ + +static int +tdfx_ioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + int nr = DRM_IOCTL_NR(cmd); + drm_device_t *dev = kdev->si_drv1; + drm_file_t *priv; + int retcode = 0; + drm_ioctl_desc_t *ioctl; + d_ioctl_t *func; + + DRM_DEBUG("dev=%p\n", dev); + priv = drm_find_file_by_proc(dev, p); + if (!priv) { + DRM_DEBUG("can't find authenticator\n"); + return EINVAL; + } + + atomic_inc(&dev->ioctl_count); + atomic_inc(&dev->total_ioctl); + ++priv->ioctl_count; + + DRM_DEBUG("pid = %d, cmd = 0x%02lx, nr = 0x%02x, auth = %d\n", + p->p_pid, cmd, nr, priv->authenticated); + + switch (cmd) { + case FIONBIO: + atomic_dec(&dev->ioctl_count); + return 0; + + case FIOASYNC: + atomic_dec(&dev->ioctl_count); + dev->flags |= FASYNC; + return 0; + + case FIOSETOWN: + atomic_dec(&dev->ioctl_count); + return fsetown(*(int *)data, &dev->buf_sigio); + + case FIOGETOWN: + atomic_dec(&dev->ioctl_count); + *(int *) data = fgetown(dev->buf_sigio); + return 0; + } + + if (nr >= TDFX_IOCTL_COUNT) { + retcode = EINVAL; + } else { + ioctl = &tdfx_ioctls[nr]; + func = ioctl->func; + + if (!func) { + DRM_DEBUG("no function\n"); + retcode = EINVAL; + } else if ((ioctl->root_only && suser(p)) + || (ioctl->auth_needed && !priv->authenticated)) { + retcode = EACCES; + } else { + retcode = (func)(kdev, cmd, data, flags, p); + } + } + + atomic_dec(&dev->ioctl_count); + return retcode; +} + +static int +tdfx_lock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + int ret = 0; + drm_lock_t lock; +#if DRM_DMA_HISTOGRAM + + getnanotime(&dev->lck_start); +#endif + + lock = *(drm_lock_t *) data; + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + p->p_pid, lock.context); + return EINVAL; + } + + DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", + lock.context, p->p_pid, dev->lock.hw_lock->lock, + lock.flags); + +#if 0 + /* dev->queue_count == 0 right now for + tdfx. FIXME? */ + if (lock.context < 0 || lock.context >= dev->queue_count) + return EINVAL; +#endif + + if (!ret) { +#if 0 + if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) + != lock.context) { + long j = ticks - dev->lock.lock_time; + + if (lock.context == tdfx_res_ctx.handle && + j >= 0 && j < DRM_LOCK_SLICE) { + /* Can't take lock if we just had it and + there is contention. */ + DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d ticks=%d\n", + lock.context, p->p_pid, j, + dev->lock.lock_time, ticks); + ret = tsleep(&never, PZERO|PCATCH, "drmlk1", + DRM_LOCK_SLICE - j); + if (ret) + return ret; + DRM_DEBUG("ticks=%d\n", ticks); + } + } +#endif + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + ret = EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + lock.context)) { + dev->lock.pid = p->p_pid; + dev->lock.lock_time = ticks; + atomic_inc(&dev->total_locks); + break; /* Got lock */ + } + + /* Contention */ + atomic_inc(&dev->total_sleeps); + ret = tsleep(&dev->lock.lock_queue, + PZERO|PCATCH, + "drmlk2", + 0); + if (ret) + break; + } + } + +#if 0 + if (!ret && dev->last_context != lock.context && + lock.context != tdfx_res_ctx.handle && + dev->last_context != tdfx_res_ctx.handle) { + add_wait_queue(&dev->context_wait, &entry); + current->state = TASK_INTERRUPTIBLE; + /* PRE: dev->last_context != lock.context */ + tdfx_context_switch(dev, dev->last_context, lock.context); + /* POST: we will wait for the context + switch and will dispatch on a later call + when dev->last_context == lock.context + NOTE WE HOLD THE LOCK THROUGHOUT THIS + TIME! */ + current->policy |= SCHED_YIELD; + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&dev->context_wait, &entry); + if (signal_pending(current)) { + ret = EINTR; + } else if (dev->last_context != lock.context) { + DRM_ERROR("Context mismatch: %d %d\n", + dev->last_context, lock.context); + } + } +#endif + + if (!ret) { + if (lock.flags & _DRM_LOCK_READY) { + /* Wait for space in DMA/FIFO */ + } + if (lock.flags & _DRM_LOCK_QUIESCENT) { + /* Make hardware quiescent */ +#if 0 + tdfx_quiescent(dev); +#endif + } + } + +#if 0 + DRM_ERROR("pid = %5d, old counter = %5ld\n", + p->p_pid, current->counter); +#endif +#if 0 + while (current->counter > 25) + current->counter >>= 1; /* decrease time slice */ + DRM_ERROR("pid = %5d, new counter = %5ld\n", + p->p_pid, current->counter); +#endif + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); + +#if DRM_DMA_HISTOGRAM + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &dev->lck_start); + atomic_inc(&dev->histo.lhld[drm_histogram_slot(&ts)]); + } +#endif + + return ret; +} + + +static int +tdfx_unlock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + drm_device_t *dev = kdev->si_drv1; + drm_lock_t lock; + + lock = *(drm_lock_t *) data; + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + p->p_pid, lock.context); + return EINVAL; + } + + DRM_DEBUG("%d frees lock (%d holds)\n", + lock.context, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + atomic_inc(&dev->total_unlocks); + if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) + atomic_inc(&dev->total_contends); + drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); + /* FIXME: Try to send data to card here */ + if (!dev->context_flag) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("\n"); + } + } + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_drv.h new file mode 100644 index 000000000..213f8ef1e --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/tdfx/tdfx_drv.h @@ -0,0 +1,47 @@ +/* tdfx_drv.h -- Private header for tdfx driver -*- c -*- + * Created: Thu Oct 7 10:40:04 1999 by faith@precisioninsight.com + * Revised: Sat Oct 9 23:38:19 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI$ + * $XFree86$ + * + */ + +#ifndef _TDFX_DRV_H_ +#define _TDFX_DRV_H_ + + /* tdfx_context.c */ + +extern d_ioctl_t tdfx_resctx; +extern d_ioctl_t tdfx_addctx; +extern d_ioctl_t tdfx_modctx; +extern d_ioctl_t tdfx_getctx; +extern d_ioctl_t tdfx_switchctx; +extern d_ioctl_t tdfx_newctx; +extern d_ioctl_t tdfx_rmctx; + +extern int tdfx_context_switch(drm_device_t *dev, int old, int new); +extern int tdfx_context_switch_complete(drm_device_t *dev, int new); +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drm.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drm.c new file mode 100644 index 000000000..985c48f9d --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drm.c @@ -0,0 +1,1108 @@ +/* xf86drm.c -- User-level interface to DRM device + * Created: Tue Jan 5 08:16:21 1999 by faith@precisioninsight.com + * Revised: Wed Aug 4 07:54:23 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.43 1999/08/04 18:14:43 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.4 1999/09/25 14:37:49 dawes Exp $ + * + */ + +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# include "xf86Priv.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/stat.h> +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# include <sys/types.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void*), void*); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +int sysctlbyname(const char *, void *, size_t *, void *, size_t); + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include "xf86drm.h" +#include "drm.h" + +#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) /* create dev_t */ + +static int drmOpenByBusid(const char *busid); +static int drmOpenDevice(const char *path, long dev, + mode_t mode, uid_t user, gid_t group); + +static void *drmHashTable = NULL; /* Context switch callbacks */ + +typedef struct drmHashEntry { + int fd; + void (*f)(int, void *, void *); + void *tagTable; +} drmHashEntry; + +void *drmMalloc(int size) +{ + void *pt; + if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size); + return pt; +} + +void drmFree(void *pt) +{ + if (pt) _DRM_FREE(pt); +} + +static char *drmStrdup(const char *s) +{ + return s ? strdup(s) : NULL; +} + + +static unsigned long drmGetKeyFromFd(int fd) +{ +#ifdef XFree86LOADER + struct xf86stat st; +#else + struct stat st; +#endif + + st.st_rdev = 0; + fstat(fd, &st); + return st.st_rdev; +} + +static drmHashEntry *drmGetEntry(int fd) +{ + unsigned long key = drmGetKeyFromFd(fd); + void *value; + drmHashEntry *entry; + + if (!drmHashTable) drmHashTable = drmHashCreate(); + + if (drmHashLookup(drmHashTable, key, &value)) { + entry = drmMalloc(sizeof(*entry)); + entry->fd = fd; + entry->f = NULL; + entry->tagTable = drmHashCreate(); + drmHashInsert(drmHashTable, key, entry); + } else { + entry = value; + } + return entry; +} + +/* drm_open is used to open the /dev/drm device */ + +static int drm_open(const char *file) +{ + int fd = open(file, O_RDWR, 0); + + if (fd >= 0) return fd; + return -errno; +} + +/* drmAvailable looks for a usable device node in /dev/dri. */ + +int drmAvailable(void) +{ + int i, fd; + char dev_name[64]; + mode_t mode = DRM_DEV_MODE; + mode_t dirmode; + gid_t group = DRM_DEV_GID; + uid_t user = DRM_DEV_UID; + long dev = 0; + + if (!geteuid()) { + dirmode = mode; + if (dirmode & S_IRUSR) dirmode |= S_IXUSR; + if (dirmode & S_IRGRP) dirmode |= S_IXGRP; + if (dirmode & S_IROTH) dirmode |= S_IXOTH; + dirmode &= ~(S_IWGRP | S_IWOTH); + mkdir("/dev/dri", 0); + chown("/dev/dri", user, group); + chmod("/dev/dri", dirmode); + } + + for (i = 0; i < 8; i++) { + sprintf(dev_name, "/dev/dri/card%d", i); + dev = makedev(145, i); + fd = drmOpenDevice(dev_name, dev, mode, user, group); + if (fd < 0) { + remove(dev_name); + continue; + } + close(fd); + return 1; + } + return 0; +} + +static int drmOpenDevice(const char *path, long dev, + mode_t mode, uid_t user, gid_t group) +{ +#ifdef XFree86LOADER + struct xf86stat st; +#else + struct stat st; +#endif + + if (!stat(path, &st) && st.st_rdev == dev) return drm_open(path); + + if (geteuid()) return DRM_ERR_NOT_ROOT; + remove(path); + if (mknod(path, S_IFCHR, dev)) { + remove(path); + return DRM_ERR_NOT_ROOT; + } + chown(path, user, group); + chmod(path, mode); + return drm_open(path); +} + +static int drmOpenByName(const char *name) +{ + int i; + char dev_name[64]; + mode_t mode = DRM_DEV_MODE; + mode_t dirmode; + gid_t group = DRM_DEV_GID; + uid_t user = DRM_DEV_UID; + long dev = 0; + drmVersionPtr version; + int fd; + +#if defined(XFree86Server) + mode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; + group = xf86ConfigDRI.group ? xf86ConfigDRI.group : DRM_DEV_GID; +#endif + +#if defined(XFree86Server) + if (!drmAvailable()) { + /* try to load the kernel module now */ + if (!xf86LoadKernelModule(name)) { + ErrorF("[drm] failed to load kernel module \"%s\"\n", + name); + return -1; + } + } +#else + if (!drmAvailable()) + return -1; +#endif + + if (!geteuid()) { + dirmode = mode; + if (dirmode & S_IRUSR) dirmode |= S_IXUSR; + if (dirmode & S_IRGRP) dirmode |= S_IXGRP; + if (dirmode & S_IROTH) dirmode |= S_IXOTH; + dirmode &= ~(S_IWGRP | S_IWOTH); + mkdir("/dev/dri", 0); + chown("/dev/dri", user, group); + chmod("/dev/dri", dirmode); + } + + for (i = 0; i < 8; i++) { + sprintf(dev_name, "/dev/dri/card%d", i); + dev = makedev(145, i); + fd = drmOpenDevice(dev_name, dev, mode, user, group); + if (fd < 0) { + remove(dev_name); + continue; + } + version = drmGetVersion(fd); + if (!version) { + continue; + } + if (!strcmp(version->name, name)) { + drmFreeVersion(version); + return fd; + } + drmFreeVersion(version); + } + +#if 0 + for (i = 0; i < 8; i++) { + sprintf(sysctl_name, "hw.dri.%d.name", i); + sprintf(dev_name, "/dev/dri/card%d", i); + len = sizeof(buf); + if (sysctlbyname(sysctl_name, buf, &len, 0, 0) == 0) { + buf[len-1] = '\0'; + for (driver = pt = buf; *pt && *pt != ' '; ++pt) + ; + if (*pt) { /* Device is next */ + *pt = '\0'; + if (!strcmp(driver, name)) { /* Match */ + for (devstring = ++pt; *pt && *pt != ' '; ++pt) + ; + if (*pt) { /* Found busid */ + return drmOpenByBusid(++pt); + } else { /* No busid */ + dev = strtol(devstring, NULL, 0); + return drmOpenDevice(dev_name, dev, + mode, user, group); + } + } + } + } else remove(dev_name); + } +#endif + + return -1; +} + +static int drmOpenByBusid(const char *busid) +{ + int i; + char dev_name[64]; + char *buf; + int fd; + + for (i = 0; i < 8; i++) { + sprintf(dev_name, "/dev/dri/card%d", i); + if ((fd = drm_open(dev_name)) >= 0) { + buf = drmGetBusid(fd); + if (buf && !strcmp(buf, busid)) { + drmFreeBusid(buf); + return fd; + } + if (buf) drmFreeBusid(buf); + close(fd); + } + } + return -1; +} + + +/* drmOpen looks up the specified name and busid, and opens the device + found. The entry in /dev/dri is created if necessary (and if root). + A file descriptor is returned. On error, the return value is + negative. */ + +int drmOpen(const char *name, const char *busid) +{ + if (busid) return drmOpenByBusid(busid); + return drmOpenByName(name); +} + +void drmFreeVersion(drmVersionPtr v) +{ + if (!v) return; + if (v->name) drmFree(v->name); + if (v->date) drmFree(v->date); + if (v->desc) drmFree(v->desc); + drmFree(v); +} + +static void drmFreeKernelVersion(drm_version_t *v) +{ + if (!v) return; + if (v->name) drmFree(v->name); + if (v->date) drmFree(v->date); + if (v->desc) drmFree(v->desc); + drmFree(v); +} + +static void drmCopyVersion(drmVersionPtr d, drm_version_t *s) +{ + d->version_major = s->version_major; + d->version_minor = s->version_minor; + d->version_patchlevel = s->version_patchlevel; + d->name_len = s->name_len; + d->name = drmStrdup(s->name); + d->date_len = s->date_len; + d->date = drmStrdup(s->date); + d->desc_len = s->desc_len; + d->desc = drmStrdup(s->desc); +} + +/* drmVersion obtains the version information via an ioctl. Similar + * information is available via /proc/drm. */ + +drmVersionPtr drmGetVersion(int fd) +{ + drmVersionPtr retval; + drm_version_t *version = drmMalloc(sizeof(*version)); + + /* First, get the lengths */ + version->name_len = 0; + version->name = NULL; + version->date_len = 0; + version->date = NULL; + version->desc_len = 0; + version->desc = NULL; + + if (ioctl(fd, DRM_IOCTL_VERSION, version)) { + drmFreeKernelVersion(version); + return NULL; + } + + /* Now, allocate space and get the data */ + if (version->name_len) + version->name = drmMalloc(version->name_len + 1); + if (version->date_len) + version->date = drmMalloc(version->date_len + 1); + if (version->desc_len) + version->desc = drmMalloc(version->desc_len + 1); + + if (ioctl(fd, DRM_IOCTL_VERSION, version)) { + drmFreeKernelVersion(version); + return NULL; + } + + /* The results might not be null-terminated + strings, so terminate them. */ + + if (version->name_len) version->name[version->name_len] = '\0'; + if (version->date_len) version->date[version->date_len] = '\0'; + if (version->desc_len) version->desc[version->desc_len] = '\0'; + + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + drmCopyVersion(retval, version); + drmFreeKernelVersion(version); + return retval; +} + +void drmFreeBusid(const char *busid) +{ + drmFree((void *)busid); +} + +char *drmGetBusid(int fd) +{ + drm_unique_t u; + + u.unique_len = 0; + u.unique = NULL; + + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; + u.unique = drmMalloc(u.unique_len + 1); + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; + u.unique[u.unique_len] = '\0'; + return u.unique; +} + +int drmSetBusid(int fd, const char *busid) +{ + drm_unique_t u; + + u.unique = (char *)busid; + u.unique_len = strlen(busid); + + if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) return -errno; + return 0; +} + +int drmGetMagic(int fd, drmMagicPtr magic) +{ + drm_auth_t auth; + + *magic = 0; + if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno; + *magic = auth.magic; + return 0; +} + +int drmAuthMagic(int fd, drmMagic magic) +{ + drm_auth_t auth; + + auth.magic = magic; + if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno; + return 0; +} + +int drmAddMap(int fd, + drmHandle offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drmHandlePtr handle) +{ + drm_map_t map; + + map.offset = offset; + map.size = size; + map.handle = 0; + map.type = type; + map.flags = flags; + if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno; + if (handle) *handle = (drmHandle)map.handle; + return 0; +} + +int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, + int agp_offset) +{ + drm_buf_desc_t request; + + request.count = count; + request.size = size; + request.low_mark = 0; + request.high_mark = 0; + request.flags = flags; + request.agp_start = agp_offset; + + if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno; + return request.count; +} + +int drmMarkBufs(int fd, double low, double high) +{ + drm_buf_info_t info; + int i; + + info.count = 0; + info.list = NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL; + + if (!info.count) return -EINVAL; + + if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) + return -ENOMEM; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { + int retval = -errno; + drmFree(info.list); + return retval; + } + + for (i = 0; i < info.count; i++) { + info.list[i].low_mark = low * info.list[i].count; + info.list[i].high_mark = high * info.list[i].count; + if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { + int retval = -errno; + drmFree(info.list); + return retval; + } + } + drmFree(info.list); + + return 0; +} + +int drmFreeBufs(int fd, int count, int *list) +{ + drm_buf_free_t request; + + request.count = count; + request.list = list; + if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno; + return 0; +} + +int drmClose(int fd) +{ + unsigned long key = drmGetKeyFromFd(fd); + drmHashEntry *entry = drmGetEntry(fd); + + drmHashDestroy(entry->tagTable); + entry->fd = 0; + entry->f = NULL; + entry->tagTable = NULL; + + drmHashDelete(drmHashTable, key); + drmFree(entry); + + return close(fd); +} + +int drmMap(int fd, + drmHandle handle, + drmSize size, + drmAddressPtr address) +{ + if (fd < 0) return -EINVAL; + *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); + if (*address == MAP_FAILED) return -errno; + return 0; +} + +int drmUnmap(drmAddress address, drmSize size) +{ + return munmap(address, size); +} + +drmBufInfoPtr drmGetBufInfo(int fd) +{ + drm_buf_info_t info; + drmBufInfoPtr retval; + int i; + + info.count = 0; + info.list = NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL; + + if (info.count) { + if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) + return NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { + drmFree(info.list); + return NULL; + } + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + retval->count = info.count; + retval->list = drmMalloc(info.count * sizeof(*retval->list)); + for (i = 0; i < info.count; i++) { + retval->list[i].count = info.list[i].count; + retval->list[i].size = info.list[i].size; + retval->list[i].low_mark = info.list[i].low_mark; + retval->list[i].high_mark = info.list[i].high_mark; + } + drmFree(info.list); + return retval; + } + return NULL; +} + +drmBufMapPtr drmMapBufs(int fd) +{ + drm_buf_map_t bufs; + drmBufMapPtr retval; + int i; + + bufs.count = 0; + bufs.list = NULL; + if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL; + + if (bufs.count) { + if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) + return NULL; + + if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { + drmFree(bufs.list); + return NULL; + } + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + retval->count = bufs.count; + retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); + for (i = 0; i < bufs.count; i++) { + retval->list[i].idx = bufs.list[i].idx; + retval->list[i].total = bufs.list[i].total; + retval->list[i].used = 0; + retval->list[i].address = bufs.list[i].address; + } + return retval; + } + return NULL; +} + +int drmUnmapBufs(drmBufMapPtr bufs) +{ + int i; + + for (i = 0; i < bufs->count; i++) { + munmap(bufs->list[i].address, bufs->list[i].total); + } + return 0; +} + +int drmDMA(int fd, drmDMAReqPtr request) +{ + drm_dma_t dma; + + /* Copy to hidden structure */ + dma.context = request->context; + dma.send_count = request->send_count; + dma.send_indices = request->send_list; + dma.send_sizes = request->send_sizes; + dma.flags = request->flags; + dma.request_count = request->request_count; + dma.request_size = request->request_size; + dma.request_indices = request->request_list; + dma.request_sizes = request->request_sizes; + if (ioctl(fd, DRM_IOCTL_DMA, &dma)) return -errno; + request->granted_count = dma.granted_count; + + return 0; +} + +int drmGetLock(int fd, drmContext context, drmLockFlags flags) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; + if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; + if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; + + while (ioctl(fd, DRM_IOCTL_LOCK, &lock)) + ; + return 0; +} + +int drmUnlock(int fd, drmContext context) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + return ioctl(fd, DRM_IOCTL_UNLOCK, &lock); +} + +drmContextPtr drmGetReservedContextList(int fd, int *count) +{ + drm_ctx_res_t res; + drm_ctx_t *list; + drmContextPtr retval; + int i; + + res.count = 0; + res.contexts = NULL; + if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; + + if (!res.count) return NULL; + + if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL; + if (!(retval = drmMalloc(res.count * sizeof(*retval)))) { + drmFree(list); + return NULL; + } + + res.contexts = list; + if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; + + for (i = 0; i < res.count; i++) retval[i] = list[i].handle; + drmFree(list); + + *count = res.count; + return retval; +} + +void drmFreeReservedContextList(drmContextPtr pt) +{ + drmFree(pt); +} + +int drmCreateContext(int fd, drmContextPtr handle) +{ + drm_ctx_t ctx; + + ctx.flags = 0; /* Modified with functions below */ + if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno; + *handle = ctx.handle; + return 0; +} + +int drmSwitchToContext(int fd, drmContext context) +{ + drm_ctx_t ctx; + + ctx.handle = context; + if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno; + return 0; +} + +int drmSetContextFlags(int fd, drmContext context, drmContextFlags flags) +{ + drm_ctx_t ctx; + + /* Context preserving means that no context + switched are done between DMA buffers + from one context and the next. This is + suitable for use in the X server (which + promises to maintain hardware context, + or in the client-side library when + buffers are swapped on behalf of two + threads. */ + ctx.handle = context; + ctx.flags = 0; + if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED; + if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY; + if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno; + return 0; +} + +int drmGetContextFlags(int fd, drmContext context, drmContextFlagsPtr flags) +{ + drm_ctx_t ctx; + + ctx.handle = context; + if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno; + *flags = 0; + if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED; + if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY; + return 0; +} + +int drmDestroyContext(int fd, drmContext handle) +{ + drm_ctx_t ctx; + ctx.handle = handle; + if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno; + return 0; +} + +int drmCreateDrawable(int fd, drmDrawablePtr handle) +{ + drm_draw_t draw; + if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno; + *handle = draw.handle; + return 0; +} + +int drmDestroyDrawable(int fd, drmDrawable handle) +{ + drm_draw_t draw; + draw.handle = handle; + if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno; + return 0; +} + +int drmAgpAcquire(int fd) +{ + if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno; + return 0; +} + +int drmAgpRelease(int fd) +{ + if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno; + return 0; +} + +int drmAgpEnable(int fd, unsigned long mode) +{ + drm_agp_mode_t m; + + m.mode = mode; + if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno; + return 0; +} + +int drmAgpAlloc(int fd, unsigned long size, unsigned long type, + unsigned long *address, unsigned long *handle) +{ + drm_agp_buffer_t b; + *handle = 0; + b.size = size; + b.handle = 0; + b.type = type; + if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno; + if (address != 0UL) *address = b.physical; + *handle = b.handle; + return 0; +} + +int drmAgpFree(int fd, unsigned long handle) +{ + drm_agp_buffer_t b; + + b.size = 0; + b.handle = handle; + if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno; + return 0; +} + +int drmAgpBind(int fd, unsigned long handle, unsigned long offset) +{ + drm_agp_binding_t b; + + b.handle = handle; + b.offset = offset; + if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno; + return 0; +} + +int drmAgpUnbind(int fd, unsigned long handle) +{ + drm_agp_binding_t b; + + b.handle = handle; + b.offset = 0; + if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno; + return 0; +} + +int drmAgpVersionMajor(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; + return i.agp_version_major; +} + +int drmAgpVersionMinor(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; + return i.agp_version_minor; +} + +unsigned long drmAgpGetMode(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.mode; +} + +unsigned long drmAgpBase(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.aperture_base; +} + +unsigned long drmAgpSize(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.aperture_size; +} + +unsigned long drmAgpMemoryUsed(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.memory_used; +} + +unsigned long drmAgpMemoryAvail(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.memory_allowed; +} + +unsigned int drmAgpVendorId(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.id_vendor; +} + +unsigned int drmAgpDeviceId(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.id_device; +} + +int drmError(int err, const char *label) +{ + switch (err) { + case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break; + case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break; + case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break; + case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break; + default: + if (err < 0) err = -err; + fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); + break; + } + + return 1; +} + +int drmCtlInstHandler(int fd, int irq) +{ + drm_control_t ctl; + + ctl.func = DRM_INST_HANDLER; + ctl.irq = irq; + if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; + return 0; +} + +int drmCtlUninstHandler(int fd) +{ + drm_control_t ctl; + + ctl.func = DRM_UNINST_HANDLER; + ctl.irq = 0; + if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; + return 0; +} + +int drmFinish(int fd, int context, drmLockFlags flags) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; + if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; + if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; + if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno; + return 0; +} + +int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) +{ + drm_irq_busid_t p; + + p.busnum = busnum; + p.devnum = devnum; + p.funcnum = funcnum; + if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno; + return p.irq; +} + +int drmAddContextTag(int fd, drmContext context, void *tag) +{ + drmHashEntry *entry = drmGetEntry(fd); + + if (drmHashInsert(entry->tagTable, context, tag)) { + drmHashDelete(entry->tagTable, context); + drmHashInsert(entry->tagTable, context, tag); + } + return 0; +} + +int drmDelContextTag(int fd, drmContext context) +{ + drmHashEntry *entry = drmGetEntry(fd); + + return drmHashDelete(entry->tagTable, context); +} + +void *drmGetContextTag(int fd, drmContext context) +{ + drmHashEntry *entry = drmGetEntry(fd); + void *value; + + if (drmHashLookup(entry->tagTable, context, &value)) return NULL; + + return value; +} + +#if defined(XFree86Server) || defined(DRM_USE_MALLOC) +static void drmSIGIOHandler(int interrupt, void *arg) +{ + unsigned long key; + void *value; + ssize_t count; + drm_ctx_t ctx; + typedef void (*_drmCallback)(int, void *, void *); + char buf[256]; + drmContext old; + drmContext new; + void *oldctx; + void *newctx; + char *pt; + drmHashEntry *entry; + + if (!drmHashTable) return; + if (drmHashFirst(drmHashTable, &key, &value)) { + entry = value; + do { +#if 1 + fprintf(stderr, "Trying %d\n", entry->fd); +#endif + if ((count = read(entry->fd, buf, sizeof(buf)))) { + buf[count] = '\0'; +#if 1 + fprintf(stderr, "Got %s\n", buf); +#endif + + for (pt = buf; *pt != ' '; ++pt); /* Find first space */ + ++pt; + old = strtol(pt, &pt, 0); + new = strtol(pt, NULL, 0); + oldctx = drmGetContextTag(entry->fd, old); + newctx = drmGetContextTag(entry->fd, new); +#if 1 + fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); +#endif + ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); + ctx.handle = new; + ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); + } + } while (drmHashNext(drmHashTable, &key, &value)); + } +} + +int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) +{ + drmHashEntry *entry; + + entry = drmGetEntry(fd); + entry->f = f; + + return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); +} + +int drmRemoveSIGIOHandler(int fd) +{ + drmHashEntry *entry = drmGetEntry(fd); + + entry->f = NULL; + + return xf86RemoveSIGIOHandler(fd); +} +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmHash.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmHash.c new file mode 100644 index 000000000..a3c9481b5 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmHash.c @@ -0,0 +1,435 @@ +/* xf86drmHash.c -- Small hash table support for integer -> integer mapping + * Created: Sun Apr 18 09:35:45 1999 by faith@precisioninsight.com + * Revised: Thu Jun 3 16:11:06 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmHash.c,v 1.3 1999/06/07 13:01:42 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmHash.c,v 1.1 1999/06/14 07:32:02 dawes Exp $ + * + * DESCRIPTION + * + * This file contains a straightforward implementation of a fixed-sized + * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for + * collision resolution. There are two potentially interesting things + * about this implementation: + * + * 1) The table is power-of-two sized. Prime sized tables are more + * traditional, but do not have a significant advantage over power-of-two + * sized table, especially when double hashing is not used for collision + * resolution. + * + * 2) The hash computation uses a table of random integers [Hanson97, + * pp. 39-41]. + * + * FUTURE ENHANCEMENTS + * + * With a table size of 512, the current implementation is sufficient for a + * few hundred keys. Since this is well above the expected size of the + * tables for which this implementation was designed, the implementation of + * dynamic hash tables was postponed until the need arises. A common (and + * naive) approach to dynamic hash table implementation simply creates a + * new hash table when necessary, rehashes all the data into the new table, + * and destroys the old table. The approach in [Larson88] is superior in + * two ways: 1) only a portion of the table is expanded when needed, + * distributing the expansion cost over several insertions, and 2) portions + * of the table can be locked, enabling a scalable thread-safe + * implementation. + * + * REFERENCES + * + * [Hanson97] David R. Hanson. C Interfaces and Implementations: + * Techniques for Creating Reusable Software. Reading, Massachusetts: + * Addison-Wesley, 1997. + * + * [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3: + * Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973. + * + * [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April + * 1988, pp. 446-457. + * + */ + +#define HASH_MAIN 0 + +#if HASH_MAIN +# include <stdio.h> +# include <stdlib.h> +#else +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define N(x) drm##x + +#define HASH_MAGIC 0xdeadbeef +#define HASH_DEBUG 0 +#define HASH_SIZE 512 /* Good for about 100 entries */ + /* If you change this value, you probably + have to change the HashHash hashing + function! */ + +#if HASH_MAIN +#define HASH_ALLOC malloc +#define HASH_FREE free +#define HASH_RANDOM_DECL +#define HASH_RANDOM_INIT(seed) srandom(seed) +#define HASH_RANDOM random() +#else +#define HASH_ALLOC drmMalloc +#define HASH_FREE drmFree +#define HASH_RANDOM_DECL void *state +#define HASH_RANDOM_INIT(seed) state = drmRandomCreate(seed) +#define HASH_RANDOM drmRandom(state) + +#endif + +typedef struct HashBucket { + unsigned long key; + void *value; + struct HashBucket *next; +} HashBucket, *HashBucketPtr; + +typedef struct HashTable { + unsigned long magic; + unsigned long entries; + unsigned long hits; /* At top of linked list */ + unsigned long partials; /* Not at top of linked list */ + unsigned long misses; /* Not in table */ + HashBucketPtr buckets[HASH_SIZE]; + int p0; + HashBucketPtr p1; +} HashTable, *HashTablePtr; + +#if HASH_MAIN +extern void *N(HashCreate)(void); +extern int N(HashDestroy)(void *t); +extern int N(HashLookup)(void *t, unsigned long key, unsigned long *value); +extern int N(HashInsert)(void *t, unsigned long key, unsigned long value); +extern int N(HashDelete)(void *t, unsigned long key); +#endif + +static unsigned long HashHash(unsigned long key) +{ + unsigned long hash = 0; + unsigned long tmp = key; + static int init = 0; + static unsigned long scatter[256]; + int i; + + if (!init) { + HASH_RANDOM_DECL; + HASH_RANDOM_INIT(37); + for (i = 0; i < 256; i++) scatter[i] = HASH_RANDOM; + ++init; + } + + while (tmp) { + hash = (hash << 1) + scatter[tmp & 0xff]; + tmp >>= 8; + } + + hash %= HASH_SIZE; +#if HASH_DEBUG + printf( "Hash(%d) = %d\n", key, hash); +#endif + return hash; +} + +void *N(HashCreate)(void) +{ + HashTablePtr table; + int i; + + table = HASH_ALLOC(sizeof(*table)); + if (!table) return NULL; + table->magic = HASH_MAGIC; + table->entries = 0; + table->hits = 0; + table->partials = 0; + table->misses = 0; + + for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL; + return table; +} + +int N(HashDestroy)(void *t) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + HashBucketPtr next; + int i; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + for (i = 0; i < HASH_SIZE; i++) { + for (bucket = table->buckets[i]; bucket;) { + next = bucket->next; + HASH_FREE(bucket); + bucket = next; + } + } + HASH_FREE(table); + return 0; +} + +/* Find the bucket and organize the list so that this bucket is at the + top. */ + +static HashBucketPtr HashFind(HashTablePtr table, + unsigned long key, unsigned long *h) +{ + unsigned long hash = HashHash(key); + HashBucketPtr prev = NULL; + HashBucketPtr bucket; + + if (h) *h = hash; + + for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) { + if (bucket->key == key) { + if (prev) { + /* Organize */ + prev->next = bucket->next; + bucket->next = table->buckets[hash]; + table->buckets[hash] = bucket; + ++table->partials; + } else { + ++table->hits; + } + return bucket; + } + prev = bucket; + } + ++table->misses; + return NULL; +} + +int N(HashLookup)(void *t, unsigned long key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + bucket = HashFind(table, key, NULL); + if (!bucket) return 1; /* Not found */ + *value = bucket->value; + return 0; /* Found */ +} + +int N(HashInsert)(void *t, unsigned long key, void *value) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + unsigned long hash; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + if (HashFind(table, key, &hash)) return 1; /* Already in table */ + + bucket = HASH_ALLOC(sizeof(*bucket)); + if (!bucket) return -1; /* Error */ + bucket->key = key; + bucket->value = value; + bucket->next = table->buckets[hash]; + table->buckets[hash] = bucket; +#if HASH_DEBUG + printf("Inserted %d at %d/%p\n", key, hash, bucket); +#endif + return 0; /* Added to table */ +} + +int N(HashDelete)(void *t, unsigned long key) +{ + HashTablePtr table = (HashTablePtr)t; + unsigned long hash; + HashBucketPtr bucket; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + bucket = HashFind(table, key, &hash); + + if (!bucket) return 1; /* Not found */ + + table->buckets[hash] = bucket->next; + HASH_FREE(bucket); + return 0; +} + +int N(HashNext)(void *t, unsigned long *key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + + for (; table->p0 < HASH_SIZE; + ++table->p0, table->p1 = table->buckets[table->p0]) { + if (table->p1) { + *key = table->p1->key; + *value = table->p1->value; + table->p1 = table->p1->next; + return 1; + } + } + return 0; +} + +int N(HashFirst)(void *t, unsigned long *key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + table->p0 = 0; + table->p1 = table->buckets[0]; + return N(HashNext)(table, key, value); +} + +#if HASH_MAIN +#define DIST_LIMIT 10 +static int dist[DIST_LIMIT]; + +static void clear_dist(void) { + int i; + + for (i = 0; i < DIST_LIMIT; i++) dist[i] = 0; +} + +static int count_entries(HashBucketPtr bucket) +{ + int count = 0; + + for (; bucket; bucket = bucket->next) ++count; + return count; +} + +static void update_dist(int count) +{ + if (count >= DIST_LIMIT) ++dist[DIST_LIMIT-1]; + else ++dist[count]; +} + +static void compute_dist(HashTablePtr table) +{ + int i; + HashBucketPtr bucket; + + printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n", + table->entries, table->hits, table->partials, table->misses); + clear_dist(); + for (i = 0; i < HASH_SIZE; i++) { + bucket = table->buckets[i]; + update_dist(count_entries(bucket)); + } + for (i = 0; i < DIST_LIMIT; i++) { + if (i != DIST_LIMIT-1) printf("%5d %10d\n", i, dist[i]); + else printf("other %10d\n", dist[i]); + } +} + +static void check_table(HashTablePtr table, + unsigned long key, unsigned long value) +{ + unsigned long retval = 0; + int retcode = N(HashLookup)(table, key, &retval); + + switch (retcode) { + case -1: + printf("Bad magic = 0x%08lx:" + " key = %lu, expected = %lu, returned = %lu\n", + table->magic, key, value, retval); + break; + case 1: + printf("Not found: key = %lu, expected = %lu returned = %lu\n", + key, value, retval); + break; + case 0: + if (value != retval) + printf("Bad value: key = %lu, expected = %lu, returned = %lu\n", + key, value, retval); + break; + default: + printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n", + retcode, key, value, retval); + break; + } +} + +int main(void) +{ + HashTablePtr table; + int i; + + printf("\n***** 256 consecutive integers ****\n"); + table = N(HashCreate)(); + for (i = 0; i < 256; i++) N(HashInsert)(table, i, i); + for (i = 0; i < 256; i++) check_table(table, i, i); + for (i = 256; i >= 0; i--) check_table(table, i, i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 1024 consecutive integers ****\n"); + table = N(HashCreate)(); + for (i = 0; i < 1024; i++) N(HashInsert)(table, i, i); + for (i = 0; i < 1024; i++) check_table(table, i, i); + for (i = 1024; i >= 0; i--) check_table(table, i, i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 1024 consecutive page addresses (4k pages) ****\n"); + table = N(HashCreate)(); + for (i = 0; i < 1024; i++) N(HashInsert)(table, i*4096, i); + for (i = 0; i < 1024; i++) check_table(table, i*4096, i); + for (i = 1024; i >= 0; i--) check_table(table, i*4096, i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 1024 random integers ****\n"); + table = N(HashCreate)(); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) N(HashInsert)(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) check_table(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) check_table(table, random(), i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 5000 random integers ****\n"); + table = N(HashCreate)(); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) N(HashInsert)(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) check_table(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) check_table(table, random(), i); + compute_dist(table); + N(HashDestroy)(table); + + return 0; +} +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c new file mode 100644 index 000000000..067c6376e --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmI810.c @@ -0,0 +1,86 @@ +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# include "xf86Priv.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/stat.h> +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include "xf86drm.h" +#include "xf86drmI810.h" +#include "drm.h" + +Bool drmI810CleanupDma(int driSubFD) +{ + drm_i810_init_t init; + + memset(&init, 0, sizeof(drm_i810_init_t)); + init.func = I810_CLEANUP_DMA; + + if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) { + return FALSE; + } + + return TRUE; +} + +Bool drmI810InitDma(int driSubFD, drmI810Init *info) +{ + drm_i810_init_t init; + + memset(&init, 0, sizeof(drm_i810_init_t)); + + init.func = I810_INIT_DMA; + init.ring_map_idx = info->ring_map_idx; + init.buffer_map_idx = info->buffer_map_idx; + init.ring_start = info->start; + init.ring_end = info->end; + init.ring_size = info->size; + init.sarea_priv_offset = info->sarea_off; + init.front_offset = info->front_offset; + init.back_offset = info->back_offset; + init.depth_offset = info->depth_offset; + init.w = info->w; + init.h = info->h; + init.pitch = info->pitch; + init.pitch_bits = info->pitch_bits; + + if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) { + return FALSE; + } + return TRUE; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmMga.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmMga.c new file mode 100644 index 000000000..aa3a6c745 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmMga.c @@ -0,0 +1,116 @@ +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# include "xf86Priv.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/stat.h> +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include "xf86drm.h" +#include "xf86drmMga.h" +#include "drm.h" + +Bool drmMgaCleanupDma(int driSubFD) +{ + drm_mga_init_t init; + memset(&init, 0, sizeof(drm_mga_init_t)); + init.func = MGA_CLEANUP_DMA; + if(ioctl(driSubFD, DRM_IOCTL_MGA_INIT, &init)) { + return FALSE; + } + + return TRUE; +} + +Bool drmMgaLockUpdate(int driSubFD, drmLockFlags flags) +{ + drm_lock_t lock; + + memset(&lock, 0, sizeof(drm_lock_t)); + + if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + + if(ioctl(driSubFD, DRM_IOCTL_MGA_FLUSH, &lock)) { + return FALSE; + } + + return TRUE; +} + +Bool drmMgaInitDma(int driSubFD, drmMgaInit *info) +{ + drm_mga_init_t init; + int i; + + memset(&init, 0, sizeof(drm_mga_init_t)); + init.func = MGA_INIT_DMA; + init.reserved_map_agpstart = info->reserved_map_agpstart; + init.reserved_map_idx = info->reserved_map_idx; + init.buffer_map_idx = info->buffer_map_idx; + init.sarea_priv_offset = info->sarea_priv_offset; + init.primary_size = info->primary_size; + init.warp_ucode_size = info->warp_ucode_size; + init.frontOffset = info->frontOffset; + init.backOffset = info->backOffset; + init.depthOffset = info->depthOffset; + init.textureOffset = info->textureOffset; + init.textureSize = info->textureSize; + init.agpTextureSize = info->agpTextureSize; + init.agpTextureOffset = info->agpTextureOffset; + init.cpp = info->cpp; + init.stride = info->stride; + init.sgram = info->sgram; + init.chipset = info->chipset; + + for(i = 0; i < MGA_MAX_WARP_PIPES; i++) { + init.WarpIndex[i].installed = info->WarpIndex[i].installed; + init.WarpIndex[i].phys_addr = info->WarpIndex[i].phys_addr; + init.WarpIndex[i].size = info->WarpIndex[i].size; + } + + init.mAccess = info->mAccess; + + + + if(ioctl(driSubFD, DRM_IOCTL_MGA_INIT, &init)) { + return FALSE; + } + return TRUE; +} + diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmR128.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmR128.c new file mode 100644 index 000000000..4195c90ba --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmR128.c @@ -0,0 +1,198 @@ +/* xf86drmR128.c -- User-level interface to Rage 128 DRM device + * Created: Sun Apr 9 18:13:54 2000 by kevin@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * Author: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# include "xf86Priv.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/stat.h> +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include "xf86drm.h" +#include "xf86drmR128.h" +#include "drm.h" + +int drmR128InitCCE(int fd, drmR128Init *info) +{ + drm_r128_init_t init; + + memset(&init, 0, sizeof(drm_r128_init_t)); + + init.func = R128_INIT_CCE; + init.sarea_priv_offset = info->sarea_priv_offset; + init.is_pci = info->is_pci; + init.cce_mode = info->cce_mode; + init.cce_fifo_size = info->cce_fifo_size; + init.cce_secure = info->cce_secure; + init.ring_size = info->ring_size; + init.usec_timeout = info->usec_timeout; + + init.fb_offset = info->fb_offset; + init.agp_ring_offset = info->agp_ring_offset; + init.agp_read_ptr_offset = info->agp_read_ptr_offset; + init.agp_vertbufs_offset = info->agp_vertbufs_offset; + init.agp_indbufs_offset = info->agp_indbufs_offset; + init.agp_textures_offset = info->agp_textures_offset; + init.mmio_offset = info->mmio_offset; + + if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno; + + return 0; +} + +int drmR128CleanupCCE(int fd) +{ + drm_r128_init_t init; + + memset(&init, 0, sizeof(drm_r128_init_t)); + + init.func = R128_CLEANUP_CCE; + + if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno; + + return 0; +} + +int drmR128EngineReset(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_RESET, NULL)) return -errno; + + return 0; +} + +int drmR128EngineFlush(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_FLUSH, NULL)) return -errno; + + return 0; +} + +int drmR128CCEWaitForIdle(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_CCEIDL, NULL)) return -errno; + + return 0; +} + +int drmR128SubmitPackets(int fd, CARD32 *buffer, int *count, int flags) +{ + drm_r128_packet_t packet; + int ret; + + memset(&packet, 0, sizeof(drm_r128_packet_t)); + + packet.count = *count; + packet.flags = flags; + + while (packet.count > 0) { + packet.buffer = buffer + (*count - packet.count); + ret = ioctl(fd, DRM_IOCTL_R128_PACKET, &packet); + if (ret < 0 && ret != -EAGAIN) { + *count = packet.count; + return -errno; + } + } + + *count = 0; + return 0; +} + +int drmR128GetVertexBuffers(int fd, int count, int *indices, int *sizes) +{ + drm_r128_vertex_t v; + + v.send_count = 0; + v.send_indices = NULL; + v.send_sizes = NULL; + v.prim = DRM_R128_PRIM_NONE; + v.request_count = count; + v.request_indices = indices; + v.request_sizes = sizes; + v.granted_count = 0; + + if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v)) return -errno; + + return v.granted_count; +} + +int drmR128FlushVertexBuffers(int fd, int count, int *indices, + int *sizes, drmR128PrimType prim) +{ + drm_r128_vertex_t v; + + v.send_count = count; + v.send_indices = indices; + v.send_sizes = sizes; + v.prim = prim; + v.request_count = 0; + v.request_indices = NULL; + v.request_sizes = NULL; + v.granted_count = 0; + + if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v) < 0) return -errno; + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmRandom.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmRandom.c new file mode 100644 index 000000000..dad836d02 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmRandom.c @@ -0,0 +1,219 @@ +/* xf86drmRandom.c -- "Minimal Standard" PRNG Implementation + * Created: Mon Apr 19 08:28:13 1999 by faith@precisioninsight.com + * Revised: Thu Jun 24 14:53:45 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRandom.c,v 1.4 1999/06/24 18:54:55 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRandom.c,v 1.2 1999/06/27 14:08:20 dawes Exp $ + * + * DESCRIPTION + * + * This file contains a simple, straightforward implementation of the Park + * & Miller "Minimal Standard" PRNG [PM88, PMS93], which is a Lehmer + * multiplicative linear congruential generator (MLCG) with a period of + * 2^31-1. + * + * This implementation is intended to provide a reliable, portable PRNG + * that is suitable for testing a hash table implementation and for + * implementing skip lists. + * + * FUTURE ENHANCEMENTS + * + * If initial seeds are not selected randomly, two instances of the PRNG + * can be correlated. [Knuth81, pp. 32-33] describes a shuffling technique + * that can eliminate this problem. + * + * If PRNGs are used for simulation, the period of the current + * implementation may be too short. [LE88] discusses methods of combining + * MLCGs to produce much longer periods, and suggests some alternative + * values for A and M. [LE90 and Sch92] also provide information on + * long-period PRNGs. + * + * REFERENCES + * + * [Knuth81] Donald E. Knuth. The Art of Computer Programming. Volume 2: + * Seminumerical Algorithms. Reading, Massachusetts: Addison-Wesley, 1981. + * + * [LE88] Pierre L'Ecuyer. "Efficient and Portable Combined Random Number + * Generators". CACM 31(6), June 1988, pp. 742-774. + * + * [LE90] Pierre L'Ecuyer. "Random Numbers for Simulation". CACM 33(10, + * October 1990, pp. 85-97. + * + * [PM88] Stephen K. Park and Keith W. Miller. "Random Number Generators: + * Good Ones are Hard to Find". CACM 31(10), October 1988, pp. 1192-1201. + * + * [Sch92] Bruce Schneier. "Pseudo-Ransom Sequence Generator for 32-Bit + * CPUs". Dr. Dobb's Journal 17(2), February 1992, pp. 34, 37-38, 40. + * + * [PMS93] Stephen K. Park, Keith W. Miller, and Paul K. Stockmeyer. In + * "Technical Correspondence: Remarks on Choosing and Implementing Random + * Number Generators". CACM 36(7), July 1993, pp. 105-110. + * + */ + +#define RANDOM_MAIN 0 + +#if RANDOM_MAIN +# include <stdio.h> +# include <stdlib.h> +#else +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define N(x) drm##x + +#define RANDOM_MAGIC 0xfeedbeef +#define RANDOM_DEBUG 0 + +#if RANDOM_MAIN +#define RANDOM_ALLOC malloc +#define RANDOM_FREE free +#else +#define RANDOM_ALLOC drmMalloc +#define RANDOM_FREE drmFree +#endif + +typedef struct RandomState { + unsigned long magic; + unsigned long a; + unsigned long m; + unsigned long q; /* m div a */ + unsigned long r; /* m mod a */ + unsigned long check; + long seed; +} RandomState; + +#if RANDOM_MAIN +extern void *N(RandomCreate)(unsigned long seed); +extern int N(RandomDestroy)(void *state); +extern unsigned long N(Random)(void *state); +extern double N(RandomDouble)(void *state); +#endif + +void *N(RandomCreate)(unsigned long seed) +{ + RandomState *state; + + state = RANDOM_ALLOC(sizeof(*state)); + if (!state) return NULL; + state->magic = RANDOM_MAGIC; +#if 0 + /* Park & Miller, October 1988 */ + state->a = 16807; + state->m = 2147483647; + state->check = 1043618065; /* After 10000 iterations */ +#else + /* Park, Miller, and Stockmeyer, July 1993 */ + state->a = 48271; + state->m = 2147483647; + state->check = 399268537; /* After 10000 iterations */ +#endif + state->q = state->m / state->a; + state->r = state->m % state->a; + + state->seed = seed; + /* Check for illegal boundary conditions, + and choose closest legal value. */ + if (state->seed <= 0) state->seed = 1; + if (state->seed >= state->m) state->seed = state->m - 1; + + return state; +} + +int N(RandomDestroy)(void *state) +{ + RANDOM_FREE(state); + return 0; +} + +unsigned long N(Random)(void *state) +{ + RandomState *s = (RandomState *)state; + long hi; + long lo; + + hi = s->seed / s->q; + lo = s->seed % s->q; + s->seed = s->a * lo - s->r * hi; + if (s->seed <= 0) s->seed += s->m; + + return s->seed; +} + +double N(RandomDouble)(void *state) +{ + RandomState *s = (RandomState *)state; + + return (double)N(Random)(state)/(double)s->m; +} + +#if RANDOM_MAIN +static void check_period(long seed) +{ + unsigned long count = 0; + unsigned long initial; + void *state; + + state = N(RandomCreate)(seed); + initial = N(Random)(state); + ++count; + while (initial != N(Random)(state)) { + if (!++count) break; + } + printf("With seed of %10ld, period = %10lu (0x%08lx)\n", + seed, count, count); + N(RandomDestroy)(state); +} + +int main(void) +{ + RandomState *state; + int i; + unsigned long rand; + + state = N(RandomCreate)(1); + for (i = 0; i < 10000; i++) { + rand = N(Random)(state); + } + printf("After 10000 iterations: %lu (%lu expected): %s\n", + rand, state->check, + rand - state->check ? "*INCORRECT*" : "CORRECT"); + N(RandomDestroy)(state); + + printf("Checking periods...\n"); + check_period(1); + check_period(2); + check_period(31415926); + + return 0; +} +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmSL.c b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmSL.c new file mode 100644 index 000000000..d5dd63da8 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/xf86drmSL.c @@ -0,0 +1,490 @@ +/* xf86drmSL.c -- Skip list support + * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com + * Revised: Thu Jun 3 16:13:01 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmSL.c,v 1.2 1999/06/07 13:01:42 faith Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmSL.c,v 1.1 1999/06/14 07:32:02 dawes Exp $ + * + * DESCRIPTION + * + * This file contains a straightforward skip list implementation.n + * + * FUTURE ENHANCEMENTS + * + * REFERENCES + * + * [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to + * Balanced Trees. CACM 33(6), June 1990, pp. 668-676. + * + */ + +#define SL_MAIN 0 + +#if SL_MAIN +# include <stdio.h> +# include <stdlib.h> +# include <sys/time.h> +#else +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define N(x) drm##x + +#define SL_LIST_MAGIC 0xfacade00LU +#define SL_ENTRY_MAGIC 0x00fab1edLU +#define SL_FREED_MAGIC 0xdecea5edLU +#define SL_MAX_LEVEL 16 +#define SL_DEBUG 0 +#define SL_RANDOM_SEED 0xc01055a1LU + +#if SL_MAIN +#define SL_ALLOC malloc +#define SL_FREE free +#define SL_RANDOM_DECL static int state = 0; +#define SL_RANDOM_INIT(seed) if (!state) { srandom(seed); ++state; } +#define SL_RANDOM random() +#else +#define SL_ALLOC drmMalloc +#define SL_FREE drmFree +#define SL_RANDOM_DECL static void *state = NULL +#define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed) +#define SL_RANDOM drmRandom(state) + +#endif + +typedef struct SLEntry { + unsigned long magic; /* SL_ENTRY_MAGIC */ + unsigned long key; + void *value; + int levels; + struct SLEntry *forward[1]; /* variable sized array */ +} SLEntry, *SLEntryPtr; + +typedef struct SkipList { + unsigned long magic; /* SL_LIST_MAGIC */ + int level; + int count; + SLEntryPtr head; + SLEntryPtr p0; /* Position for iteration */ +} SkipList, *SkipListPtr; + +#if SL_MAIN +extern void *N(SLCreate)(void); +extern int N(SLDestroy)(void *l); +extern int N(SLLookup)(void *l, unsigned long key, void **value); +extern int N(SLInsert)(void *l, unsigned long key, void *value); +extern int N(SLDelete)(void *l, unsigned long key); +extern int N(SLNext)(void *l, unsigned long *key, void **value); +extern int N(SLFirst)(void *l, unsigned long *key, void **value); +extern void N(SLDump)(void *l); +extern int N(SLLookupNeighbors)(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); +#endif + +static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value) +{ + SLEntryPtr entry; + + if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL; + + entry = SL_ALLOC(sizeof(*entry) + + (max_level + 1) * sizeof(entry->forward[0])); + if (!entry) return NULL; + entry->magic = SL_ENTRY_MAGIC; + entry->key = key; + entry->value = value; + entry->levels = max_level + 1; + + return entry; +} + +static int SLRandomLevel(void) +{ + int level = 1; + SL_RANDOM_DECL; + + SL_RANDOM_INIT(SL_RANDOM_SEED); + + while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level; + return level; +} + +void *N(SLCreate)(void) +{ + SkipListPtr list; + int i; + + list = SL_ALLOC(sizeof(*list)); + if (!list) return NULL; + list->magic = SL_LIST_MAGIC; + list->level = 0; + list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL); + list->count = 0; + + for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL; + + return list; +} + +int N(SLDestroy)(void *l) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + SLEntryPtr next; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + for (entry = list->head; entry; entry = next) { + if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */ + next = entry->forward[0]; + entry->magic = SL_FREED_MAGIC; + SL_FREE(entry); + } + + list->magic = SL_FREED_MAGIC; + SL_FREE(list); + return 0; +} + +static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) return NULL; + + for (i = list->level, entry = list->head; i >= 0; i--) { + while (entry->forward[i] && entry->forward[i]->key < key) + entry = entry->forward[i]; + update[i] = entry; + } + + return entry->forward[0]; +} + +int N(SLInsert)(void *l, unsigned long key, void *value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + int level; + int i; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = SLLocate(list, key, update); + + if (entry && entry->key == key) return 1; /* Already in list */ + + + level = SLRandomLevel(); + if (level > list->level) { + level = ++list->level; + update[level] = list->head; + } + + entry = SLCreateEntry(level, key, value); + + /* Fix up forward pointers */ + for (i = 0; i <= level; i++) { + entry->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = entry; + } + + ++list->count; + return 0; /* Added to table */ +} + +int N(SLDelete)(void *l, unsigned long key) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = SLLocate(list, key, update); + + if (!entry || entry->key != key) return 1; /* Not found */ + + /* Fix up forward pointers */ + for (i = 0; i <= list->level; i++) { + if (update[i]->forward[i] == entry) + update[i]->forward[i] = entry->forward[i]; + } + + entry->magic = SL_FREED_MAGIC; + SL_FREE(entry); + + while (list->level && !list->head->forward[list->level]) --list->level; + --list->count; + return 0; +} + +int N(SLLookup)(void *l, unsigned long key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + + entry = SLLocate(list, key, update); + + if (entry && entry->key == key) { + *value = entry; + return 0; + } + *value = NULL; + return -1; +} + +int N(SLLookupNeighbors)(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + int retcode = 0; + + entry = SLLocate(list, key, update); + + *prev_key = *next_key = key; + *prev_value = *next_value = NULL; + + if (update[0]) { + *prev_key = update[0]->key; + *prev_value = update[0]->value; + ++retcode; + if (update[0]->forward[0]) { + *next_key = update[0]->forward[0]->key; + *next_value = update[0]->forward[0]->value; + ++retcode; + } + } + return retcode; +} + +int N(SLNext)(void *l, unsigned long *key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = list->p0; + + if (entry) { + list->p0 = entry->forward[0]; + *key = entry->key; + *value = entry->value; + return 1; + } + list->p0 = NULL; + return 0; +} + +int N(SLFirst)(void *l, unsigned long *key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + list->p0 = list->head->forward[0]; + return N(SLNext)(list, key, value); +} + +/* Dump internal data structures for debugging. */ +void N(SLDump)(void *l) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) { + printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", + list->magic, SL_LIST_MAGIC); + return; + } + + printf("Level = %d, count = %d\n", list->level, list->count); + for (entry = list->head; entry; entry = entry->forward[0]) { + if (entry->magic != SL_ENTRY_MAGIC) { + printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", + list->magic, SL_ENTRY_MAGIC); + } + printf("\nEntry %p <0x%08lx, %p> has %2d levels\n", + entry, entry->key, entry->value, entry->levels); + for (i = 0; i < entry->levels; i++) { + if (entry->forward[i]) { + printf(" %2d: %p <0x%08lx, %p>\n", + i, + entry->forward[i], + entry->forward[i]->key, + entry->forward[i]->value); + } else { + printf(" %2d: %p\n", i, entry->forward[i]); + } + } + } +} + +#if SL_MAIN +static void print(SkipListPtr list) +{ + unsigned long key; + void *value; + + if (N(SLFirst)(list, &key, &value)) { + do { + printf("key = %5lu, value = %p\n", key, value); + } while (N(SLNext)(list, &key, &value)); + } +} + +static double do_time(int size, int iter) +{ + SkipListPtr list; + int i, j; + unsigned long keys[1000000]; + unsigned long previous; + unsigned long key; + void *value; + struct timeval start, stop; + double usec; + SL_RANDOM_DECL; + + SL_RANDOM_INIT(12345); + + list = N(SLCreate)(); + + for (i = 0; i < size; i++) { + keys[i] = SL_RANDOM; + N(SLInsert)(list, keys[i], NULL); + } + + previous = 0; + if (N(SLFirst)(list, &key, &value)) { + do { + if (key <= previous) { + printf( "%lu !< %lu\n", previous, key); + } + previous = key; + } while (N(SLNext)(list, &key, &value)); + } + + gettimeofday(&start, NULL); + for (j = 0; j < iter; j++) { + for (i = 0; i < size; i++) { + if (N(SLLookup)(list, keys[i], &value)) + printf("Error %lu %d\n", keys[i], i); + } + } + gettimeofday(&stop, NULL); + + usec = (double)(stop.tv_sec * 1000000 + stop.tv_usec + - start.tv_sec * 1000000 - start.tv_usec) / (size * iter); + + printf("%0.2f microseconds for list length %d\n", usec, size); + + N(SLDestroy)(list); + + return usec; +} + +static void print_neighbors(void *list, unsigned long key) +{ + unsigned long prev_key = 0; + unsigned long next_key = 0; + void *prev_value; + void *next_value; + int retval; + + retval = drmSLLookupNeighbors(list, key, + &prev_key, &prev_value, + &next_key, &next_value); + printf("Neighbors of %5lu: %d %5lu %5lu\n", + key, retval, prev_key, next_key); +} + +int main(void) +{ + SkipListPtr list; + double usec, usec2, usec3, usec4; + + list = N(SLCreate)(); + printf( "list at %p\n", list); + + print(list); + printf("\n==============================\n\n"); + + N(SLInsert)(list, 123, NULL); + N(SLInsert)(list, 213, NULL); + N(SLInsert)(list, 50, NULL); + print(list); + printf("\n==============================\n\n"); + + print_neighbors(list, 0); + print_neighbors(list, 50); + print_neighbors(list, 51); + print_neighbors(list, 123); + print_neighbors(list, 200); + print_neighbors(list, 213); + print_neighbors(list, 256); + printf("\n==============================\n\n"); + + N(SLDelete)(list, 50); + print(list); + printf("\n==============================\n\n"); + + N(SLDump)(list); + N(SLDestroy)(list); + printf("\n==============================\n\n"); + + usec = do_time(100, 10000); + usec2 = do_time(1000, 500); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 1000.0/100.0, usec2 / usec); + + usec3 = do_time(10000, 50); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 10000.0/100.0, usec3 / usec); + + usec4 = do_time(100000, 4); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 100000.0/100.0, usec4 / usec); + + return 0; +} +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile index 96388450b..fdaecb972 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Imakefile @@ -13,15 +13,16 @@ MOBJ = drmmodule.o MTRR_DEFINES = -DHAS_MTRR_SUPPORT #endif -SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c $(MSRC) -OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o $(MOBJ) - +SRCS = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmI810.c xf86drmMga.c xf86drmR128.c $(MSRC) +OBJS = xf86drm.o xf86drmHash.o xf86drmRandom.o xf86drmSL.o xf86drmI810.o xf86drmMga.o xf86drmR128.o $(MOBJ) INCLUDES = -I$(XF86COMSRC) -I$(XF86OSSRC) -I. -I$(SERVERSRC)/include \ -I$(XINCLUDESRC) -I$(EXTINCSRC) -I../.. -Ikernel DEFINES = $(MTRR_DEFINES) $(GLX_DEFINES) +#if DoLoadableServer + ModuleObjectRule() LibraryModuleTarget(drm,$(OBJS)) NormalLintTarget($(SRCS)) @@ -30,6 +31,14 @@ NormalLintTarget($(SRCS)) InstallLibraryModule(drm,$(MODULEDIR),linux) #endif +#else + +SubdirLibraryRule($(OBJS)) +NormalLibraryObjectRule() + +#endif + + #define IHaveSubdirs SUBDIRS = kernel diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel index 44d75c487..a169473af 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel @@ -14,7 +14,8 @@ L_TARGET := libdrm.a L_OBJS := init.o memory.o proc.o auth.o context.o drawable.o bufs.o \ - lists.o lock.o ioctl.o fops.o vm.o dma.o + lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o \ + agpsupport.o M_OBJS := @@ -26,6 +27,14 @@ ifdef CONFIG_DRM_TDFX M_OBJS += tdfx.o endif +ifdef CONFIG_DRM_MGA +M_OBJS += mga.o +endif + +ifdef CONFIG_DRM_R128 +M_OBJS += r128.o +endif + include $(TOPDIR)/Rules.make gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET) @@ -33,3 +42,12 @@ gamma.o: gamma_drv.o gamma_dma.o $(L_TARGET) tdfx.o: tdfx_drv.o tdfx_context.o $(L_TARGET) $(LD) $(LD_RFLAG) -r -o $@ tdfx_drv.o tdfx_context.o -L. -ldrm + +i810.o: i810_drv.o i810_context.o $(L_TARGET) + $(LD) $(LD_RFLAG) -r -o $@ i810_drv.o i810_bufs.o i810_dma.o i810_context.o -L. -ldrm + +mga.o: mga_drv.o mga_context.o mga_dma.o mga_bufs.o $(L_TARGET) + $(LD) $(LD_RFLAG) -r -o $@ mga_drv.o mga_bufs.o mga_dma.o mga_context.o mga_state.o -L. -ldrm + +r128.o: r128_drv.o r128_context.o $(L_TARGET) + $(LD) $(LD_RFLAG) -r -o $@ r128_drv.o r128_context.o -L. -ldrm diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux index 9810fe3d5..ecc196bdd 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux @@ -47,7 +47,7 @@ # **** End of SMP/MODVERSIONS detection -MODS= gamma.o tdfx.o +MODS= gamma.o tdfx.o r128.o LIBS= libdrm.a PROGS= drmstat @@ -61,6 +61,9 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS) TDFXOBJS= tdfx_drv.o tdfx_context.o TDFXHEADERS= tdfx_drv.h $(DRMHEADERS) +R128OBJS= r128_drv.o r128_dma.o r128_bufs.o r128_context.o +R128HEADERS= r128_drv.h r128_drm.h $(DRMHEADERS) + PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po PROGHEADERS= xf86drm.h $(DRMHEADERS) @@ -167,6 +170,9 @@ gamma.o: $(GAMMAOBJS) $(LIBS) tdfx.o: $(TDFXOBJS) $(LIBS) $(LD) -r $^ -o $@ +r128.o: $(R128OBJS) $(LIBS) + $(LD) -r $^ -o $@ + ifeq ($(AGP),1) mga.o: $(MGAOBJS) $(LIBS) $(LD) -r $^ -o $@ @@ -196,6 +202,7 @@ ChangeLog: $(DRMOBJS): $(DRMHEADERS) $(GAMMAOBJS): $(GAMMAHEADERS) $(TDFXOBJS): $(TDFXHEADERS) +$(R128OBJS): $(R128HEADERS) ifeq ($(AGP),1) $(MGAOBJS): $(MGAHEADERS) $(I810OBJS): $(I810HEADERS) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c index 262d63adf..c89c3e258 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/agpsupport.c @@ -238,6 +238,8 @@ int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd, page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; if ((retcode = drm_bind_agp(entry->memory, page))) return retcode; entry->bound = dev->agp->base + (page << PAGE_SHIFT); + DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", + dev->agp->base, entry->bound); return 0; } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h index 15491aeeb..c8c5581da 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h @@ -72,9 +72,10 @@ typedef struct drm_clip_rect { unsigned short y2; } drm_clip_rect_t; -/* Seperate include files for the i810/mga specific structures */ +/* Seperate include files for the i810/mga/r128 specific structures */ #include "mga_drm.h" #include "i810_drm.h" +#include "r128_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -297,7 +298,7 @@ typedef struct drm_agp_info { #define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) #define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) -#define DRM_IOCTL_GET_MAGIC DRM_IOW( 0x02, drm_auth_t) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t) #define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) @@ -328,11 +329,11 @@ typedef struct drm_agp_info { #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) #define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) -#define DRM_IOCTL_AGP_ENABLE DRM_IOR( 0x32, drm_agp_mode_t) -#define DRM_IOCTL_AGP_INFO DRM_IOW( 0x33, drm_agp_info_t) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t) #define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t) #define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t) -#define DRM_IOCTL_AGP_BIND DRM_IOWR(0x36, drm_agp_binding_t) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t) #define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t) /* Mga specific ioctls */ @@ -342,12 +343,23 @@ typedef struct drm_agp_info { #define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t) #define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t) #define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t ) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) /* I810 specific ioctls */ #define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) #define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) -#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t) +#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t) #define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) #define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) +#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) +#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46) + +/* Rage 128 specific ioctls */ +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) +#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43) +#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h index ecf50436d..350d1ef9b 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h @@ -229,8 +229,8 @@ typedef struct drm_magic_entry { } drm_magic_entry_t; typedef struct drm_magic_head { - struct drm_magic_entry *head; - struct drm_magic_entry *tail; + struct drm_magic_entry *head; + struct drm_magic_entry *tail; } drm_magic_head_t; typedef struct drm_vma_entry { @@ -263,16 +263,15 @@ typedef struct drm_buf { DRM_LIST_RECLAIM = 5 } list; /* Which list we're on */ - - void *dev_private; - int dev_priv_size; - #if DRM_DMA_HISTOGRAM cycles_t time_queued; /* Queued to kernel DMA queue */ cycles_t time_dispatched; /* Dispatched to hardware */ cycles_t time_completed; /* Completed by hardware */ cycles_t time_freed; /* Back on freelist */ #endif + + int dev_priv_size; /* Size of buffer private stoarge */ + void *dev_private; /* Per-buffer private storage */ } drm_buf_t; #if DRM_DMA_HISTOGRAM diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c index 3372f51ea..eb78c0374 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_dma.c @@ -88,13 +88,31 @@ static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address, GAMMA_WRITE(GAMMA_DMACOUNT, length / 4); } -static inline void gamma_dma_quiescent(drm_device_t *dev) +static inline void gamma_dma_quiescent_single(drm_device_t *dev) { while (GAMMA_READ(GAMMA_DMACOUNT)) ; while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) ; + + GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); + GAMMA_WRITE(GAMMA_SYNC, 0); + + do { + while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) + ; + } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); +} + +static inline void gamma_dma_quiescent_dual(drm_device_t *dev) +{ + while (GAMMA_READ(GAMMA_DMACOUNT)) + ; + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) + ; + GAMMA_WRITE(GAMMA_BROADCASTMASK, 3); + GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); GAMMA_WRITE(GAMMA_SYNC, 0); @@ -104,7 +122,6 @@ static inline void gamma_dma_quiescent(drm_device_t *dev) ; } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); - /* Read from second MX */ do { while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000)) @@ -789,8 +806,13 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, if (!ret) { if (lock.flags & _DRM_LOCK_READY) gamma_dma_ready(dev); - if (lock.flags & _DRM_LOCK_QUIESCENT) - gamma_dma_quiescent(dev); + if (lock.flags & _DRM_LOCK_QUIESCENT) { + if (gamma_found() == 1) { + gamma_dma_quiescent_single(dev); + } else { + gamma_dma_quiescent_dual(dev); + } + } } DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.c index c6838cb74..d42cf4aea 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.c @@ -32,6 +32,7 @@ #define EXPORT_SYMTAB #include "drmP.h" #include "gamma_drv.h" +#include <linux/pci.h> EXPORT_SYMBOL(gamma_init); EXPORT_SYMBOL(gamma_cleanup); @@ -99,10 +100,13 @@ static drm_ioctl_desc_t gamma_ioctls[] = { int init_module(void); void cleanup_module(void); static char *gamma = NULL; +static int devices = 0; MODULE_AUTHOR("Precision Insight, Inc., Cedar Park, Texas."); MODULE_DESCRIPTION("3dlabs GMX 2000"); MODULE_PARM(gamma, "s"); +MODULE_PARM(devices, "i"); +MODULE_PARM_DESC(devices, "devices=x, where x is the number of MX chips on your card\n"); /* init_module is called when insmod is used to load the module */ @@ -317,6 +321,34 @@ static int gamma_takedown(drm_device_t *dev) return 0; } +int gamma_found(void) +{ + return devices; +} + +int gamma_find_devices(void) +{ + struct pci_dev *d = NULL, *one = NULL, *two = NULL; + + d = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_GAMMA,d); + if (!d) return 0; + + one = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_MX,d); + if (!one) return 0; + + /* Make sure it's on the same card, if not - no MX's found */ + if (PCI_SLOT(d->devfn) != PCI_SLOT(one->devfn)) return 0; + + two = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_MX,one); + if (!two) return 1; + + /* Make sure it's on the same card, if not - only 1 MX found */ + if (PCI_SLOT(d->devfn) != PCI_SLOT(two->devfn)) return 1; + + /* Two MX's found - we don't currently support more than 2 */ + return 2; +} + /* gamma_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ @@ -334,6 +366,8 @@ int gamma_init(void) #ifdef MODULE drm_parse_options(gamma); #endif + devices = gamma_find_devices(); + if (devices == 0) return -1; if ((retcode = misc_register(&gamma_misc))) { DRM_ERROR("Cannot register \"%s\"\n", GAMMA_NAME); @@ -345,13 +379,14 @@ int gamma_init(void) drm_mem_init(); drm_proc_init(dev); - DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d with %d MX devices\n", GAMMA_NAME, GAMMA_MAJOR, GAMMA_MINOR, GAMMA_PATCHLEVEL, GAMMA_DATE, - gamma_misc.minor); + gamma_misc.minor, + devices); return 0; } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.h index 622cedfe3..55dc26bec 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/gamma_drv.h @@ -51,5 +51,7 @@ extern int gamma_irq_install(drm_device_t *dev, int irq); extern int gamma_irq_uninstall(drm_device_t *dev); extern int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int gamma_find_devices(void); +extern int gamma_found(void); #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c index 315f34378..fa1f84dcd 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_bufs.c @@ -119,6 +119,7 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, buf->dev_private = drm_alloc(sizeof(drm_i810_buf_priv_t), DRM_MEM_BUFS); buf->dev_priv_size = sizeof(drm_i810_buf_priv_t); + memset(buf->dev_private, 0, sizeof(drm_i810_buf_priv_t)); #if DRM_DMA_HISTOGRAM buf->time_queued = 0; @@ -331,113 +332,3 @@ int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int i810_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; - int retcode = 0; - const int zero = 0; - unsigned long virtual; - unsigned long address; - drm_buf_map_t request; - int i; - - if (!dma) return -EINVAL; - - DRM_DEBUG("\n"); - - spin_lock(&dev->count_lock); - if (atomic_read(&dev->buf_alloc)) { - spin_unlock(&dev->count_lock); - DRM_DEBUG("Busy\n"); - return -EBUSY; - } - ++dev->buf_use; /* Can't allocate more after this call */ - spin_unlock(&dev->count_lock); - - copy_from_user_ret(&request, - (drm_buf_map_t *)arg, - sizeof(request), - -EFAULT); - DRM_DEBUG("dma->flags : %lx\n", dma->flags); - if (request.count >= dma->buf_count) { - if(dma->flags & _DRM_DMA_USE_AGP) { - drm_i810_private_t *dev_priv = - (drm_i810_private_t *)dev->dev_private; - drm_map_t *map = NULL; - - map = dev->maplist[dev_priv->buffer_map_idx]; - if (!map) { - DRM_DEBUG("map is null\n"); - retcode = -EINVAL; - goto done; - } - DRM_DEBUG("map->offset : %lx\n", map->offset); - DRM_DEBUG("map->size : %lx\n", map->size); - DRM_DEBUG("map->type : %d\n", map->type); - DRM_DEBUG("map->flags : %x\n", map->flags); - DRM_DEBUG("map->handle : %lx\n", map->handle); - DRM_DEBUG("map->mtrr : %d\n", map->mtrr); - down(¤t->mm->mmap_sem); - virtual = do_mmap(filp, 0, map->size, - PROT_READ|PROT_WRITE, - MAP_SHARED, - (unsigned long)map->offset); - - up(¤t->mm->mmap_sem); - } else { - down(¤t->mm->mmap_sem); - virtual = do_mmap(filp, 0, dma->byte_count, - PROT_READ|PROT_WRITE, MAP_SHARED, 0); - up(¤t->mm->mmap_sem); - } - if (virtual > -1024UL) { - /* Real error */ - DRM_DEBUG("mmap error\n"); - retcode = (signed long)virtual; - goto done; - } - request.virtual = (void *)virtual; - - for (i = 0; i < dma->buf_count; i++) { - if (copy_to_user(&request.list[i].idx, - &dma->buflist[i]->idx, - sizeof(request.list[0].idx))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request.list[i].total, - &dma->buflist[i]->total, - sizeof(request.list[0].total))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request.list[i].used, - &zero, - sizeof(zero))) { - retcode = -EFAULT; - goto done; - } - address = virtual + dma->buflist[i]->offset; - if (copy_to_user(&request.list[i].address, - &address, - sizeof(address))) { - retcode = -EFAULT; - goto done; - } - } - } - done: - request.count = dma->buf_count; - DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); - - copy_to_user_ret((drm_buf_map_t *)arg, - &request, - sizeof(request), - -EFAULT); - - DRM_DEBUG("retcode : %d\n", retcode); - return retcode; -} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c index d82ed049e..94f35b61c 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c @@ -36,8 +36,17 @@ #include <linux/interrupt.h> /* For task queue support */ -#define I810_BUF_FREE 1 -#define I810_BUF_USED 0 +/* in case we don't have a 2.3.99-pre6 kernel or later: */ +#ifndef VM_DONTCOPY +#define VM_DONTCOPY 0 +#endif + +#define I810_BUF_FREE 2 +#define I810_BUF_CLIENT 1 +#define I810_BUF_HARDWARE 0 + +#define I810_BUF_UNMAPPED 0 +#define I810_BUF_MAPPED 1 #define I810_REG(reg) 2 #define I810_BASE(reg) ((unsigned long) \ @@ -90,7 +99,7 @@ static inline void i810_print_status_page(drm_device_t *dev) DRM_DEBUG( "hw_status: Reserved : %x\n", temp[3]); DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]); for(i = 6; i < dma->buf_count + 6; i++) { - DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]); + DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]); } } @@ -107,7 +116,7 @@ static drm_buf_t *i810_freelist_get(drm_device_t *dev) drm_i810_buf_priv_t *buf_priv = buf->dev_private; /* In use is already a pointer */ used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, - I810_BUF_USED); + I810_BUF_CLIENT); if(used == I810_BUF_FREE) { return buf; } @@ -125,8 +134,8 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf) int used; /* In use is already a pointer */ - used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE); - if(used != I810_BUF_USED) { + used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE); + if(used != I810_BUF_CLIENT) { DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx); return -EINVAL; } @@ -134,26 +143,114 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf) return 0; } -static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) +static struct file_operations i810_buffer_fops = { + open: i810_open, + flush: drm_flush, + release: i810_release, + ioctl: i810_ioctl, + mmap: i810_mmap_buffers, + read: drm_read, + fasync: drm_fasync, + poll: drm_poll, +}; + +int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i810_private_t *dev_priv = dev->dev_private; + drm_buf_t *buf = dev_priv->mmap_buffer; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + + vma->vm_flags |= (VM_IO | VM_DONTCOPY); + vma->vm_file = filp; + + buf_priv->currently_mapped = I810_BUF_MAPPED; + + if (remap_page_range(vma->vm_start, + VM_OFFSET(vma), + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) return -EAGAIN; + return 0; +} + +static int i810_map_buffer(drm_buf_t *buf, struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + drm_i810_private_t *dev_priv = dev->dev_private; + struct file_operations *old_fops; + int retcode = 0; + + if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; + down(¤t->mm->mmap_sem); + old_fops = filp->f_op; + filp->f_op = &i810_buffer_fops; + dev_priv->mmap_buffer = buf; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + dev_priv->mmap_buffer = NULL; + filp->f_op = old_fops; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + buf_priv->virtual = 0; + } + up(¤t->mm->mmap_sem); + return retcode; +} + +static int i810_unmap_buffer(drm_buf_t *buf) +{ + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + int retcode = 0; + + if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL; + down(¤t->mm->mmap_sem); + retcode = do_munmap((unsigned long)buf_priv->virtual, + (size_t) buf->total); + buf_priv->currently_mapped = I810_BUF_UNMAPPED; + buf_priv->virtual = 0; + up(¤t->mm->mmap_sem); + + return retcode; +} + +static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, + struct file *filp) { - int i; + drm_file_t *priv = filp->private_data; drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + int retcode = 0; - for (i = d->granted_count; i < d->request_count; i++) { - buf = i810_freelist_get(dev); - if (!buf) break; - buf->pid = current->pid; - copy_to_user_ret(&d->request_indices[i], - &buf->idx, - sizeof(buf->idx), - -EFAULT); - copy_to_user_ret(&d->request_sizes[i], - &buf->total, - sizeof(buf->total), - -EFAULT); - ++d->granted_count; + buf = i810_freelist_get(dev); + if (!buf) { + retcode = -ENOMEM; + DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode); + goto out_get_buf; } - return 0; + + retcode = i810_map_buffer(buf, filp); + if(retcode) { + i810_freelist_put(dev, buf); + DRM_DEBUG("mapbuf failed in %s retcode %d\n", + __FUNCTION__, retcode); + goto out_get_buf; + } + buf->pid = priv->pid; + buf_priv = buf->dev_private; + d->granted = 1; + d->request_idx = buf->idx; + d->request_size = buf->total; + d->virtual = buf_priv->virtual; + +out_get_buf: + return retcode; } static unsigned long i810_alloc_page(drm_device_t *dev) @@ -184,7 +281,10 @@ static void i810_free_page(drm_device_t *dev, unsigned long page) static int i810_dma_cleanup(drm_device_t *dev) { + drm_device_dma_t *dma = dev->dma; + if(dev->dev_private) { + int i; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; @@ -200,6 +300,12 @@ static int i810_dma_cleanup(drm_device_t *dev) drm_free(dev->dev_private, sizeof(drm_i810_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + drm_ioremapfree(buf_priv->kernel_virtual, buf->total); + } } return 0; } @@ -210,6 +316,7 @@ static int i810_wait_ring(drm_device_t *dev, int n) drm_i810_ring_buffer_t *ring = &(dev_priv->ring); int iters = 0; unsigned long end; + unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; end = jiffies + (HZ*3); while (ring->space < n) { @@ -217,9 +324,11 @@ static int i810_wait_ring(drm_device_t *dev, int n) ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->space = ring->head - (ring->tail+8); + if (ring->space < 0) ring->space += ring->Size; - if (ring->space < 0) ring->space += ring->Size; - + if (ring->head != last_head) + end = jiffies + (HZ*3); + iters++; if((signed)(end - jiffies) <= 0) { DRM_ERROR("space: %d wanted %d\n", ring->space, n); @@ -249,9 +358,9 @@ static int i810_freelist_init(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u8 *hw_status = (u8 *)dev_priv->hw_status_page; - int i; int my_idx = 24; + u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx); + int i; if(dma->buf_count > 1019) { /* Not enough space in the status page for the freelist */ @@ -262,11 +371,14 @@ static int i810_freelist_init(drm_device_t *dev) drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - buf_priv->in_use = hw_status + my_idx; - DRM_DEBUG("buf_priv->in_use : %p\n", buf_priv->in_use); - *buf_priv->in_use = I810_BUF_FREE; + buf_priv->in_use = hw_status++; buf_priv->my_use_idx = my_idx; my_idx += 4; + + *buf_priv->in_use = I810_BUF_FREE; + + buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, + buf->total); } return 0; } @@ -300,9 +412,11 @@ static int i810_dma_initialize(drm_device_t *dev, dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; + dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + init->ring_start, init->ring_size); + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; if (dev_priv->ring.virtual_start == NULL) { @@ -311,6 +425,17 @@ static int i810_dma_initialize(drm_device_t *dev, " ring buffer\n"); return -ENOMEM; } + + dev_priv->w = init->w; + dev_priv->h = init->h; + dev_priv->pitch = init->pitch; + dev_priv->back_offset = init->back_offset; + dev_priv->depth_offset = init->depth_offset; + + dev_priv->front_di1 = init->front_offset | init->pitch_bits; + dev_priv->back_di1 = init->back_offset | init->pitch_bits; + dev_priv->zi1 = init->depth_offset | init->pitch_bits; + /* Program Hardware Status Page */ dev_priv->hw_status_page = i810_alloc_page(dev); @@ -365,37 +490,270 @@ int i810_dma_init(struct inode *inode, struct file *filp, return retcode; } -static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf, - int used ) + + +/* Most efficient way to verify state for the i810 is as it is + * emitted. Non-conformant state is silently dropped. + * + * Use 'volatile' & local var tmp to force the emitted values to be + * identical to the verified ones. + */ +static void i810EmitContextVerified( drm_device_t *dev, + volatile unsigned int *code ) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + int i, j = 0; + unsigned int tmp; + RING_LOCALS; + + BEGIN_LP_RING( I810_CTX_SETUP_SIZE ); + + OUT_RING( GFX_OP_COLOR_FACTOR ); + OUT_RING( code[I810_CTXREG_CF1] ); + + OUT_RING( GFX_OP_STIPPLE ); + OUT_RING( code[I810_CTXREG_ST1] ); + + for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) { + tmp = code[i]; + + if ((tmp & (7<<29)) == (3<<29) && + (tmp & (0x1f<<24)) < (0x1d<<24)) + { + OUT_RING( tmp ); + j++; + } + } + + if (j & 1) + OUT_RING( 0 ); + + ADVANCE_LP_RING(); +} + +static void i810EmitTexVerified( drm_device_t *dev, + volatile unsigned int *code ) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + int i, j = 0; + unsigned int tmp; + RING_LOCALS; + + BEGIN_LP_RING( I810_TEX_SETUP_SIZE ); + + OUT_RING( GFX_OP_MAP_INFO ); + OUT_RING( code[I810_TEXREG_MI1] ); + OUT_RING( code[I810_TEXREG_MI2] ); + OUT_RING( code[I810_TEXREG_MI3] ); + + for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) { + tmp = code[i]; + + if ((tmp & (7<<29)) == (3<<29) && + (tmp & (0x1f<<24)) < (0x1d<<24)) + { + OUT_RING( tmp ); + j++; + } + } + + if (j & 1) + OUT_RING( 0 ); + + ADVANCE_LP_RING(); +} + + +/* Need to do some additional checking when setting the dest buffer. + */ +static void i810EmitDestVerified( drm_device_t *dev, + volatile unsigned int *code ) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + unsigned int tmp; + RING_LOCALS; + + BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 ); + + tmp = code[I810_DESTREG_DI1]; + if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { + OUT_RING( CMD_OP_DESTBUFFER_INFO ); + OUT_RING( tmp ); + } else + DRM_DEBUG("bad di1 %x (allow %x or %x)\n", + tmp, dev_priv->front_di1, dev_priv->back_di1); + + /* invarient: + */ + OUT_RING( CMD_OP_Z_BUFFER_INFO ); + OUT_RING( dev_priv->zi1 ); + + OUT_RING( GFX_OP_DESTBUFFER_VARS ); + OUT_RING( code[I810_DESTREG_DV1] ); + + OUT_RING( GFX_OP_DRAWRECT_INFO ); + OUT_RING( code[I810_DESTREG_DR1] ); + OUT_RING( code[I810_DESTREG_DR2] ); + OUT_RING( code[I810_DESTREG_DR3] ); + OUT_RING( code[I810_DESTREG_DR4] ); + OUT_RING( 0 ); + + ADVANCE_LP_RING(); +} + + + +static void i810EmitState( drm_device_t *dev ) { - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - unsigned long address = (unsigned long)buf->bus_address; - unsigned long start = address - dev->agp->base; - RING_LOCALS; + drm_i810_private_t *dev_priv = dev->dev_private; + drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + unsigned int dirty = sarea_priv->dirty; - dev_priv->counter++; - DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); - DRM_DEBUG( "i810_dma_dispatch\n"); - DRM_DEBUG( "start : 0x%lx\n", start); - DRM_DEBUG( "used : 0x%x\n", used); - DRM_DEBUG( "start + used - 4 : 0x%lx\n", start + used - 4); - i810_kernel_lost_context(dev); + if (dirty & I810_UPLOAD_BUFFERS) { + i810EmitDestVerified( dev, sarea_priv->BufferState ); + sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS; + } - BEGIN_LP_RING(10); - OUT_RING( CMD_OP_BATCH_BUFFER ); - OUT_RING( start | BB1_PROTECTED ); - OUT_RING( start + used - 4 ); - OUT_RING( CMD_STORE_DWORD_IDX ); - OUT_RING( 20 ); - OUT_RING( dev_priv->counter ); - OUT_RING( CMD_STORE_DWORD_IDX ); - OUT_RING( buf_priv->my_use_idx ); - OUT_RING( I810_BUF_FREE ); - OUT_RING( CMD_REPORT_HEAD ); - ADVANCE_LP_RING(); + if (dirty & I810_UPLOAD_CTX) { + i810EmitContextVerified( dev, sarea_priv->ContextState ); + sarea_priv->dirty &= ~I810_UPLOAD_CTX; + } + + if (dirty & I810_UPLOAD_TEX0) { + i810EmitTexVerified( dev, sarea_priv->TexState[0] ); + sarea_priv->dirty &= ~I810_UPLOAD_TEX0; + } + + if (dirty & I810_UPLOAD_TEX1) { + i810EmitTexVerified( dev, sarea_priv->TexState[1] ); + sarea_priv->dirty &= ~I810_UPLOAD_TEX1; + } } + + +/* need to verify + */ +static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, + unsigned int clear_color, + unsigned int clear_zval ) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + int pitch = dev_priv->pitch; + int cpp = 2; + int i; + RING_LOCALS; + + i810_kernel_lost_context(dev); + + if (nbox > I810_NR_SAREA_CLIPRECTS) + nbox = I810_NR_SAREA_CLIPRECTS; + + for (i = 0 ; i < nbox ; i++, pbox++) { + unsigned int x = pbox->x1; + unsigned int y = pbox->y1; + unsigned int width = (pbox->x2 - x) * cpp; + unsigned int height = pbox->y2 - y; + unsigned int start = y * pitch + x * cpp; + + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + pbox->x2 > dev_priv->w || + pbox->y2 > dev_priv->h) + continue; + + if ( flags & I810_FRONT ) { + DRM_DEBUG("clear front\n"); + BEGIN_LP_RING( 6 ); + OUT_RING( BR00_BITBLT_CLIENT | + BR00_OP_COLOR_BLT | 0x3 ); + OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch ); + OUT_RING( (height << 16) | width ); + OUT_RING( start ); + OUT_RING( clear_color ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + } + + if ( flags & I810_BACK ) { + DRM_DEBUG("clear back\n"); + BEGIN_LP_RING( 6 ); + OUT_RING( BR00_BITBLT_CLIENT | + BR00_OP_COLOR_BLT | 0x3 ); + OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch ); + OUT_RING( (height << 16) | width ); + OUT_RING( dev_priv->back_offset + start ); + OUT_RING( clear_color ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + } + + if ( flags & I810_DEPTH ) { + DRM_DEBUG("clear depth\n"); + BEGIN_LP_RING( 6 ); + OUT_RING( BR00_BITBLT_CLIENT | + BR00_OP_COLOR_BLT | 0x3 ); + OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch ); + OUT_RING( (height << 16) | width ); + OUT_RING( dev_priv->depth_offset + start ); + OUT_RING( clear_zval ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + } + } +} + +static void i810_dma_dispatch_swap( drm_device_t *dev ) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + int pitch = dev_priv->pitch; + int cpp = 2; + int ofs = dev_priv->back_offset; + int i; + RING_LOCALS; + + DRM_DEBUG("swapbuffers\n"); + + i810_kernel_lost_context(dev); + + if (nbox > I810_NR_SAREA_CLIPRECTS) + nbox = I810_NR_SAREA_CLIPRECTS; + + for (i = 0 ; i < nbox; i++, pbox++) + { + unsigned int w = pbox->x2 - pbox->x1; + unsigned int h = pbox->y2 - pbox->y1; + unsigned int dst = pbox->x1*cpp + pbox->y1*pitch; + unsigned int start = ofs + dst; + + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + pbox->x2 > dev_priv->w || + pbox->y2 > dev_priv->h) + continue; + + DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", + pbox[i].x1, pbox[i].y1, + pbox[i].x2, pbox[i].y2); + + BEGIN_LP_RING( 6 ); + OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 ); + OUT_RING( pitch | (0xCC << 16)); + OUT_RING( (h << 16) | (w * cpp)); + OUT_RING( dst ); + OUT_RING( pitch ); + OUT_RING( start ); + ADVANCE_LP_RING(); + } +} + + static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf, int discard, @@ -408,14 +766,29 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)buf->bus_address; unsigned long start = address - dev->agp->base; - int i = 0; + int i = 0, u; RING_LOCALS; - + i810_kernel_lost_context(dev); + if (nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; - - DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", + + if (discard) { + u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, + I810_BUF_HARDWARE); + if(u != I810_BUF_CLIENT) { + DRM_DEBUG("xxxx 2\n"); + } + } + + if (used > 4*1024) + used = 0; + + if (sarea_priv->dirty) + i810EmitState( dev ); + + DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", address, used, nbox); dev_priv->counter++; @@ -424,8 +797,20 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, DRM_DEBUG( "start : %lx\n", start); DRM_DEBUG( "used : %d\n", used); DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); - i810_kernel_lost_context(dev); + if (buf_priv->currently_mapped == I810_BUF_MAPPED) { + *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | + sarea_priv->vertex_prim | + ((used/4)-2)); + + if (used & 4) { + *(u32 *)((u32)buf_priv->virtual + used) = 0; + used += 4; + } + + i810_unmap_buffer(buf); + } + if (used) { do { if (i < nbox) { @@ -433,7 +818,7 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | SC_ENABLE ); OUT_RING( GFX_OP_SCISSOR_INFO ); - OUT_RING( box[i].x1 | (box[i].y1 << 16) ); + OUT_RING( box[i].x1 | (box[i].y1<<16) ); OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) ); ADVANCE_LP_RING(); } @@ -478,7 +863,9 @@ static void i810_dma_service(int irq, void *device, struct pt_regs *regs) temp = temp & ~(0x6000); if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, temp); /* Clear all interrupts */ - + else + return; + queue_task(&dev->tq, &tq_immediate); mark_bh(IMMEDIATE_BH); } @@ -538,7 +925,7 @@ int i810_irq_install(drm_device_t *dev, int irq) /* Install handler */ if ((retcode = request_irq(dev->irq, i810_dma_service, - 0, + SA_SHIRQ, dev->devname, dev))) { down(&dev->struct_sem); @@ -559,6 +946,9 @@ int i810_irq_uninstall(drm_device_t *dev) int irq; u16 temp; + +/* return 0; */ + down(&dev->struct_sem); irq = dev->irq; dev->irq = 0; @@ -617,10 +1007,15 @@ static inline void i810_dma_emit_flush(drm_device_t *dev) RING_LOCALS; i810_kernel_lost_context(dev); + BEGIN_LP_RING(2); OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_USER_INTERRUPT ); + OUT_RING( GFX_OP_USER_INTERRUPT ); ADVANCE_LP_RING(); + +/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ +/* atomic_set(&dev_priv->flush_done, 1); */ +/* wake_up_interruptible(&dev_priv->flush_queue); */ } static inline void i810_dma_quiescent_emit(drm_device_t *dev) @@ -629,13 +1024,17 @@ static inline void i810_dma_quiescent_emit(drm_device_t *dev) RING_LOCALS; i810_kernel_lost_context(dev); - BEGIN_LP_RING(4); + BEGIN_LP_RING(4); OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_USER_INTERRUPT ); - OUT_RING( 0 ); + OUT_RING( 0 ); + OUT_RING( GFX_OP_USER_INTERRUPT ); ADVANCE_LP_RING(); + +/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ +/* atomic_set(&dev_priv->flush_done, 1); */ +/* wake_up_interruptible(&dev_priv->flush_queue); */ } static void i810_dma_quiescent(drm_device_t *dev) @@ -675,8 +1074,9 @@ static int i810_flush_queue(drm_device_t *dev) { DECLARE_WAITQUEUE(entry, current); drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_device_dma_t *dma = dev->dma; unsigned long end; - int ret = 0; + int i, ret = 0; if(dev_priv == NULL) { return 0; @@ -701,7 +1101,21 @@ static int i810_flush_queue(drm_device_t *dev) current->state = TASK_RUNNING; remove_wait_queue(&dev_priv->flush_queue, &entry); - + + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + + int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE, + I810_BUF_FREE); + + if (used == I810_BUF_HARDWARE) + DRM_DEBUG("reclaimed from HARDWARE\n"); + if (used == I810_BUF_CLIENT) + DRM_DEBUG("still on client HARDWARE\n"); + } + return ret; } @@ -712,20 +1126,23 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid) int i; if (!dma) return; - if(dev->dev_private == NULL) return; - if(dma->buflist == NULL) return; + if (!dev->dev_private) return; + if (!dma->buflist) return; + i810_flush_queue(dev); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - /* Only buffers that need to get reclaimed ever - * get set to free - */ if (buf->pid == pid && buf_priv) { - cmpxchg(buf_priv->in_use, - I810_BUF_USED, I810_BUF_FREE); + int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, + I810_BUF_FREE); + + if (used == I810_BUF_CLIENT) + DRM_DEBUG("reclaimed from client\n"); + if(buf_priv->currently_mapped == I810_BUF_MAPPED) + buf_priv->currently_mapped = I810_BUF_UNMAPPED; } } } @@ -759,19 +1176,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, */ if (!ret) { -#if 0 - if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) - != lock.context) { - long j = jiffies - dev->lock.lock_time; - - if (j > 0 && j <= DRM_LOCK_SLICE) { - /* Can't take lock if we just had it and - there is contention. */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(j); - } - } -#endif add_wait_queue(&dev->lock.lock_queue, &entry); for (;;) { if (!dev->lock.hw_lock) { @@ -828,90 +1232,80 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, return 0; } -static int i810DmaGeneral(drm_device_t *dev, drm_i810_general_t *args) -{ - drm_device_dma_t *dma = dev->dma; - drm_buf_t *buf = dma->buflist[ args->idx ]; - - if (!args->used) { - i810_freelist_put(dev, buf); - } else { - i810_dma_dispatch_general( dev, buf, args->used ); - atomic_add(args->used, &dma->total_bytes); - atomic_inc(&dma->total_dmas); - } - return 0; -} -static int i810DmaVertex(drm_device_t *dev, drm_i810_vertex_t *args) -{ - drm_device_dma_t *dma = dev->dma; - drm_buf_t *buf = dma->buflist[ args->idx ]; - i810_dma_dispatch_vertex( dev, buf, args->discard, args->used ); - atomic_add(args->used, &dma->total_bytes); - atomic_inc(&dma->total_dmas); - return 0; -} - -int i810_dma_general(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int i810_dma_vertex(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_i810_general_t general; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; + drm_i810_vertex_t vertex; - int retcode = 0; - - copy_from_user_ret(&general, (drm_i810_general_t *)arg, sizeof(general), + copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex), -EFAULT); - DRM_DEBUG("i810 dma general idx %d used %d\n", - general.idx, general.used); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { - DRM_ERROR("i810_dma_general called without lock held\n"); + DRM_ERROR("i810_dma_vertex called without lock held\n"); return -EINVAL; } - retcode = i810DmaGeneral(dev, &general); + DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", + vertex.idx, vertex.used, vertex.discard); + + i810_dma_dispatch_vertex( dev, + dma->buflist[ vertex.idx ], + vertex.discard, vertex.used ); + + atomic_add(vertex.used, &dma->total_bytes); + atomic_inc(&dma->total_dmas); sarea_priv->last_enqueue = dev_priv->counter-1; sarea_priv->last_dispatch = (int) hw_status[5]; - return retcode; + return 0; } -int i810_dma_vertex(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) + + +int i810_clear_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u32 *hw_status = (u32 *)dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - drm_i810_vertex_t vertex; - int retcode = 0; + drm_i810_clear_t clear; - copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex), + copy_from_user_ret(&clear, (drm_i810_clear_t *)arg, sizeof(clear), -EFAULT); + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { - DRM_ERROR("i810_dma_vertex called without lock held\n"); + DRM_ERROR("i810_clear_bufs called without lock held\n"); return -EINVAL; } - DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", - vertex.idx, vertex.used, vertex.discard); + i810_dma_dispatch_clear( dev, clear.flags, + clear.clear_color, + clear.clear_depth ); + return 0; +} - retcode = i810DmaVertex(dev, &vertex); - sarea_priv->last_enqueue = dev_priv->counter-1; - sarea_priv->last_dispatch = (int) hw_status[5]; +int i810_swap_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; - return retcode; + DRM_DEBUG("i810_swap_bufs\n"); + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i810_swap_buf called without lock held\n"); + return -EINVAL; + } + + i810_dma_dispatch_swap( dev ); + return 0; } int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, @@ -928,53 +1322,32 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; int retcode = 0; - drm_dma_t d; + drm_i810_dma_t d; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - - copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); - DRM_DEBUG("%d %d: %d send, %d req\n", - current->pid, d.context, d.send_count, d.request_count); + DRM_DEBUG("getbuf\n"); + copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma called without lock held\n"); return -EINVAL; } - - /* Please don't send us buffers. - */ - if (d.send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - current->pid, d.send_count); - return -EINVAL; - } - /* We'll send you buffers. - */ - if (d.request_count < 0 || d.request_count > dma->buf_count) { - DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - current->pid, d.request_count, dma->buf_count); - return -EINVAL; - } - - d.granted_count = 0; + d.granted = 0; - if (!retcode && d.request_count) { - retcode = i810_dma_get_buffers(dev, &d); - } + retcode = i810_dma_get_buffer(dev, &d, filp); - DRM_DEBUG("i810_dma: %d returning, granted = %d\n", - current->pid, d.granted_count); + DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", + current->pid, retcode, d.granted); copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); sarea_priv->last_dispatch = (int) hw_status[5]; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drm.h new file mode 100644 index 000000000..4c8e09f6a --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drm.h @@ -0,0 +1,188 @@ +#ifndef _I810_DRM_H_ +#define _I810_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _I810_DEFINES_ +#define _I810_DEFINES_ + +#define I810_DMA_BUF_ORDER 12 +#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER) +#define I810_DMA_BUF_NR 256 +#define I810_NR_SAREA_CLIPRECTS 8 + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define I810_NR_TEX_REGIONS 64 +#define I810_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define I810_UPLOAD_CTX 0x4 +#define I810_UPLOAD_BUFFERS 0x8 +#define I810_UPLOAD_TEX0 0x10 +#define I810_UPLOAD_TEX1 0x20 +#define I810_UPLOAD_CLIPRECTS 0x40 + + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +/* Destbuffer state + * - backbuffer linear offset and pitch -- invarient in the current dri + * - zbuffer linear offset and pitch -- also invarient + * - drawing origin in back and depth buffers. + * + * Keep the depth/back buffer state here to acommodate private buffers + * in the future. + */ +#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */ +#define I810_DESTREG_DI1 1 +#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */ +#define I810_DESTREG_DV1 3 +#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */ +#define I810_DESTREG_DR1 5 +#define I810_DESTREG_DR2 6 +#define I810_DESTREG_DR3 7 +#define I810_DESTREG_DR4 8 +#define I810_DEST_SETUP_SIZE 10 + +/* Context state + */ +#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */ +#define I810_CTXREG_CF1 1 +#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */ +#define I810_CTXREG_ST1 3 +#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */ +#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */ +#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */ +#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */ +#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */ +#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */ +#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */ +#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */ +#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */ +#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */ +#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */ +#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */ +#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */ +#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */ +#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */ +#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */ +#define I810_CTX_SETUP_SIZE 20 + +/* Texture state (per tex unit) + */ +#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */ +#define I810_TEXREG_MI1 1 +#define I810_TEXREG_MI2 2 +#define I810_TEXREG_MI3 3 +#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */ +#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */ +#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */ +#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */ +#define I810_TEX_SETUP_SIZE 8 + +#define I810_FRONT 0x1 +#define I810_BACK 0x2 +#define I810_DEPTH 0x4 + + +typedef struct _drm_i810_init { + enum { + I810_INIT_DMA = 0x01, + I810_CLEANUP_DMA = 0x02 + } func; + int ring_map_idx; + int buffer_map_idx; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; +} drm_i810_init_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_i810_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char in_use; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_i810_tex_region_t; + +typedef struct _drm_i810_sarea { + unsigned int ContextState[I810_CTX_SETUP_SIZE]; + unsigned int BufferState[I810_DEST_SETUP_SIZE]; + unsigned int TexState[2][I810_TEX_SETUP_SIZE]; + unsigned int dirty; + + unsigned int nbox; + drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS]; + + /* Maintain an LRU of contiguous regions of texture space. If + * you think you own a region of texture memory, and it has an + * age different to the one you set, then you are mistaken and + * it has been stolen by another client. If global texAge + * hasn't changed, there is no need to walk the list. + * + * These regions can be used as a proxy for the fine-grained + * texture information of other clients - by maintaining them + * in the same lru which is used to age their own textures, + * clients have an approximate lru for the whole of global + * texture space, and can make informed decisions as to which + * areas to kick out. There is no need to choose whether to + * kick out your own texture or someone else's - simply eject + * them all in LRU order. + */ + + drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1]; + /* Last elt is sentinal */ + int texAge; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int last_quiescent; /* */ + int ctxOwner; /* last context to upload state */ + + int vertex_prim; + +} drm_i810_sarea_t; + +typedef struct _drm_i810_clear { + int clear_color; + int clear_depth; + int flags; +} drm_i810_clear_t; + + + +/* These may be placeholders if we have more cliprects than + * I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to + * false, indicating that the buffer will be dispatched again with a + * new set of cliprects. + */ +typedef struct _drm_i810_vertex { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + int discard; /* client is finished with the buffer? */ +} drm_i810_vertex_t; + +typedef struct drm_i810_dma { + void *virtual; + int request_idx; + int request_size; + int granted; +} drm_i810_dma_t; + +#endif /* _I810_DRM_H_ */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c index eec9eb0f3..b523db902 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.c @@ -79,7 +79,6 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { i810_addbufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { i810_markbufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { i810_infobufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { i810_mapbufs, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { i810_freebufs, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { i810_addctx, 1, 1 }, @@ -92,8 +91,6 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { i810_dma, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { i810_lock, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { i810_unlock, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, @@ -106,11 +103,14 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)] = { i810_dma_general,1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)] = { i810_clear_bufs, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl,1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 }, }; #define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h index 690710c83..c387bf727 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_drv.h @@ -32,6 +32,16 @@ #ifndef _I810_DRV_H_ #define _I810_DRV_H_ +typedef struct drm_i810_buf_priv { + u32 *in_use; + int my_use_idx; + int currently_mapped; + void *virtual; + void *kernel_virtual; + int map_count; + struct vm_area_struct *vma; +} drm_i810_buf_priv_t; + typedef struct _drm_i810_ring_buffer{ int tail_mask; unsigned long Start; @@ -55,6 +65,15 @@ typedef struct drm_i810_private { atomic_t flush_done; wait_queue_head_t flush_queue; /* Processes waiting until flush */ + drm_buf_t *mmap_buffer; + + + u32 front_di1, back_di1, zi1; + + int back_offset; + int depth_offset; + int w, h; + int pitch; } drm_i810_private_t; /* i810_drv.c */ @@ -71,8 +90,8 @@ extern int i810_unlock(struct inode *inode, struct file *filp, /* i810_dma.c */ extern int i810_dma_schedule(drm_device_t *dev, int locked); -extern int i810_dma(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int i810_getbuf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int i810_irq_install(drm_device_t *dev, int irq); extern int i810_irq_uninstall(drm_device_t *dev); extern int i810_control(struct inode *inode, struct file *filp, @@ -86,6 +105,7 @@ extern int i810_flush_ioctl(struct inode *inode, struct file *filp, extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid); extern int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma); /* i810_bufs.c */ @@ -97,8 +117,6 @@ extern int i810_markbufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int i810_mapbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); extern int i810_addmap(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); @@ -121,32 +139,17 @@ extern int i810_rmctx(struct inode *inode, struct file *filp, extern int i810_context_switch(drm_device_t *dev, int old, int new); extern int i810_context_switch_complete(drm_device_t *dev, int new); - - - -/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer. - * This can be fixed by emitting directly to the ringbuffer in the - * 'vertex_dma' ioctl. -*/ -typedef struct { - u32 *in_use; - int my_use_idx; -} drm_i810_buf_priv_t; - - -#define I810_DMA_GENERAL 0 -#define I810_DMA_VERTEX 1 -#define I810_DMA_DISCARD 2 /* not used */ - #define I810_VERBOSE 0 int i810_dma_vertex(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -int i810_dma_general(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +int i810_swap_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +int i810_clear_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) @@ -200,5 +203,22 @@ int i810_dma_general(struct inode *inode, struct file *filp, #define SCI_YMAX_MASK (0xffff<<16) #define SCI_XMAX_MASK (0xffff<<0) +#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) +#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) +#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x2) +#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) +#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) +#define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24)) + +#define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23)) +#define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23)) + +#define BR00_BITBLT_CLIENT 0x40000000 +#define BR00_OP_COLOR_BLT 0x10000000 +#define BR00_OP_SRC_COPY_BLT 0x10C00000 +#define BR13_SOLID_PATTERN 0x80000000 + + + #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c index b03544bc2..25e3622ca 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_dma.c @@ -52,6 +52,7 @@ static unsigned long mga_alloc_page(drm_device_t *dev) { unsigned long address; + DRM_DEBUG("%s\n", __FUNCTION__); address = __get_free_page(GFP_KERNEL); if(address == 0UL) { return 0; @@ -64,6 +65,8 @@ static unsigned long mga_alloc_page(drm_device_t *dev) static void mga_free_page(drm_device_t *dev, unsigned long page) { + DRM_DEBUG("%s\n", __FUNCTION__); + if(page == 0UL) { return; } @@ -79,9 +82,11 @@ static void mga_delay(void) return; } -static void mga_flush_write_combine(void) +void mga_flush_write_combine(void) { int xchangeDummy; + DRM_DEBUG("%s\n", __FUNCTION__); + __asm__ volatile(" push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy)); __asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;" " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;" @@ -93,18 +98,6 @@ static void mga_flush_write_combine(void) #define MGA_BUF_USED 0xffffffff #define MGA_BUF_FREE 0 -static void mga_freelist_debug(drm_mga_freelist_t *item) -{ - if(item->buf != NULL) { - DRM_DEBUG("buf index : %d\n", item->buf->idx); - } else { - DRM_DEBUG("Freelist head\n"); - } - DRM_DEBUG("item->age : %x\n", item->age); - DRM_DEBUG("item->next : %p\n", item->next); - DRM_DEBUG("item->prev : %p\n", item->prev); -} - static int mga_freelist_init(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -113,7 +106,9 @@ static int mga_freelist_init(drm_device_t *dev) drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_freelist_t *item; int i; - + + DRM_DEBUG("%s\n", __FUNCTION__); + dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); if(dev_priv->head == NULL) return -ENOMEM; memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t)); @@ -135,19 +130,10 @@ static int mga_freelist_init(drm_device_t *dev) item->buf = buf; buf_priv->my_freelist = item; buf_priv->discard = 0; + buf_priv->dispatched = 0; dev_priv->head->next = item; } - item = dev_priv->head; - while(item) { - mga_freelist_debug(item); - item = item->next; - } - DRM_DEBUG("Head\n"); - mga_freelist_debug(dev_priv->head); - DRM_DEBUG("Tail\n"); - mga_freelist_debug(dev_priv->tail); - return 0; } @@ -157,6 +143,8 @@ static void mga_freelist_cleanup(drm_device_t *dev) drm_mga_freelist_t *item; drm_mga_freelist_t *prev; + DRM_DEBUG("%s\n", __FUNCTION__); + item = dev_priv->head; while(item) { prev = item; @@ -173,14 +161,14 @@ static inline void mga_dma_quiescent(drm_device_t *dev) drm_device_dma_t *dma = dev->dma; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; unsigned long end; int i; + DRM_DEBUG("%s\n", __FUNCTION__); end = jiffies + (HZ*3); while(1) { - if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) { + if(!test_and_set_bit(MGA_IN_DISPATCH, + &dev_priv->dispatch_status)) { break; } if((signed)(end - jiffies) <= 0) { @@ -204,51 +192,25 @@ static inline void mga_dma_quiescent(drm_device_t *dev) } for (i = 0 ; i < 2000 ; i++) mga_delay(); } - DRM_DEBUG("status[1] : %x last_sync_tag : %x\n", status[1], - dev_priv->last_sync_tag); sarea_priv->dirty |= MGA_DMA_FLUSH; out_status: - clear_bit(0, &dev_priv->dispatch_lock); + clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); out_nolock: } -#define FREELIST_INITIAL (MGA_DMA_BUF_NR * 2) -#define FREELIST_COMPARE(age) ((age >> 2)) - -unsigned int mga_create_sync_tag(drm_device_t *dev) +static void mga_reset_freelist(drm_device_t *dev) { - drm_mga_private_t *dev_priv = - (drm_mga_private_t *) dev->dev_private; - unsigned int temp; - drm_buf_t *buf; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; - drm_device_dma_t *dma = dev->dma; - int i; - - dev_priv->sync_tag++; - - if(dev_priv->sync_tag < FREELIST_INITIAL) { - dev_priv->sync_tag = FREELIST_INITIAL; - } - if(dev_priv->sync_tag > 0x3fffffff) { - mga_flush_queue(dev); - mga_dma_quiescent(dev); - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[ i ]; - buf_priv = buf->dev_private; - buf_priv->my_freelist->age = MGA_BUF_FREE; - } - - dev_priv->sync_tag = FREELIST_INITIAL; - } - temp = dev_priv->sync_tag << 2; - - dev_priv->sarea_priv->last_enqueue = temp; + int i; - DRM_DEBUG("sync_tag : %x\n", temp); - return temp; + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[ i ]; + buf_priv = buf->dev_private; + buf_priv->my_freelist->age = MGA_BUF_FREE; + } } /* Least recently used : @@ -257,23 +219,52 @@ unsigned int mga_create_sync_tag(drm_device_t *dev) drm_buf_t *mga_freelist_get(drm_device_t *dev) { + DECLARE_WAITQUEUE(entry, current); drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_mga_freelist_t *prev; drm_mga_freelist_t *next; + static int failed = 0; + + DRM_DEBUG("%s : tail->age : %d last_prim_age : %d\n", __FUNCTION__, + dev_priv->tail->age, dev_priv->last_prim_age); - if((dev_priv->tail->age >> 2) <= FREELIST_COMPARE(status[1])) { + if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) { + DRM_DEBUG("I'm waiting on the freelist!!! %d\n", + dev_priv->last_prim_age); + set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status); + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&dev_priv->buf_queue, &entry); + for (;;) { + mga_dma_schedule(dev, 0); + if(!test_bit(MGA_IN_GETBUF, + &dev_priv->dispatch_status)) + break; + atomic_inc(&dev->total_sleeps); + schedule(); + if (signal_pending(current)) { + clear_bit(MGA_IN_GETBUF, + &dev_priv->dispatch_status); + goto failed_getbuf; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->buf_queue, &entry); + } + + if(dev_priv->tail->age < dev_priv->last_prim_age) { prev = dev_priv->tail->prev; next = dev_priv->tail; prev->next = NULL; next->prev = next->next = NULL; dev_priv->tail = prev; next->age = MGA_BUF_USED; + failed = 0; return next->buf; - } + } +failed_getbuf: + failed++; return NULL; } @@ -286,6 +277,8 @@ int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf) drm_mga_freelist_t *head; drm_mga_freelist_t *next; + DRM_DEBUG("%s\n", __FUNCTION__); + if(buf_priv->my_freelist->age == MGA_BUF_USED) { /* Discarded buffer, put it on the tail */ next = buf_priv->my_freelist; @@ -312,32 +305,6 @@ int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf) return 0; } -static void mga_print_all_primary(drm_device_t *dev) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_prim_buf_t *prim; - int i; - - DRM_DEBUG("Full list of primarys\n"); - for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) { - prim = dev_priv->prim_bufs[i]; - DRM_DEBUG("index : %d num_dwords : %d " - "max_dwords : %d phy_head : %x\n", - prim->idx, prim->num_dwords, - prim->max_dwords, prim->phys_head); - DRM_DEBUG("sec_used : %d swap_pending : %x " - "in_use : %x force_fire : %d\n", - prim->sec_used, prim->swap_pending, - prim->in_use, atomic_read(&prim->force_fire)); - DRM_DEBUG("needs_overflow : %d\n", - atomic_read(&prim->needs_overflow)); - } - - DRM_DEBUG("current_idx : %d, next_idx : %d, last_idx : %d\n", - dev_priv->next_prim->idx, dev_priv->last_prim->idx, - dev_priv->current_prim->idx); -} - static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) { drm_mga_private_t *dev_priv = dev->dev_private; @@ -345,10 +312,9 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) int i, temp, size_of_buf; int offset = init->reserved_map_agpstart; - DRM_DEBUG("mga_init_primary_bufs\n"); + DRM_DEBUG("%s\n", __FUNCTION__); dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; - DRM_DEBUG("primary_size\n"); size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS; dev_priv->warp_ucode_size = init->warp_ucode_size; dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) * @@ -358,18 +324,12 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) DRM_ERROR("Unable to allocate memory for prim_buf\n"); return -ENOMEM; } - DRM_DEBUG("memset\n"); memset(dev_priv->prim_bufs, 0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1)); temp = init->warp_ucode_size + dev_priv->primary_size; temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; - DRM_DEBUG("temp : %x\n", temp); - DRM_DEBUG("dev->agp->base: %lx\n", dev->agp->base); - DRM_DEBUG("init->reserved_map_agpstart: %x\n", - init->reserved_map_agpstart); - DRM_DEBUG("ioremap\n"); dev_priv->ioremap = drm_ioremap(dev->agp->base + offset, temp); if(dev_priv->ioremap == NULL) { @@ -379,11 +339,9 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) init_waitqueue_head(&dev_priv->wait_queue); for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) { - DRM_DEBUG("For loop\n"); prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t), DRM_MEM_DRIVER); if(prim_buffer == NULL) return -ENOMEM; - DRM_DEBUG("memset\n"); memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t)); prim_buffer->phys_head = offset + dev->agp->base; prim_buffer->current_dma_ptr = @@ -396,17 +354,18 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init) prim_buffer->max_dwords -= 5; /* Leave room for the softrap */ prim_buffer->sec_used = 0; prim_buffer->idx = i; + prim_buffer->prim_age = i + 1; offset = offset + size_of_buf; dev_priv->prim_bufs[i] = prim_buffer; - DRM_DEBUG("Looping\n"); } dev_priv->current_prim_idx = 0; dev_priv->next_prim = dev_priv->last_prim = dev_priv->current_prim = dev_priv->prim_bufs[0]; - set_bit(0, &dev_priv->current_prim->in_use); - DRM_DEBUG("init done\n"); + dev_priv->next_prim_age = 2; + dev_priv->last_prim_age = 1; + set_bit(MGA_BUF_IN_USE, &dev_priv->current_prim->buffer_status); return 0; } @@ -420,9 +379,8 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) int i; int next_idx; PRIMLOCALS; - - DRM_DEBUG("mga_fire_primary\n"); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); + + DRM_DEBUG("%s\n", __FUNCTION__); dev_priv->last_prim = prim; /* We never check for overflow, b/c there is always room */ @@ -433,7 +391,7 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) } PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); + PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_SOFTRAP, 0); PRIMFINISH(prim); @@ -468,13 +426,13 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) for (i = 0 ; i < 4096 ; i++) mga_delay(); } } - + mga_flush_write_combine(); atomic_inc(&dev_priv->pending_bufs); - atomic_inc(&dma->total_lost); MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); prim->num_dwords = 0; + sarea_priv->last_enqueue = prim->prim_age; next_idx = prim->idx + 1; if(next_idx >= MGA_NUM_PRIM_BUFS) @@ -486,11 +444,10 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim) out_prim_wait: prim->num_dwords = 0; prim->sec_used = 0; - clear_bit(0, &prim->in_use); + clear_bit(MGA_BUF_IN_USE, &prim->buffer_status); wake_up_interruptible(&dev_priv->wait_queue); - clear_bit(0, &prim->swap_pending); - clear_bit(0, &dev_priv->dispatch_lock); - atomic_dec(&dev_priv->pending_bufs); + clear_bit(MGA_BUF_SWAP_PENDING, &prim->buffer_status); + clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); } int mga_advance_primary(drm_device_t *dev) @@ -505,27 +462,28 @@ int mga_advance_primary(drm_device_t *dev) /* This needs to reset the primary buffer if available, * we should collect stats on how many times it bites * it's tail */ + DRM_DEBUG("%s\n", __FUNCTION__); next_prim_idx = dev_priv->current_prim_idx + 1; if(next_prim_idx >= MGA_NUM_PRIM_BUFS) next_prim_idx = 0; prim_buffer = dev_priv->prim_bufs[next_prim_idx]; - atomic_set(&dev_priv->in_wait, 1); + set_bit(MGA_IN_WAIT, &dev_priv->dispatch_status); /* In use is cleared in interrupt handler */ - if(test_and_set_bit(0, &prim_buffer->in_use)) { + if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) { add_wait_queue(&dev_priv->wait_queue, &entry); + current->state = TASK_INTERRUPTIBLE; + for (;;) { - current->state = TASK_INTERRUPTIBLE; mga_dma_schedule(dev, 0); - if(!test_and_set_bit(0, &prim_buffer->in_use)) break; + if(!test_and_set_bit(MGA_BUF_IN_USE, + &prim_buffer->buffer_status)) + break; atomic_inc(&dev->total_sleeps); atomic_inc(&dma->total_missed_sched); - mga_print_all_primary(dev); - DRM_DEBUG("Schedule in advance\n"); - /* Three second delay */ - schedule_timeout(HZ*3); + schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; break; @@ -535,16 +493,27 @@ int mga_advance_primary(drm_device_t *dev) remove_wait_queue(&dev_priv->wait_queue, &entry); if(ret) return ret; } - atomic_set(&dev_priv->in_wait, 0); + clear_bit(MGA_IN_WAIT, &dev_priv->dispatch_status); + /* This primary buffer is now free to use */ prim_buffer->current_dma_ptr = prim_buffer->head; prim_buffer->num_dwords = 0; prim_buffer->sec_used = 0; - atomic_set(&prim_buffer->needs_overflow, 0); + prim_buffer->prim_age = dev_priv->next_prim_age++; + if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) { + mga_flush_queue(dev); + mga_dma_quiescent(dev); + mga_reset_freelist(dev); + prim_buffer->prim_age = (dev_priv->next_prim_age += 2); + } + + /* Reset all buffer status stuff */ + clear_bit(MGA_BUF_NEEDS_OVERFLOW, &prim_buffer->buffer_status); + clear_bit(MGA_BUF_FORCE_FIRE, &prim_buffer->buffer_status); + clear_bit(MGA_BUF_SWAP_PENDING, &prim_buffer->buffer_status); + dev_priv->current_prim = prim_buffer; dev_priv->current_prim_idx = next_prim_idx; - DRM_DEBUG("Primarys at advance\n"); - mga_print_all_primary(dev); return 0; } @@ -553,21 +522,29 @@ static inline int mga_decide_to_fire(drm_device_t *dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_device_dma_t *dma = dev->dma; - - if(atomic_read(&dev_priv->next_prim->force_fire)) - { + + DRM_DEBUG("%s\n", __FUNCTION__); + + if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) { atomic_inc(&dma->total_prio); return 1; } - if (atomic_read(&dev_priv->in_flush) && dev_priv->next_prim->num_dwords) - { + if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) && + dev_priv->next_prim->num_dwords) { + atomic_inc(&dma->total_prio); + return 1; + } + + if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) && + dev_priv->next_prim->num_dwords) { atomic_inc(&dma->total_prio); return 1; } if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS - 1) { - if(test_bit(0, &dev_priv->next_prim->swap_pending)) { + if(test_bit(MGA_BUF_SWAP_PENDING, + &dev_priv->next_prim->buffer_status)) { atomic_inc(&dma->total_dmas); return 1; } @@ -601,10 +578,11 @@ int mga_dma_schedule(drm_device_t *dev, int locked) return -EBUSY; } - DRM_DEBUG("mga_dma_schedule\n"); + DRM_DEBUG("%s\n", __FUNCTION__); - if(atomic_read(&dev_priv->in_flush) || - atomic_read(&dev_priv->in_wait)) { + if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) || + test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) || + test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) { locked = 1; } @@ -612,27 +590,25 @@ int mga_dma_schedule(drm_device_t *dev, int locked) !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { atomic_inc(&dma->total_missed_lock); clear_bit(0, &dev->dma_flag); + DRM_DEBUG("Not locked\n"); return -EBUSY; } DRM_DEBUG("I'm locked\n"); - - if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) { + if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) { /* Fire dma buffer */ if(mga_decide_to_fire(dev)) { - DRM_DEBUG("mga_fire_primary\n"); DRM_DEBUG("idx :%d\n", dev_priv->next_prim->idx); - atomic_set(&dev_priv->next_prim->force_fire, 0); - if(dev_priv->current_prim == dev_priv->next_prim && - dev_priv->next_prim->num_dwords != 0) { + clear_bit(MGA_BUF_FORCE_FIRE, + &dev_priv->next_prim->buffer_status); + if(dev_priv->current_prim == dev_priv->next_prim) { /* Schedule overflow for a later time */ - atomic_set( - &dev_priv->current_prim->needs_overflow, - 1); + set_bit(MGA_BUF_NEEDS_OVERFLOW, + &dev_priv->next_prim->buffer_status); } mga_fire_primary(dev, dev_priv->next_prim); } else { - clear_bit(0, &dev_priv->dispatch_lock); + clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); } } else { DRM_DEBUG("I can't get the dispatch lock\n"); @@ -645,17 +621,26 @@ int mga_dma_schedule(drm_device_t *dev, int locked) } } - clear_bit(0, &dev->dma_flag); - - if(atomic_read(&dev_priv->in_flush) == 1 && - dev_priv->next_prim->num_dwords == 0) { - /* Everything is on the hardware */ - DRM_DEBUG("Primarys at Flush\n"); - mga_print_all_primary(dev); - atomic_set(&dev_priv->in_flush, 0); + if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) && + dev_priv->next_prim->num_dwords == 0 && + atomic_read(&dev_priv->pending_bufs) == 0) { + /* Everything has been processed by the hardware */ + clear_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status); wake_up_interruptible(&dev_priv->flush_queue); } + if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) && + dev_priv->tail->age < dev_priv->last_prim_age) { + clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status); + DRM_DEBUG("Waking up buf queue\n"); + wake_up_interruptible(&dev_priv->buf_queue); + } else if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) { + DRM_DEBUG("Not waking buf_queue on %d %d\n", + atomic_read(&dev->total_irq), + dev_priv->last_prim_age); + } + + clear_bit(0, &dev->dma_flag); return 0; } @@ -664,33 +649,35 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs) drm_device_t *dev = (drm_device_t *)device; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_prim_buf_t *last_prim_buffer; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; - + + DRM_DEBUG("%s\n", __FUNCTION__); atomic_inc(&dev->total_irq); + if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return; MGA_WRITE(MGAREG_ICLEAR, 0x00000001); last_prim_buffer = dev_priv->last_prim; last_prim_buffer->num_dwords = 0; last_prim_buffer->sec_used = 0; - clear_bit(0, &last_prim_buffer->in_use); + dev_priv->sarea_priv->last_dispatch = + dev_priv->last_prim_age = last_prim_buffer->prim_age; + clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status); wake_up_interruptible(&dev_priv->wait_queue); - clear_bit(0, &last_prim_buffer->swap_pending); - clear_bit(0, &dev_priv->dispatch_lock); + clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status); + clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); atomic_dec(&dev_priv->pending_bufs); - dev_priv->sarea_priv->last_dispatch = status[1]; queue_task(&dev->tq, &tq_immediate); mark_bh(IMMEDIATE_BH); } static void mga_dma_task_queue(void *device) { - drm_device_t *dev = (drm_device_t *) device; - - mga_dma_schedule(dev, 0); + DRM_DEBUG("%s\n", __FUNCTION__); + mga_dma_schedule((drm_device_t *)device, 0); } int mga_dma_cleanup(drm_device_t *dev) { + DRM_DEBUG("%s\n", __FUNCTION__); + if(dev->dev_private) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; @@ -739,14 +726,13 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { drm_map_t *sarea_map = NULL; int i; + DRM_DEBUG("%s\n", __FUNCTION__); + dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); if(dev_priv == NULL) return -ENOMEM; dev->dev_private = (void *) dev_priv; - DRM_DEBUG("dev_private\n"); - memset(dev_priv, 0, sizeof(drm_mga_private_t)); - atomic_set(&dev_priv->in_flush, 0); if((init->reserved_map_idx >= dev->map_count) || (init->buffer_map_idx >= dev->map_count)) { @@ -761,7 +747,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { dev_priv->sarea_priv = (drm_mga_sarea_t *) ((u8 *)sarea_map->handle + init->sarea_priv_offset); - DRM_DEBUG("sarea_priv\n"); /* Scale primary size to the next page */ dev_priv->chipset = init->chipset; @@ -776,6 +761,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { dev_priv->mAccess = init->mAccess; init_waitqueue_head(&dev_priv->flush_queue); + init_waitqueue_head(&dev_priv->buf_queue); dev_priv->WarpPipe = -1; DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n", @@ -795,20 +781,17 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { dev_priv->WarpIndex[i].phys_addr, dev_priv->WarpIndex[i].size); - DRM_DEBUG("Doing init prim buffers\n"); if(mga_init_primary_bufs(dev, init) != 0) { DRM_ERROR("Can not initialize primary buffers\n"); mga_dma_cleanup(dev); return -ENOMEM; } - DRM_DEBUG("Done with init prim buffers\n"); dev_priv->real_status_page = mga_alloc_page(dev); if(dev_priv->real_status_page == 0UL) { mga_dma_cleanup(dev); DRM_ERROR("Can not allocate status page\n"); return -ENOMEM; } - DRM_DEBUG("Status page at %lx\n", dev_priv->real_status_page); dev_priv->status_page = ioremap_nocache(virt_to_bus((void *)dev_priv->real_status_page), @@ -820,38 +803,23 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { return -ENOMEM; } - DRM_DEBUG("Status page remapped to %p\n", dev_priv->status_page); /* Write status page when secend or softrap occurs */ MGA_WRITE(MGAREG_PRIMPTR, virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003); - - dev_priv->device = pci_find_device(0x102b, 0x0525, NULL); - if(dev_priv->device == NULL) { - DRM_ERROR("Could not find pci device for card\n"); - mga_dma_cleanup(dev); - return -EINVAL; - } - - DRM_DEBUG("dma initialization\n"); + /* Private is now filled in, initialize the hardware */ { - __volatile__ unsigned int *status = - (unsigned int *)dev_priv->status_page; PRIMLOCALS; PRIMGETPTR( dev_priv ); - - dev_priv->last_sync_tag = mga_create_sync_tag(dev); - + PRIMOUTREG(MGAREG_DMAPAD, 0); PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag); + PRIMOUTREG(MGAREG_DWGSYNC, 0x0100); PRIMOUTREG(MGAREG_SOFTRAP, 0); /* Poll for the first buffer to insure that * the status register will be correct */ - DRM_DEBUG("phys_head : %lx\n", (unsigned long)phys_head); - status[1] = 0; mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL); @@ -859,9 +827,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) | PDEA_pagpxfer_enable)); - while(MGA_READ(MGAREG_DWGSYNC) != dev_priv->last_sync_tag) ; - DRM_DEBUG("status[0] after initialization : %x\n", status[0]); - DRM_DEBUG("status[1] after initialization : %x\n", status[1]); + while(MGA_READ(MGAREG_DWGSYNC) != 0x0100) ; } if(mga_freelist_init(dev) != 0) { @@ -869,7 +835,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { mga_dma_cleanup(dev); return -ENOMEM; } - DRM_DEBUG("dma init was successful\n"); return 0; } @@ -880,6 +845,8 @@ int mga_dma_init(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_mga_init_t init; + DRM_DEBUG("%s\n", __FUNCTION__); + copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT); switch(init.func) { @@ -924,7 +891,7 @@ int mga_irq_install(drm_device_t *dev, int irq) /* Install handler */ if ((retcode = request_irq(dev->irq, mga_dma_service, - 0, + SA_SHIRQ, dev->devname, dev))) { down(&dev->struct_sem); @@ -963,7 +930,9 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_control_t ctl; copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); - + + DRM_DEBUG("%s\n", __FUNCTION__); + switch (ctl.func) { case DRM_INST_HANDLER: return mga_irq_install(dev, ctl.irq); @@ -980,30 +949,33 @@ static int mga_flush_queue(drm_device_t *dev) drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; int ret = 0; + DRM_DEBUG("%s\n", __FUNCTION__); + if(dev_priv == NULL) { return 0; } if(dev_priv->next_prim->num_dwords != 0) { - atomic_set(&dev_priv->in_flush, 1); + set_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status); current->state = TASK_INTERRUPTIBLE; add_wait_queue(&dev_priv->flush_queue, &entry); for (;;) { mga_dma_schedule(dev, 0); - if (atomic_read(&dev_priv->in_flush) == 0) + if (!test_bit(MGA_IN_FLUSH, + &dev_priv->dispatch_status)) break; atomic_inc(&dev->total_sleeps); - DRM_DEBUG("Schedule in flush_queue\n"); - schedule_timeout(HZ*3); + schedule(); if (signal_pending(current)) { ret = -EINTR; /* Can't restart */ + clear_bit(MGA_IN_FLUSH, + &dev_priv->dispatch_status); break; } } current->state = TASK_RUNNING; remove_wait_queue(&dev_priv->flush_queue, &entry); } - atomic_set(&dev_priv->in_flush, 0); return ret; } @@ -1017,6 +989,7 @@ void mga_reclaim_buffers(drm_device_t *dev, pid_t pid) if(dev->dev_private == NULL) return; if(dma->buflist == NULL) return; + DRM_DEBUG("%s\n", __FUNCTION__); mga_flush_queue(dev); for (i = 0; i < dma->buf_count; i++) { @@ -1042,6 +1015,7 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, int ret = 0; drm_lock_t lock; + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); if (lock.context == DRM_KERNEL_CONTEXT) { @@ -1080,7 +1054,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); current->state = TASK_INTERRUPTIBLE; - DRM_DEBUG("Calling lock schedule\n"); schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; @@ -1110,11 +1083,8 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_lock_t lock; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; - int i; - + + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { @@ -1123,28 +1093,17 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp, } if(lock.flags & _DRM_LOCK_FLUSH || lock.flags & _DRM_LOCK_FLUSH_ALL) { - mga_flush_queue(dev); - - if((MGA_READ(MGAREG_STATUS) & 0x00030001) == 0x00020000 && - status[1] != dev_priv->last_sync_tag) - { - DRM_DEBUG("Reseting hardware status\n"); - MGA_WRITE(MGAREG_DWGSYNC, dev_priv->last_sync_tag); - - while(MGA_READ(MGAREG_DWGSYNC) != - dev_priv->last_sync_tag) - { - for(i = 0; i < 4096; i++) mga_delay(); - } - - status[1] = - sarea_priv->last_dispatch = - dev_priv->last_sync_tag; - } else { - sarea_priv->last_dispatch = status[1]; - } + drm_mga_prim_buf_t *temp_buf = + dev_priv->prim_bufs[dev_priv->current_prim_idx]; + + if(temp_buf && temp_buf->num_dwords) { + set_bit(MGA_BUF_FORCE_FIRE, &temp_buf->buffer_status); + mga_advance_primary(dev); + mga_dma_schedule(dev, 1); + } } if(lock.flags & _DRM_LOCK_QUIESCENT) { + mga_flush_queue(dev); mga_dma_quiescent(dev); } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h index 53d3590b1..e75e91a4f 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drm.h @@ -37,6 +37,7 @@ */ #ifndef _MGA_DEFINES_ #define _MGA_DEFINES_ + #define MGA_F 0x1 /* fog */ #define MGA_A 0x2 /* alpha */ #define MGA_S 0x4 /* specular */ @@ -61,11 +62,11 @@ #define MGA_MAX_G400_PIPES 16 #define MGA_MAX_G200_PIPES 8 /* no multitex */ - #define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES #define MGA_CARD_TYPE_G200 1 #define MGA_CARD_TYPE_G400 2 + #define MGA_FRONT 0x1 #define MGA_BACK 0x2 #define MGA_DEPTH 0x4 @@ -110,19 +111,19 @@ #define MGA_UPLOAD_TEX0 0x2 #define MGA_UPLOAD_TEX1 0x4 #define MGA_UPLOAD_PIPE 0x8 -#define MGA_UPLOAD_TEX0IMAGE 0x10 -#define MGA_UPLOAD_TEX1IMAGE 0x20 +#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ +#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ #define MGA_UPLOAD_2D 0x40 #define MGA_WAIT_AGE 0x80 /* handled client-side */ #define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ #define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock quiescent */ -/* 64 buffers of 16k each, total 1 meg. +/* 32 buffers of 64k each, total 2 meg. */ -#define MGA_DMA_BUF_ORDER 14 +#define MGA_DMA_BUF_ORDER 16 #define MGA_DMA_BUF_SZ (1<<MGA_DMA_BUF_ORDER) -#define MGA_DMA_BUF_NR 63 +#define MGA_DMA_BUF_NR 31 /* Keep these small for testing. */ @@ -159,19 +160,19 @@ typedef struct drm_mga_init { int sarea_priv_offset; int primary_size; int warp_ucode_size; - int frontOffset; - int backOffset; - int depthOffset; - int textureOffset; - int textureSize; - int agpTextureOffset; - int agpTextureSize; - int cpp; - int stride; + unsigned int frontOffset; + unsigned int backOffset; + unsigned int depthOffset; + unsigned int textureOffset; + unsigned int textureSize; + unsigned int agpTextureOffset; + unsigned int agpTextureSize; + unsigned int cpp; + unsigned int stride; int sgram; int chipset; drm_mga_warp_index_t WarpIndex[MGA_MAX_WARP_PIPES]; - int mAccess; + unsigned int mAccess; } drm_mga_init_t; /* Warning: if you change the sarea structure, you must change the Xserver @@ -180,7 +181,7 @@ typedef struct drm_mga_init { typedef struct _drm_mga_tex_region { unsigned char next, prev; unsigned char in_use; - int age; + unsigned int age; } drm_mga_tex_region_t; typedef struct _drm_mga_sarea { @@ -219,9 +220,9 @@ typedef struct _drm_mga_sarea { /* Counters for aging textures and for client-side throttling. */ - int last_enqueue; /* last time a buffer was enqueued */ - int last_dispatch; /* age of the most recently dispatched buffer */ - int last_quiescent; /* */ + unsigned int last_enqueue; /* last time a buffer was enqueued */ + unsigned int last_dispatch; /* age of the most recently dispatched buffer */ + unsigned int last_quiescent; /* */ /* LRU lists for texture memory in agp space and on the card @@ -237,9 +238,9 @@ typedef struct _drm_mga_sarea { /* Device specific ioctls: */ typedef struct _drm_mga_clear { - int clear_color; - int clear_depth; - int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int flags; } drm_mga_clear_t; typedef struct _drm_mga_swap { @@ -258,4 +259,11 @@ typedef struct _drm_mga_vertex { int discard; /* client finished with buffer? */ } drm_mga_vertex_t; +typedef struct _drm_mga_indices { + int idx; /* buffer to queue */ + unsigned int start; + unsigned int end; + int discard; /* client finished with buffer? */ +} drm_mga_indices_t; + #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c index b066fe9d9..4b2c835fa 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.c @@ -111,6 +111,7 @@ static drm_ioctl_desc_t mga_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_iload, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_vertex, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_flush_ioctl, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices, 1, 0 }, }; #define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h index fe6e4ef53..f217acb97 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_drv.h @@ -32,18 +32,21 @@ #ifndef _MGA_DRV_H_ #define _MGA_DRV_H_ +#define MGA_BUF_IN_USE 0 +#define MGA_BUF_SWAP_PENDING 1 +#define MGA_BUF_FORCE_FIRE 2 +#define MGA_BUF_NEEDS_OVERFLOW 3 + typedef struct { + u32 buffer_status; unsigned int num_dwords; unsigned int max_dwords; u32 *current_dma_ptr; u32 *head; u32 phys_head; + unsigned int prim_age; int sec_used; int idx; - int swap_pending; - u32 in_use; - atomic_t force_fire; - atomic_t needs_overflow; } drm_mga_prim_buf_t; typedef struct _drm_mga_freelist { @@ -53,31 +56,33 @@ typedef struct _drm_mga_freelist { struct _drm_mga_freelist *prev; } drm_mga_freelist_t; +#define MGA_IN_DISPATCH 0 +#define MGA_IN_FLUSH 1 +#define MGA_IN_WAIT 2 +#define MGA_IN_GETBUF 3 + typedef struct _drm_mga_private { + u32 dispatch_status; + unsigned int next_prim_age; + __volatile__ unsigned int last_prim_age; int reserved_map_idx; int buffer_map_idx; drm_mga_sarea_t *sarea_priv; int primary_size; int warp_ucode_size; int chipset; - int frontOffset; - int backOffset; - int depthOffset; - int textureOffset; - int textureSize; + unsigned int frontOffset; + unsigned int backOffset; + unsigned int depthOffset; + unsigned int textureOffset; + unsigned int textureSize; int cpp; - int stride; + unsigned int stride; int sgram; int use_agp; drm_mga_warp_index_t WarpIndex[MGA_MAX_G400_PIPES]; unsigned int WarpPipe; - __volatile__ unsigned long softrap_age; - u32 dispatch_lock; - atomic_t in_flush; - atomic_t in_wait; atomic_t pending_bufs; - unsigned int last_sync_tag; - unsigned int sync_tag; void *status_page; unsigned long real_status_page; u8 *ioremap; @@ -86,12 +91,11 @@ typedef struct _drm_mga_private { drm_mga_prim_buf_t *last_prim; drm_mga_prim_buf_t *current_prim; int current_prim_idx; - struct pci_dev *device; drm_mga_freelist_t *head; drm_mga_freelist_t *tail; wait_queue_head_t flush_queue; /* Processes waiting until flush */ wait_queue_head_t wait_queue; /* Processes waiting until interrupt */ - + wait_queue_head_t buf_queue; /* Processes waiting for a free buf */ /* Some validated register values: */ u32 mAccess; @@ -126,7 +130,7 @@ extern int mga_dma_init(struct inode *inode, struct file *filp, extern int mga_dma_cleanup(drm_device_t *dev); extern int mga_flush_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); - +extern void mga_flush_write_combine(void); extern unsigned int mga_create_sync_tag(drm_device_t *dev); extern drm_buf_t *mga_freelist_get(drm_device_t *dev); extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf); @@ -156,6 +160,8 @@ extern int mga_iload(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int mga_vertex(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int mga_indices(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /* mga_context.c */ extern int mga_resctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); @@ -186,6 +192,7 @@ typedef enum { typedef struct { drm_mga_freelist_t *my_freelist; int discard; + int dispatched; } drm_mga_buf_priv_t; #define DWGREG0 0x1c00 @@ -206,15 +213,16 @@ typedef struct { #define PRIM_OVERFLOW(dev, dev_priv, length) do { \ drm_mga_prim_buf_t *tmp_buf = \ - dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ - if( tmp_buf->max_dwords - tmp_buf->num_dwords < length || \ - tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \ - atomic_set(&tmp_buf->force_fire, 1); \ - mga_advance_primary(dev); \ - mga_dma_schedule(dev, 1); \ - } else if( atomic_read(&tmp_buf->needs_overflow)) { \ - mga_advance_primary(dev); \ - mga_dma_schedule(dev, 1); \ + dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ + if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \ + &tmp_buf->buffer_status)) { \ + mga_advance_primary(dev); \ + mga_dma_schedule(dev, 1); \ + } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||\ + tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \ + set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \ + mga_advance_primary(dev); \ + mga_dma_schedule(dev, 1); \ } \ } while(0) @@ -266,6 +274,13 @@ drm_mga_prim_buf_t *tmp_buf = \ tmp_buf->sec_used++; \ } while (0) +#define AGEBUF(dev_priv, buf_priv) do { \ + drm_mga_prim_buf_t *tmp_buf = \ + dev_priv->prim_bufs[dev_priv->current_prim_idx]; \ + buf_priv->my_freelist->age = tmp_buf->prim_age; \ +} while (0) + + #define PRIMOUTREG(reg, val) do { \ tempIndex[outcount]=ADRINDEX(reg); \ dma_ptr[1+outcount] = val; \ @@ -356,28 +371,61 @@ drm_mga_prim_buf_t *tmp_buf = \ #define MGAREG_YTOP 0x1c98 #define MGAREG_ZORG 0x1c0c -#define DC_atype_rstr 0x10 -#define DC_atype_blk 0x40 #define PDEA_pagpxfer_enable 0x2 + #define WIA_wmode_suspend 0x0 #define WIA_wmode_start 0x3 #define WIA_wagp_agp 0x4 -#define DC_opcod_trap 0x4 -#define DC_arzero_enable 0x1000 -#define DC_sgnzero_enable 0x2000 -#define DC_shftzero_enable 0x4000 -#define DC_bop_SHIFT 16 -#define DC_clipdis_enable 0x80000000 -#define DC_solid_enable 0x800 -#define DC_transc_enable 0x40000000 + +#define DC_opcod_line_open 0x0 +#define DC_opcod_autoline_open 0x1 +#define DC_opcod_line_close 0x2 +#define DC_opcod_autoline_close 0x3 +#define DC_opcod_trap 0x4 +#define DC_opcod_texture_trap 0x6 #define DC_opcod_bitblt 0x8 -#define DC_atype_rpl 0x0 -#define DC_linear_xy 0x0 -#define DC_solid_disable 0x0 -#define DC_arzero_disable 0x0 -#define DC_bltmod_bfcol 0x4000000 -#define DC_pattern_disable 0x0 -#define DC_transc_disable 0x0 +#define DC_opcod_iload 0x9 +#define DC_atype_rpl 0x0 +#define DC_atype_rstr 0x10 +#define DC_atype_zi 0x30 +#define DC_atype_blk 0x40 +#define DC_atype_i 0x70 +#define DC_linear_xy 0x0 +#define DC_linear_linear 0x80 +#define DC_zmode_nozcmp 0x0 +#define DC_zmode_ze 0x200 +#define DC_zmode_zne 0x300 +#define DC_zmode_zlt 0x400 +#define DC_zmode_zlte 0x500 +#define DC_zmode_zgt 0x600 +#define DC_zmode_zgte 0x700 +#define DC_solid_disable 0x0 +#define DC_solid_enable 0x800 +#define DC_arzero_disable 0x0 +#define DC_arzero_enable 0x1000 +#define DC_sgnzero_disable 0x0 +#define DC_sgnzero_enable 0x2000 +#define DC_shftzero_disable 0x0 +#define DC_shftzero_enable 0x4000 +#define DC_bop_SHIFT 16 +#define DC_trans_SHIFT 20 +#define DC_bltmod_bmonolef 0x0 +#define DC_bltmod_bmonowf 0x8000000 +#define DC_bltmod_bplan 0x2000000 +#define DC_bltmod_bfcol 0x4000000 +#define DC_bltmod_bu32bgr 0x6000000 +#define DC_bltmod_bu32rgb 0xe000000 +#define DC_bltmod_bu24bgr 0x16000000 +#define DC_bltmod_bu24rgb 0x1e000000 +#define DC_pattern_disable 0x0 +#define DC_pattern_enable 0x20000000 +#define DC_transc_disable 0x0 +#define DC_transc_enable 0x40000000 +#define DC_clipdis_disable 0x0 +#define DC_clipdis_enable 0x80000000 + +#define SETADD_mode_vertlist 0x0 + #define MGA_CLEAR_CMD (DC_opcod_trap | DC_arzero_enable | \ DC_sgnzero_enable | DC_shftzero_enable | \ @@ -392,4 +440,8 @@ drm_mga_prim_buf_t *tmp_buf = \ DC_pattern_disable | DC_transc_disable | \ DC_clipdis_enable) \ +#define MGA_FLUSH_CMD (DC_opcod_texture_trap | (0xF << DC_trans_SHIFT) |\ + DC_arzero_enable | DC_sgnzero_enable | \ + DC_atype_i) + #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c index 0a50aa4f5..3134b7853 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/mga_state.c @@ -40,15 +40,23 @@ static void mgaEmitClipRect( drm_mga_private_t *dev_priv, drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); /* This takes 10 dwords */ PRIMGETPTR( dev_priv ); /* Force reset of dwgctl (eliminates clip disable) */ +#if 1 PRIMOUTREG( MGAREG_DMAPAD, 0 ); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 ); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 ); + PRIMOUTREG( MGAREG_DWGSYNC, 0 ); + PRIMOUTREG( MGAREG_DWGSYNC, 0 ); PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); +#else + PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); + PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000 ); + PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); + PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000 ); +#endif PRIMOUTREG( MGAREG_DMAPAD, 0 ); PRIMOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) ); @@ -63,6 +71,7 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); /* This takes a max of 15 dwords */ PRIMGETPTR( dev_priv ); @@ -80,13 +89,13 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv ) if (dev_priv->chipset == MGA_CARD_TYPE_G400) { PRIMOUTREG( MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG] ); PRIMOUTREG( MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0] ); - PRIMOUTREG( MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1] ); + PRIMOUTREG( MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1] ); PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] ); } else { PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] ); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); } PRIMADVANCE( dev_priv ); @@ -97,27 +106,28 @@ static void mgaG200EmitTex( drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->TexState[0]; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR( dev_priv ); /* This takes 20 dwords */ - PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); - PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); - PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); - PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); + PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); + PRIMOUTREG( MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); + PRIMOUTREG( MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); + PRIMOUTREG( MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); - PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); - PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); - PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); - PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); + PRIMOUTREG( MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); + PRIMOUTREG( MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); + PRIMOUTREG( MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); + PRIMOUTREG( MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); - PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); - PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); - PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); - PRIMOUTREG(0x2d00 + 24*4, regs[MGA_TEXREG_WIDTH] ); + PRIMOUTREG( MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); + PRIMOUTREG( MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); + PRIMOUTREG( MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); + PRIMOUTREG( 0x2d00 + 24*4, regs[MGA_TEXREG_WIDTH] ); - PRIMOUTREG(0x2d00 + 34*4, regs[MGA_TEXREG_HEIGHT] ); + PRIMOUTREG( 0x2d00 + 34*4, regs[MGA_TEXREG_HEIGHT] ); PRIMOUTREG( MGAREG_TEXTRANS, 0xffff ); PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff ); PRIMOUTREG( MGAREG_DMAPAD, 0 ); @@ -131,34 +141,35 @@ static void mgaG400EmitTex0( drm_mga_private_t *dev_priv ) unsigned int *regs = sarea_priv->TexState[0]; int multitex = sarea_priv->WarpPipe & MGA_T2; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); PRIMGETPTR( dev_priv ); /* This takes a max of 30 dwords */ - PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); - PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); - PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); - PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); + PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); + PRIMOUTREG( MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); + PRIMOUTREG( MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); + PRIMOUTREG( MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); - PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); - PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); - PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); - PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); + PRIMOUTREG( MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); + PRIMOUTREG( MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); + PRIMOUTREG( MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); + PRIMOUTREG( MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); - PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); - PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); - PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); - PRIMOUTREG(0x2d00 + 49*4, 0); + PRIMOUTREG( MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); + PRIMOUTREG( MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); + PRIMOUTREG( MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); + PRIMOUTREG( 0x2d00 + 49*4, 0 ); - PRIMOUTREG(0x2d00 + 57*4, 0); - PRIMOUTREG(0x2d00 + 53*4, 0); - PRIMOUTREG(0x2d00 + 61*4, 0); + PRIMOUTREG( 0x2d00 + 57*4, 0 ); + PRIMOUTREG( 0x2d00 + 53*4, 0 ); + PRIMOUTREG( 0x2d00 + 61*4, 0 ); PRIMOUTREG( MGAREG_DMAPAD, 0 ); if (!multitex) { - PRIMOUTREG(0x2d00 + 52*4, 0x40 ); - PRIMOUTREG(0x2d00 + 60*4, 0x40 ); + PRIMOUTREG( 0x2d00 + 52*4, 0x40 ); + PRIMOUTREG( 0x2d00 + 60*4, 0x40 ); PRIMOUTREG( MGAREG_DMAPAD, 0 ); PRIMOUTREG( MGAREG_DMAPAD, 0 ); } @@ -178,85 +189,127 @@ static void mgaG400EmitTex1( drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->TexState[1]; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); - PRIMGETPTR(dev_priv); + PRIMGETPTR( dev_priv ); /* This takes 25 dwords */ - PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable); - PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); - PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); - PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); - - PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); - PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); - PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); - PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); - - PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); - PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); - PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); - PRIMOUTREG(0x2d00 + 49*4, 0); - - PRIMOUTREG(0x2d00 + 57*4, 0); - PRIMOUTREG(0x2d00 + 53*4, 0); - PRIMOUTREG(0x2d00 + 61*4, 0); - PRIMOUTREG(0x2d00 + 52*4, regs[MGA_TEXREG_WIDTH] | 0x40 ); - - PRIMOUTREG(0x2d00 + 60*4, regs[MGA_TEXREG_HEIGHT] | 0x40 ); + + PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable ); + PRIMOUTREG( MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] ); + PRIMOUTREG( MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] ); + PRIMOUTREG( MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] ); + + PRIMOUTREG( MGAREG_TEXORG, regs[MGA_TEXREG_ORG] ); + PRIMOUTREG( MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] ); + PRIMOUTREG( MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] ); + PRIMOUTREG( MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] ); + + PRIMOUTREG( MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] ); + PRIMOUTREG( MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] ); + PRIMOUTREG( MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] ); + PRIMOUTREG( 0x2d00 + 49*4, 0 ); + + PRIMOUTREG( 0x2d00 + 57*4, 0 ); + PRIMOUTREG( 0x2d00 + 53*4, 0 ); + PRIMOUTREG( 0x2d00 + 61*4, 0 ); + PRIMOUTREG( 0x2d00 + 52*4, regs[MGA_TEXREG_WIDTH] | 0x40 ); + + PRIMOUTREG( 0x2d00 + 60*4, regs[MGA_TEXREG_HEIGHT] | 0x40 ); PRIMOUTREG( MGAREG_TEXTRANS, 0xffff ); PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff ); - PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); + PRIMOUTREG( MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] ); + + PRIMADVANCE( dev_priv ); +} + +/* Required when switching from multitexturing to single texturing. + */ +static void mgaG400EmitTexFlush( drm_mga_private_t *dev_priv ) +{ + PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); + + PRIMGETPTR( dev_priv ); + + /* This takes 15 dwords */ + + PRIMOUTREG( MGAREG_YDST, 0 ); + PRIMOUTREG( MGAREG_FXLEFT, 0 ); + PRIMOUTREG( MGAREG_FXRIGHT, 1 ); + PRIMOUTREG( MGAREG_DWGCTL, MGA_FLUSH_CMD ); + + PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 1 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DWGSYNC, 0x7000 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + + PRIMOUTREG( MGAREG_TEXCTL2, 0 ); + PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0 ); + PRIMOUTREG( MGAREG_TEXCTL2, 0x80 ); + PRIMOUTREG( MGAREG_LEN + MGAREG_MGA_EXEC, 0 ); PRIMADVANCE( dev_priv ); } -static void mgaG400EmitPipe(drm_mga_private_t *dev_priv ) +static void mgaG400EmitPipe( drm_mga_private_t *dev_priv ) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int pipe = sarea_priv->WarpPipe; float fParam = 12800.0f; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); - PRIMGETPTR(dev_priv); + PRIMGETPTR( dev_priv ); + + /* This takes 30 dwords */ - /* This takes 25 dwords */ - /* Establish vertex size. */ if (pipe & MGA_T2) { - PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend); - PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09); - PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000); - PRIMOUTREG(MGAREG_WFLAG, 0); + PRIMOUTREG( MGAREG_WIADDR2, WIA_wmode_suspend ); + PRIMOUTREG( MGAREG_WVRTXSZ, 0x00001e09 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 ); + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 ); + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 ); + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0x1e000000 ); } else { - PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend); - PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807); - PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000); - PRIMOUTREG(MGAREG_WFLAG, 0); + PRIMOUTREG( MGAREG_WIADDR2, WIA_wmode_suspend ); + PRIMOUTREG( MGAREG_WVRTXSZ, 0x00001807 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 ); + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 ); + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0 ); + PRIMOUTREG( MGAREG_WACCEPTSEQ, 0x18000000 ); } - PRIMOUTREG(MGAREG_WFLAG1, 0); - PRIMOUTREG(0x2d00 + 56*4, *((u32 *)(&fParam))); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_WFLAG, 0 ); + PRIMOUTREG( MGAREG_WFLAG1, 0 ); + PRIMOUTREG( 0x2d00 + 56*4, *((u32 *)(&fParam)) ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); - PRIMOUTREG(0x2d00 + 49*4, 0); /* Tex stage 0 */ - PRIMOUTREG(0x2d00 + 57*4, 0); /* Tex stage 0 */ - PRIMOUTREG(0x2d00 + 53*4, 0); /* Tex stage 1 */ - PRIMOUTREG(0x2d00 + 61*4, 0); /* Tex stage 1 */ + PRIMOUTREG( 0x2d00 + 49*4, 0 ); /* Tex stage 0 */ + PRIMOUTREG( 0x2d00 + 57*4, 0 ); /* Tex stage 0 */ + PRIMOUTREG( 0x2d00 + 53*4, 0 ); /* Tex stage 1 */ + PRIMOUTREG( 0x2d00 + 61*4, 0 ); /* Tex stage 1 */ - PRIMOUTREG(0x2d00 + 54*4, 0x40); /* Tex stage 0 : w */ - PRIMOUTREG(0x2d00 + 62*4, 0x40); /* Tex stage 0 : h */ - PRIMOUTREG(0x2d00 + 52*4, 0x40); /* Tex stage 1 : w */ - PRIMOUTREG(0x2d00 + 60*4, 0x40); /* Tex stage 1 : h */ + PRIMOUTREG( 0x2d00 + 54*4, 0x40 ); /* Tex stage 0 : w */ + PRIMOUTREG( 0x2d00 + 62*4, 0x40 ); /* Tex stage 0 : h */ + PRIMOUTREG( 0x2d00 + 52*4, 0x40 ); /* Tex stage 1 : w */ + PRIMOUTREG( 0x2d00 + 60*4, 0x40 ); /* Tex stage 1 : h */ /* Dma pading required due to hw bug */ - PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_WIADDR2, (__u32)(dev_priv->WarpIndex[pipe].phys_addr | - WIA_wmode_start | WIA_wagp_agp)); - PRIMADVANCE(dev_priv); + PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff ); + PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff ); + PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff ); + PRIMOUTREG( MGAREG_WIADDR2, (u32)(dev_priv->WarpIndex[pipe].phys_addr | + WIA_wmode_start | WIA_wagp_agp) ); + PRIMADVANCE( dev_priv ); } static void mgaG200EmitPipe( drm_mga_private_t *dev_priv ) @@ -264,40 +317,45 @@ static void mgaG200EmitPipe( drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int pipe = sarea_priv->WarpPipe; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); - PRIMGETPTR(dev_priv); + PRIMGETPTR( dev_priv ); /* This takes 15 dwords */ - PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend); - PRIMOUTREG(MGAREG_WVRTXSZ, 7); - PRIMOUTREG(MGAREG_WFLAG, 0); - PRIMOUTREG(0x2d00 + 24*4, 0); /* tex w/h */ + PRIMOUTREG( MGAREG_WIADDR, WIA_wmode_suspend ); + PRIMOUTREG( MGAREG_WVRTXSZ, 7 ); + PRIMOUTREG( MGAREG_WFLAG, 0 ); + PRIMOUTREG( 0x2d00 + 24*4, 0 ); /* tex w/h */ - PRIMOUTREG(0x2d00 + 25*4, 0x100); - PRIMOUTREG(0x2d00 + 34*4, 0); /* tex w/h */ - PRIMOUTREG(0x2d00 + 42*4, 0xFFFF); - PRIMOUTREG(0x2d00 + 60*4, 0xFFFF); + PRIMOUTREG( 0x2d00 + 25*4, 0x100 ); + PRIMOUTREG( 0x2d00 + 34*4, 0 ); /* tex w/h */ + PRIMOUTREG( 0x2d00 + 42*4, 0xFFFF ); + PRIMOUTREG( 0x2d00 + 60*4, 0xFFFF ); /* Dma pading required due to hw bug */ - PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff); - PRIMOUTREG(MGAREG_WIADDR, (__u32)(dev_priv->WarpIndex[pipe].phys_addr | - WIA_wmode_start | WIA_wagp_agp)); + PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff ); + PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff ); + PRIMOUTREG( MGAREG_DMAPAD, 0xffffffff ); + PRIMOUTREG( MGAREG_WIADDR, (u32)(dev_priv->WarpIndex[pipe].phys_addr | + WIA_wmode_start | WIA_wagp_agp) ); - PRIMADVANCE(dev_priv); + PRIMADVANCE( dev_priv ); } static void mgaEmitState( drm_mga_private_t *dev_priv ) { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; + DRM_DEBUG("%s\n", __FUNCTION__); if (dev_priv->chipset == MGA_CARD_TYPE_G400) { int multitex = sarea_priv->WarpPipe & MGA_T2; - if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { + if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { + if ((dev_priv->WarpPipe & MGA_T2) && !multitex) { + mgaG400EmitTexFlush( dev_priv ); + } mgaG400EmitPipe( dev_priv ); dev_priv->WarpPipe = sarea_priv->WarpPipe; } @@ -342,6 +400,8 @@ static int mgaVerifyContext(drm_mga_private_t *dev_priv ) drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int *regs = sarea_priv->ContextState; + DRM_DEBUG("%s\n", __FUNCTION__); + if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset && regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) { DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n", @@ -361,6 +421,8 @@ static int mgaVerifyTex(drm_mga_private_t *dev_priv, { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + DRM_DEBUG("%s\n", __FUNCTION__); + if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) { DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n", sarea_priv->TexState[unit][MGA_TEXREG_ORG], @@ -378,6 +440,8 @@ static int mgaVerifyState( drm_mga_private_t *dev_priv ) unsigned int dirty = sarea_priv->dirty; int rv = 0; + DRM_DEBUG("%s\n", __FUNCTION__); + if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; @@ -408,6 +472,8 @@ static int mgaVerifyIload( drm_mga_private_t *dev_priv, unsigned long bus_address, unsigned int dstOrg, int length ) { + DRM_DEBUG("%s\n", __FUNCTION__); + if(dstOrg < dev_priv->textureOffset || dstOrg + length > (dev_priv->textureOffset + dev_priv->textureSize)) { @@ -431,35 +497,34 @@ static void mga_dma_dispatch_tex_blit( drm_device_t *dev, int use_agp = PDEA_pagpxfer_enable | 0x00000001; u16 y2; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); y2 = length / 64; - PRIM_OVERFLOW(dev, dev_priv, 30); + PRIM_OVERFLOW( dev, dev_priv, 30 ); PRIMGETPTR( dev_priv ); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); - - PRIMOUTREG( MGAREG_DSTORG, destOrg); - PRIMOUTREG( MGAREG_MACCESS, 0x00000000); + PRIMOUTREG( MGAREG_DSTORG, destOrg ); + PRIMOUTREG( MGAREG_MACCESS, 0x00000000 ); DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp); - PRIMOUTREG( MGAREG_SRCORG, (u32) bus_address | use_agp); - PRIMOUTREG( MGAREG_AR5, 64); - - PRIMOUTREG( MGAREG_PITCH, 64); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGCTL, MGA_COPY_CMD); - - PRIMOUTREG(MGAREG_AR0, 63); - PRIMOUTREG(MGAREG_AR3, 0); - PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16)); - PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, y2); + PRIMOUTREG( MGAREG_SRCORG, (u32) bus_address | use_agp ); + PRIMOUTREG( MGAREG_AR5, 64 ); + + PRIMOUTREG( MGAREG_PITCH, 64 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DWGCTL, MGA_COPY_CMD ); + + PRIMOUTREG( MGAREG_AR0, 63 ); + PRIMOUTREG( MGAREG_AR3, 0 ); + PRIMOUTREG( MGAREG_FXBNDRY, (63 << 16) ); + PRIMOUTREG( MGAREG_YDSTLEN+MGAREG_MGA_EXEC, y2 ); - PRIMOUTREG( MGAREG_SRCORG, 0); - PRIMOUTREG( MGAREG_PITCH, dev_priv->stride / dev_priv->cpp); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); - PRIMADVANCE(dev_priv); + PRIMOUTREG( MGAREG_SRCORG, 0 ); + PRIMOUTREG( MGAREG_PITCH, dev_priv->stride / dev_priv->cpp ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMADVANCE( dev_priv ); } static void mga_dma_dispatch_vertex(drm_device_t *dev, @@ -474,33 +539,100 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, int i = 0; int primary_needed; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("dispatch vertex %d addr 0x%lx, " "length 0x%x nbox %d dirty %x\n", buf->idx, address, length, sarea_priv->nbox, sarea_priv->dirty); + DRM_DEBUG("used : %d, total : %d\n", buf->used, buf->total); + if(sarea_priv->WarpPipe & MGA_T2) { + if ((buf->used/4) % 10) + DRM_DEBUG("Multitex Buf is not aligned properly!!!\n"); + } else { + if ((buf->used/4) % 8) + DRM_DEBUG("Buf is not aligned properly!!!\n"); + } - dev_priv->last_sync_tag = mga_create_sync_tag(dev); + if (buf->used) { + /* WARNING: if you change any of the state functions verify + * these numbers (Overestimating this doesn't hurt). + */ + buf_priv->dispatched = 1; + primary_needed = (30+15+15+30+25+ + 10 + + 15 * MGA_NR_SAREA_CLIPRECTS); + PRIM_OVERFLOW(dev, dev_priv, primary_needed); + mgaEmitState( dev_priv ); + + do { + if (i < sarea_priv->nbox) { + DRM_DEBUG("idx %d Emit box %d/%d:" + "%d,%d - %d,%d\n", + buf->idx, + i, sarea_priv->nbox, + sarea_priv->boxes[i].x1, + sarea_priv->boxes[i].y1, + sarea_priv->boxes[i].x2, + sarea_priv->boxes[i].y2); + + mgaEmitClipRect( dev_priv, + &sarea_priv->boxes[i] ); + } + + PRIMGETPTR( dev_priv ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_SECADDRESS, + ((u32)address) | TT_VERTEX ); + PRIMOUTREG( MGAREG_SECEND, + (((u32)(address + length)) | use_agp) ); + PRIMADVANCE( dev_priv ); + } while (++i < sarea_priv->nbox); + } - if (buf_priv->discard) { - buf_priv->my_freelist->age = dev_priv->last_sync_tag; + if (buf_priv->discard) { + if (buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; mga_freelist_put(dev, buf); } - /* WARNING: if you change any of the state functions verify - * these numbers (Overestimating this doesn't hurt). - */ - primary_needed = (25+15+30+25+ - 10 + - 15 * MGA_NR_SAREA_CLIPRECTS); +} - PRIM_OVERFLOW(dev, dev_priv, primary_needed); - mgaEmitState( dev_priv ); +static void mga_dma_dispatch_indices(drm_device_t *dev, + drm_buf_t *buf, + unsigned int start, + unsigned int end) +{ + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_buf_priv_t *buf_priv = buf->dev_private; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + unsigned int address = (unsigned int)buf->bus_address; + int use_agp = PDEA_pagpxfer_enable; + int i = 0; + int primary_needed; + PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); + + DRM_DEBUG("dispatch indices %d addr 0x%x, " + "start 0x%x end 0x%x nbox %d dirty %x\n", + buf->idx, address, start, end, + sarea_priv->nbox, sarea_priv->dirty); + + if (start != end) { + /* WARNING: if you change any of the state functions verify + * these numbers (Overestimating this doesn't hurt). + */ + buf_priv->dispatched = 1; + primary_needed = (25+15+30+25+ + 10 + + 15 * MGA_NR_SAREA_CLIPRECTS); + PRIM_OVERFLOW( dev, dev_priv, primary_needed ); + mgaEmitState( dev_priv ); - if (buf->used) { do { if (i < sarea_priv->nbox) { DRM_DEBUG("idx %d Emit box %d/%d:" @@ -515,25 +647,23 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, mgaEmitClipRect( dev_priv, &sarea_priv->boxes[i] ); } - - PRIMGETPTR(dev_priv); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_SECADDRESS, - ((__u32)address) | TT_VERTEX); - PRIMOUTREG( MGAREG_SECEND, - (((__u32)(address + length)) | - use_agp)); + + PRIMGETPTR( dev_priv ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_SETUPADDRESS, + ((address + start) | + SETADD_mode_vertlist) ); + PRIMOUTREG( MGAREG_SETUPEND, + ((address + end) | use_agp) ); PRIMADVANCE( dev_priv ); } while (++i < sarea_priv->nbox); } - - PRIMGETPTR( dev_priv ); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag); - PRIMADVANCE( dev_priv ); + if (buf_priv->discard) { + if (buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); + } } @@ -550,6 +680,7 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, int i; int primary_needed; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); if ( dev_priv->sgram ) cmd = MGA_CLEAR_CMD | DC_atype_blk; @@ -557,10 +688,9 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, cmd = MGA_CLEAR_CMD | DC_atype_rstr; primary_needed = nbox * 70; - if(primary_needed == 0) primary_needed = 70; - PRIM_OVERFLOW(dev, dev_priv, primary_needed); + if (primary_needed == 0) primary_needed = 70; + PRIM_OVERFLOW( dev, dev_priv, primary_needed ); PRIMGETPTR( dev_priv ); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); for (i = 0 ; i < nbox ; i++) { unsigned int height = pbox[i].y2 - pbox[i].y1; @@ -571,55 +701,50 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, if ( flags & MGA_FRONT ) { DRM_DEBUG("clear front\n"); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height); - PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1); - - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_FCOL, clear_color); - PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset); - PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_YDSTLEN, (pbox[i].y1<<16)|height); + PRIMOUTREG( MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1); + + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_FCOL, clear_color ); + PRIMOUTREG( MGAREG_DSTORG, dev_priv->frontOffset ); + PRIMOUTREG( MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd ); } if ( flags & MGA_BACK ) { DRM_DEBUG("clear back\n"); PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height); - PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1); + PRIMOUTREG( MGAREG_YDSTLEN, (pbox[i].y1<<16)|height ); + PRIMOUTREG( MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1 ); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_FCOL, clear_color); - PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset); - PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_FCOL, clear_color ); + PRIMOUTREG( MGAREG_DSTORG, dev_priv->backOffset ); + PRIMOUTREG( MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd ); } if ( flags & MGA_DEPTH ) { DRM_DEBUG("clear depth\n"); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height); - PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1); - - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_FCOL, clear_zval); - PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset); - PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_YDSTLEN, (pbox[i].y1<<16)|height ); + PRIMOUTREG( MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1 ); + + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_FCOL, clear_zval ); + PRIMOUTREG( MGAREG_DSTORG, dev_priv->depthOffset ); + PRIMOUTREG( MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd ); } } /* Force reset of DWGCTL */ - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); - - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); - PRIMADVANCE(dev_priv); + PRIMADVANCE( dev_priv ); } static void mga_dma_dispatch_swap( drm_device_t *dev ) @@ -632,23 +757,22 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) int i; int primary_needed; PRIMLOCALS; + DRM_DEBUG("%s\n", __FUNCTION__); primary_needed = nbox * 5; primary_needed += 60; PRIM_OVERFLOW(dev, dev_priv, primary_needed); PRIMGETPTR( dev_priv ); - dev_priv->last_sync_tag = mga_create_sync_tag(dev); + PRIMOUTREG( MGAREG_DSTORG, dev_priv->frontOffset ); + PRIMOUTREG( MGAREG_MACCESS, dev_priv->mAccess ); + PRIMOUTREG( MGAREG_SRCORG, dev_priv->backOffset ); + PRIMOUTREG( MGAREG_AR5, dev_priv->stride/2 ); - PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset); - PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess); - PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset); - PRIMOUTREG(MGAREG_AR5, dev_priv->stride/2); - - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DWGCTL, MGA_COPY_CMD ); for (i = 0 ; i < nbox; i++) { unsigned int h = pbox[i].y2 - pbox[i].y1; @@ -658,23 +782,19 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2); - PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1); - PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1); - PRIMOUTREG(MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16)); - PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h); + PRIMOUTREG( MGAREG_AR0, start + pbox[i].x2 - 1 ); + PRIMOUTREG( MGAREG_AR3, start + pbox[i].x1 ); + PRIMOUTREG( MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16) ); + PRIMOUTREG( MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h ); } /* Force reset of DWGCTL */ - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_DMAPAD, 0 ); + PRIMOUTREG( MGAREG_SRCORG, 0 ); PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] ); - PRIMOUTREG( MGAREG_SRCORG, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DMAPAD, 0); - PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag); - PRIMADVANCE(dev_priv); + PRIMADVANCE( dev_priv ); } int mga_clear_bufs(struct inode *inode, struct file *filp, @@ -684,12 +804,11 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_mga_clear_t clear; copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear), -EFAULT); + DRM_DEBUG("%s\n", __FUNCTION__); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_clear_bufs called without lock held\n"); @@ -706,8 +825,8 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, clear.clear_color, clear.clear_depth ); PRIMUPDATE(dev_priv); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -718,8 +837,7 @@ int mga_swap_bufs(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; + DRM_DEBUG("%s\n", __FUNCTION__); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("mga_swap_bufs called without lock held\n"); @@ -734,10 +852,9 @@ int mga_swap_bufs(struct inode *inode, struct file *filp, dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX; mga_dma_dispatch_swap( dev ); PRIMUPDATE(dev_priv); - set_bit(0, &dev_priv->current_prim->swap_pending); - dev_priv->current_prim->swap_pending = 1; + set_bit(MGA_BUF_SWAP_PENDING, &dev_priv->current_prim->buffer_status); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -749,12 +866,11 @@ int mga_iload(struct inode *inode, struct file *filp, drm_device_dma_t *dma = dev->dma; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_iload_t iload; unsigned long bus_address; + DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("Starting Iload\n"); copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload), @@ -783,11 +899,11 @@ int mga_iload(struct inode *inode, struct file *filp, mga_dma_dispatch_tex_blit(dev, bus_address, iload.length, iload.destOrg); - buf_priv->my_freelist->age = dev_priv->last_sync_tag; + AGEBUF(dev_priv, buf_priv); buf_priv->discard = 1; mga_freelist_put(dev, buf); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } @@ -797,13 +913,11 @@ int mga_vertex(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_vertex_t vertex; + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex), -EFAULT); @@ -822,25 +936,75 @@ int mga_vertex(struct inode *inode, struct file *filp, buf_priv->discard = vertex.discard; if (!mgaVerifyState(dev_priv)) { - if (vertex.discard) { - buf_priv->my_freelist->age = dev_priv->last_sync_tag; - mga_freelist_put(dev, buf); + if (vertex.discard) { + if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); } + DRM_DEBUG("bad state\n"); return -EINVAL; } mga_dma_dispatch_vertex(dev, buf); PRIMUPDATE(dev_priv); + mga_flush_write_combine(); mga_dma_schedule(dev, 1); - sarea_priv->last_dispatch = status[1]; return 0; } + +int mga_indices(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + drm_mga_buf_priv_t *buf_priv; + drm_mga_indices_t indices; + DRM_DEBUG("%s\n", __FUNCTION__); + + copy_from_user_ret(&indices, (drm_mga_indices_t *)arg, sizeof(indices), + -EFAULT); + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("mga_indices called without lock held\n"); + return -EINVAL; + } + + DRM_DEBUG("mga_indices\n"); + + buf = dma->buflist[ indices.idx ]; + buf_priv = buf->dev_private; + + buf_priv->discard = indices.discard; + + if (!mgaVerifyState(dev_priv)) { + if (indices.discard) { + if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv); + buf_priv->dispatched = 0; + mga_freelist_put(dev, buf); + } + return -EINVAL; + } + + mga_dma_dispatch_indices(dev, buf, indices.start, indices.end); + + PRIMUPDATE(dev_priv); + mga_flush_write_combine(); + mga_dma_schedule(dev, 1); + return 0; +} + + + static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) { int i; drm_buf_t *buf; + DRM_DEBUG("%s\n", __FUNCTION__); for (i = d->granted_count; i < d->request_count; i++) { buf = mga_freelist_get(dev); @@ -865,12 +1029,9 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; - drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - __volatile__ unsigned int *status = - (__volatile__ unsigned int *)dev_priv->status_page; int retcode = 0; drm_dma_t d; + DRM_DEBUG("%s\n", __FUNCTION__); copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); DRM_DEBUG("%d %d: %d send, %d req\n", @@ -906,6 +1067,5 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("%d returning, granted = %d\n", current->pid, d.granted_count); copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); - sarea_priv->last_dispatch = status[1]; return retcode; } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c index bb8e18e0e..ba6dee00d 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c @@ -400,6 +400,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len, pgprot & _PAGE_GLOBAL ? 'g' : 'l' ); #endif DRM_PROC_PRINT("\n"); +#if 0 for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) { pgd = pgd_offset(vma->vm_mm, i); pmd = pmd_offset(pgd, i); @@ -420,6 +421,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len, DRM_PROC_PRINT(" 0x%08lx\n", i); } } +#endif } return len; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_bufs.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_bufs.c new file mode 100644 index 000000000..bad6c5714 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_bufs.c @@ -0,0 +1,309 @@ +/* r128_bufs.c -- IOCTLs to manage buffers -*- linux-c -*- + * Created: Wed Apr 12 16:19:08 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * Rickard E. (Rik) Faith <faith@precisioninsight.com> + * Jeff Hartmann <jhartmann@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include "r128_drv.h" +#include "linux/un.h" + + +#ifdef DRM_AGP +int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_device_dma_t *dma = dev->dma; + drm_buf_desc_t request; + drm_buf_entry_t *entry; + drm_buf_t *buf; + unsigned long offset; + unsigned long agp_offset; + int count; + int order; + int size; + int alignment; + int page_order; + int total; + int byte_count; + int i; + + if (!dma) return -EINVAL; + + copy_from_user_ret(&request, + (drm_buf_desc_t *)arg, + sizeof(request), + -EFAULT); + + count = request.count; + order = drm_order(request.size); + size = 1 << order; + + alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size; + page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; + total = PAGE_SIZE << page_order; + + byte_count = 0; + agp_offset = dev->agp->base + request.agp_start; + + DRM_DEBUG("count: %d\n", count); + DRM_DEBUG("order: %d\n", order); + DRM_DEBUG("size: %d\n", size); + DRM_DEBUG("agp_offset: %ld\n", agp_offset); + DRM_DEBUG("alignment: %d\n", alignment); + DRM_DEBUG("page_order: %d\n", page_order); + DRM_DEBUG("total: %d\n", total); + + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; + if (dev->queue_count) return -EBUSY; /* Not while in use */ + + spin_lock(&dev->count_lock); + if (dev->buf_use) { + spin_unlock(&dev->count_lock); + return -EBUSY; + } + atomic_inc(&dev->buf_alloc); + spin_unlock(&dev->count_lock); + + down(&dev->struct_sem); + entry = &dma->bufs[order]; + if (entry->buf_count) { + up(&dev->struct_sem); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; /* May only call once for each order */ + } + + entry->buflist = drm_alloc(count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + if (!entry->buflist) { + up(&dev->struct_sem); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + memset(entry->buflist, 0, count * sizeof(*entry->buflist)); + + entry->buf_size = size; + entry->page_order = page_order; + offset = 0; + + for (offset = 0; + entry->buf_count < count; + offset += alignment, ++entry->buf_count) { + buf = &entry->buflist[entry->buf_count]; + buf->idx = dma->buf_count + entry->buf_count; + buf->total = alignment; + buf->order = order; + buf->used = 0; + buf->offset = (dma->byte_count + offset); + buf->address = (void *)(agp_offset + offset); + buf->next = NULL; + buf->waiting = 0; + buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); + buf->pid = 0; + + buf->dev_priv_size = sizeof(drm_r128_buf_priv_t); + buf->dev_private = drm_alloc(sizeof(drm_r128_buf_priv_t), + DRM_MEM_BUFS); + memset(buf->dev_private, 0, buf->dev_priv_size); + +#if DRM_DMA_HISTOGRAM + buf->time_queued = 0; + buf->time_dispatched = 0; + buf->time_completed = 0; + buf->time_freed = 0; +#endif + + byte_count += PAGE_SIZE << page_order; + + DRM_DEBUG("buffer %d @ %p\n", + entry->buf_count, buf->address); + } + + DRM_DEBUG("byte_count: %d\n", byte_count); + + dma->buflist = drm_realloc(dma->buflist, + dma->buf_count * sizeof(*dma->buflist), + (dma->buf_count + entry->buf_count) + * sizeof(*dma->buflist), + DRM_MEM_BUFS); + for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++) + dma->buflist[i] = &entry->buflist[i - dma->buf_count]; + + dma->buf_count += entry->buf_count; + dma->byte_count += byte_count; + + drm_freelist_create(&entry->freelist, entry->buf_count); + for (i = 0; i < entry->buf_count; i++) { + drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]); + } + + up(&dev->struct_sem); + + request.count = entry->buf_count; + request.size = size; + + copy_to_user_ret((drm_buf_desc_t *)arg, + &request, + sizeof(request), + -EFAULT); + + dma->flags = _DRM_DMA_USE_AGP; + + atomic_dec(&dev->buf_alloc); + return 0; +} +#endif + +int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_buf_desc_t request; + + if (!dev_priv || dev_priv->is_pci) return -EINVAL; + + copy_from_user_ret(&request, + (drm_buf_desc_t *)arg, + sizeof(request), + -EFAULT); + +#ifdef DRM_AGP + if (request.flags & _DRM_AGP_BUFFER) + return r128_addbufs_agp(inode, filp, cmd, arg); + else +#endif + return -EINVAL; +} + +int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + const int zero = 0; + unsigned long virtual; + unsigned long address; + drm_buf_map_t request; + int i; + + if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL; + + DRM_DEBUG("\n"); + + spin_lock(&dev->count_lock); + if (atomic_read(&dev->buf_alloc)) { + spin_unlock(&dev->count_lock); + return -EBUSY; + } + ++dev->buf_use; /* Can't allocate more after this call */ + spin_unlock(&dev->count_lock); + + copy_from_user_ret(&request, + (drm_buf_map_t *)arg, + sizeof(request), + -EFAULT); + + if (request.count >= dma->buf_count) { + if (dma->flags & _DRM_DMA_USE_AGP) { + drm_map_t *map; + + map = dev_priv->agp_vertbufs; + if (!map) { + retcode = -EINVAL; + goto done; + } + + down(¤t->mm->mmap_sem); + virtual = do_mmap(filp, 0, map->size, + PROT_READ|PROT_WRITE, + MAP_SHARED, + (unsigned long)map->offset); + up(¤t->mm->mmap_sem); + } else { + down(¤t->mm->mmap_sem); + virtual = do_mmap(filp, 0, dma->byte_count, + PROT_READ|PROT_WRITE, MAP_SHARED, 0); + up(¤t->mm->mmap_sem); + } + if (virtual > -1024UL) { + /* Real error */ + retcode = (signed long)virtual; + goto done; + } + request.virtual = (void *)virtual; + + for (i = 0; i < dma->buf_count; i++) { + if (copy_to_user(&request.list[i].idx, + &dma->buflist[i]->idx, + sizeof(request.list[0].idx))) { + retcode = -EFAULT; + goto done; + } + if (copy_to_user(&request.list[i].total, + &dma->buflist[i]->total, + sizeof(request.list[0].total))) { + retcode = -EFAULT; + goto done; + } + if (copy_to_user(&request.list[i].used, + &zero, + sizeof(zero))) { + retcode = -EFAULT; + goto done; + } + address = virtual + dma->buflist[i]->offset; + if (copy_to_user(&request.list[i].address, + &address, + sizeof(address))) { + retcode = -EFAULT; + goto done; + } + } + } + done: + request.count = dma->buf_count; + DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); + + copy_to_user_ret((drm_buf_map_t *)arg, + &request, + sizeof(request), + -EFAULT); + + return retcode; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_context.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_context.c new file mode 100644 index 000000000..d288fd284 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_context.c @@ -0,0 +1,214 @@ +/* r128_context.c -- IOCTLs for r128 contexts -*- linux-c -*- + * Created: Mon Dec 13 09:51:35 1999 by faith@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * Author: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * + * $XFree86$ + * + */ + +#include <linux/sched.h> + +#define __NO_VERSION__ +#include "drmP.h" +#include "r128_drv.h" + +extern drm_ctx_t r128_res_ctx; + +static int r128_alloc_queue(drm_device_t *dev) +{ +#if 0 + static int context = 0; +#endif + + return drm_ctxbitmap_next(dev); +} + +int r128_context_switch(drm_device_t *dev, int old, int new) +{ + char buf[64]; + + atomic_inc(&dev->total_ctx); + + if (test_and_set_bit(0, &dev->context_flag)) { + DRM_ERROR("Reentering -- FIXME\n"); + return -EBUSY; + } + +#if DRM_DMA_HISTOGRAM + dev->ctx_start = get_cycles(); +#endif + + DRM_DEBUG("Context switch from %d to %d\n", old, new); + + if (new == dev->last_context) { + clear_bit(0, &dev->context_flag); + return 0; + } + + if (drm_flags & DRM_FLAG_NOCTX) { + r128_context_switch_complete(dev, new); + } else { + sprintf(buf, "C %d %d\n", old, new); + drm_write_string(dev, buf); + } + + return 0; +} + +int r128_context_switch_complete(drm_device_t *dev, int new) +{ + dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ + dev->last_switch = jiffies; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("Lock isn't held after context switch\n"); + } + + /* If a context switch is ever initiated + when the kernel holds the lock, release + that lock here. */ +#if DRM_DMA_HISTOGRAM + atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles() + - dev->ctx_start)]); + +#endif + clear_bit(0, &dev->context_flag); + wake_up(&dev->context_wait); + + return 0; +} + + +int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_res_t res; + drm_ctx_t ctx; + int i; + + DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); + copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (res.count >= DRM_RESERVED_CONTEXTS) { + memset(&ctx, 0, sizeof(ctx)); + for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { + ctx.handle = i; + copy_to_user_ret(&res.contexts[i], + &i, + sizeof(i), + -EFAULT); + } + } + res.count = DRM_RESERVED_CONTEXTS; + copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + return 0; +} + + +int r128_addctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + if ((ctx.handle = r128_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) { + /* Skip kernel's context and get a new one. */ + ctx.handle = r128_alloc_queue(dev); + } + DRM_DEBUG("%d\n", ctx.handle); + if (ctx.handle == -1) { + DRM_DEBUG("Not enough free contexts.\n"); + /* Should this return -EBUSY instead? */ + return -ENOMEM; + } + + copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + return 0; +} + +int r128_modctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + if (ctx.flags==_DRM_CONTEXT_PRESERVED) + r128_res_ctx.handle=ctx.handle; + return 0; +} + +int r128_getctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + /* This is 0, because we don't hanlde any context flags */ + ctx.flags = 0; + copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + return 0; +} + +int r128_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + return r128_context_switch(dev, dev->last_context, ctx.handle); +} + +int r128_newctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + r128_context_switch_complete(dev, ctx.handle); + + return 0; +} + +int r128_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + drm_ctxbitmap_free(dev, ctx.handle); + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c new file mode 100644 index 000000000..860c41885 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c @@ -0,0 +1,908 @@ +/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include "r128_drv.h" + +#include <linux/interrupt.h> /* For task queue support */ +#include <linux/delay.h> + + + +#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size) + +#define DO_REMAPFREE(_m) \ + do { \ + if ((_m)->handle && (_m)->size) \ + drm_ioremapfree((_m)->handle, (_m)->size); \ + } while (0) + +#define DO_FIND_MAP(_m, _o) \ + do { \ + int _i; \ + for (_i = 0; _i < dev->map_count; _i++) { \ + if (dev->maplist[_i]->offset == _o) { \ + _m = dev->maplist[_i]; \ + break; \ + } \ + } \ + } while (0) + + +#define R128_MAX_VBUF_AGE 0x10000000 +#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0 + +int R128_READ_PLL(drm_device_t *dev, int addr) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + + R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); + return R128_READ(R128_CLOCK_CNTL_DATA); +} + +static void r128_flush_write_combine(void) +{ + int xchangeDummy; + + __asm__ volatile("push %%eax ;" + "xchg %%eax, %0 ;" + "pop %%eax" : : "m" (xchangeDummy)); + __asm__ volatile("push %%eax ;" + "push %%ebx ;" + "push %%ecx ;" + "push %%edx ;" + "movl $0,%%eax ;" + "cpuid ;" + "pop %%edx ;" + "pop %%ecx ;" + "pop %%ebx ;" + "pop %%eax" : /* no outputs */ : /* no inputs */ ); +} + +static int r128_do_cleanup_cce(drm_device_t *dev) +{ + if (dev->dev_private) { + drm_r128_private_t *dev_priv = dev->dev_private; + + if (!dev_priv->is_pci) { + DO_REMAPFREE(dev_priv->agp_ring); + DO_REMAPFREE(dev_priv->agp_read_ptr); + DO_REMAPFREE(dev_priv->agp_vertbufs); + DO_REMAPFREE(dev_priv->agp_indbufs); + DO_REMAPFREE(dev_priv->agp_textures); + } + + drm_free(dev->dev_private, sizeof(drm_r128_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + } + + return 0; +} + +static int r128_do_init_cce(drm_device_t *dev, drm_r128_init_t *init) +{ + drm_r128_private_t *dev_priv; + int i; + + dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) return -ENOMEM; + dev->dev_private = (void *)dev_priv; + + memset(dev_priv, 0, sizeof(drm_r128_private_t)); + + dev_priv->is_pci = init->is_pci; + + dev_priv->usec_timeout = init->usec_timeout; + if (dev_priv->usec_timeout < 1 || + dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return -EINVAL; + } + + dev_priv->cce_mode = init->cce_mode; + dev_priv->cce_fifo_size = init->cce_fifo_size; + dev_priv->cce_is_bm_mode = + ((init->cce_mode == R128_PM4_192BM) || + (init->cce_mode == R128_PM4_128BM_64INDBM) || + (init->cce_mode == R128_PM4_64BM_128INDBM) || + (init->cce_mode == R128_PM4_64BM_64VCBM_64INDBM)); + dev_priv->cce_secure = init->cce_secure; + + if (dev_priv->cce_is_bm_mode && dev_priv->is_pci) { + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return -EINVAL; + } + + for (i = 0; i < dev->map_count; i++) { + if (dev->maplist[i]->type == _DRM_SHM) { + dev_priv->sarea = dev->maplist[i]; + break; + } + } + + DO_FIND_MAP(dev_priv->fb, init->fb_offset); + if (!dev_priv->is_pci) { + DO_FIND_MAP(dev_priv->agp_ring, init->agp_ring_offset); + DO_FIND_MAP(dev_priv->agp_read_ptr, init->agp_read_ptr_offset); + DO_FIND_MAP(dev_priv->agp_vertbufs, init->agp_vertbufs_offset); + DO_FIND_MAP(dev_priv->agp_indbufs, init->agp_indbufs_offset); + DO_FIND_MAP(dev_priv->agp_textures, init->agp_textures_offset); + } + DO_FIND_MAP(dev_priv->mmio, init->mmio_offset); + + dev_priv->sarea_priv = + (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + if (!dev_priv->is_pci) { + DO_REMAP(dev_priv->agp_ring); + DO_REMAP(dev_priv->agp_read_ptr); + DO_REMAP(dev_priv->agp_vertbufs); +#if 0 + DO_REMAP(dev_priv->agp_indirectbufs); + DO_REMAP(dev_priv->agp_textures); +#endif + + dev_priv->ring_size = init->ring_size; + dev_priv->ring_sizel2qw = drm_order(init->ring_size/8); + dev_priv->ring_entries = init->ring_size/sizeof(u32); + dev_priv->ring_read_ptr = ((__volatile__ u32 *) + dev_priv->agp_read_ptr->handle); + dev_priv->ring_start = (u32 *)dev_priv->agp_ring->handle; + dev_priv->ring_end = ((u32 *)dev_priv->agp_ring->handle + + dev_priv->ring_entries); + } + + dev_priv->submit_age = 0; + R128_WRITE(R128_VB_AGE_REG, dev_priv->submit_age); + + return 0; +} + +int r128_init_cce(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_init_t init; + + copy_from_user_ret(&init, (drm_r128_init_t *)arg, sizeof(init), + -EFAULT); + + switch (init.func) { + case R128_INIT_CCE: + return r128_do_init_cce(dev, &init); + case R128_CLEANUP_CCE: + return r128_do_cleanup_cce(dev); + } + + return -EINVAL; +} + +static void r128_mark_vertbufs_done(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[i]; + drm_r128_buf_priv_t *buf_priv = buf->dev_private; + buf_priv->age = 0; + } +} + +static int r128_do_pixcache_flush(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp; + int i; + + tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL; + R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp); + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) + return 0; + udelay(1); + } + + return -EBUSY; +} + +static int r128_do_wait_for_fifo(drm_device_t *dev, int entries) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; + if (slots >= entries) return 0; + udelay(1); + } + return -EBUSY; +} + +static int r128_do_wait_for_idle(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i, ret; + + if (!(ret = r128_do_wait_for_fifo(dev, 64))) return ret; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) { + (void)r128_do_pixcache_flush(dev); + return 0; + } + udelay(1); + } + return -EBUSY; +} + +int r128_do_engine_reset(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 clock_cntl_index, mclk_cntl, gen_reset_cntl; + + (void)r128_do_pixcache_flush(dev); + + clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX); + mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL); + + R128_WRITE_PLL(R128_MCLK_CNTL, + mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CPP); + + gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL); + + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); + (void)R128_READ(R128_GEN_RESET_CNTL); + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); + (void)R128_READ(R128_GEN_RESET_CNTL); + + R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl); + R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index); + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl); + + /* For CCE ring buffer only */ + if (dev_priv->cce_is_bm_mode) { + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); + R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); + *dev_priv->ring_read_ptr = 0; + dev_priv->sarea_priv->ring_write = 0; + } + + /* Reset the CCE mode */ + (void)r128_do_wait_for_idle(dev); + R128_WRITE(R128_PM4_BUFFER_CNTL, + dev_priv->cce_mode | dev_priv->ring_sizel2qw); + (void)R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */ + R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); + + r128_mark_vertbufs_done(dev); + return 0; +} + +int r128_eng_reset(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_eng_reset called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_engine_reset(dev); +} + +static int r128_do_engine_flush(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp; + + tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR); + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp | R128_PM4_BUFFER_DL_DONE); + + return 0; +} + +int r128_eng_flush(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_eng_flush called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_engine_flush(dev); +} + +static int r128_do_cce_wait_for_fifo(drm_device_t *dev, int entries) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots = R128_READ(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK; + if (slots >= entries) return 0; + udelay(1); + } + return -EBUSY; +} + +int r128_do_cce_wait_for_idle(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + if (dev_priv->cce_is_bm_mode) { + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (*dev_priv->ring_read_ptr == dev_priv->sarea_priv->ring_write) { + int pm4stat = R128_READ(R128_PM4_STAT); + if ((pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size && + !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + return r128_do_pixcache_flush(dev); + } + } + udelay(1); + } + return -EBUSY; + } else { + int ret = r128_do_cce_wait_for_fifo(dev, dev_priv->cce_fifo_size); + if (ret < 0) return ret; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int pm4stat = R128_READ(R128_PM4_STAT); + if (!(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + return r128_do_pixcache_flush(dev); + } + udelay(1); + } + return -EBUSY; + } +} + +int r128_cce_idle(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_wait_idle called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_cce_wait_for_idle(dev); +} + +static int r128_submit_packets_ring_secure(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int write = dev_priv->sarea_priv->ring_write; + int *write_ptr = dev_priv->ring_start + write; + int c = *count; + u32 tmp = 0; + int psize = 0; + int writing = 1; + int timeout; + + while (c > 0) { + tmp = *commands++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + write++; + *write_ptr++ = tmp; + } + if (write >= dev_priv->ring_entries) { + write = 0; + write_ptr = dev_priv->ring_start; + } + timeout = 0; + while (write == *dev_priv->ring_read_ptr) { + (void)R128_READ(R128_PM4_BUFFER_DL_RPTR); + if (timeout++ >= dev_priv->usec_timeout) + return -EBUSY; + udelay(1); + } + c--; + } + + if (write < 32) + memcpy(dev_priv->ring_end, + dev_priv->ring_start, + write * sizeof(u32)); + + /* Make sure WC cache has been flushed */ + r128_flush_write_combine(); + + dev_priv->sarea_priv->ring_write = write; + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write); + + *count = 0; + + return 0; +} + +static int r128_submit_packets_pio_secure(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp = 0; + int psize = 0; + int writing = 1; + int addr = R128_PM4_FIFO_DATA_EVEN; + int ret; + + while (*count > 0) { + tmp = *commands++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) + return ret; + R128_WRITE(addr, tmp); + addr ^= 0x0004; + } + + *count -= 1; + } + + if (addr == R128_PM4_FIFO_DATA_ODD) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) return ret; + R128_WRITE(addr, R128_CCE_PACKET2); + } + + return 0; +} + +static int r128_submit_packets_ring(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int write = dev_priv->sarea_priv->ring_write; + int *write_ptr = dev_priv->ring_start + write; + int c = *count; + int timeout; + + while (c > 0) { + write++; + *write_ptr++ = *commands++; + if (write >= dev_priv->ring_entries) { + write = 0; + write_ptr = dev_priv->ring_start; + } + timeout = 0; + while (write == *dev_priv->ring_read_ptr) { + (void)R128_READ(R128_PM4_BUFFER_DL_RPTR); + if (timeout++ >= dev_priv->usec_timeout) + return -EBUSY; + udelay(1); + } + c--; + } + + if (write < 32) + memcpy(dev_priv->ring_end, + dev_priv->ring_start, + write * sizeof(u32)); + + /* Make sure WC cache has been flushed */ + r128_flush_write_combine(); + + dev_priv->sarea_priv->ring_write = write; + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write); + + *count = 0; + + return 0; +} + +static int r128_submit_packets_pio(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int ret; + + while (*count > 1) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret; + R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++); + R128_WRITE(R128_PM4_FIFO_DATA_ODD, *commands++); + *count -= 2; + } + + if (*count) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret; + R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++); + R128_WRITE(R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2); + *count = 0; + } + + return 0; +} + +static int r128_do_submit_packets(drm_device_t *dev, u32 *buffer, int count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int c = count; + int ret; + + if (dev_priv->cce_is_bm_mode) { + int left = 0; + + if (c >= dev_priv->ring_entries) { + c = dev_priv->ring_entries-1; + left = count - c; + } + + /* Since this is only used by the kernel we can use the + insecure ring buffer submit packet routine */ + ret = r128_submit_packets_ring(dev, buffer, &c); + + c += left; + } else { + /* Since this is only used by the kernel we can use the + insecure PIO submit packet routine */ + ret = r128_submit_packets_pio(dev, buffer, &c); + } + + if (ret < 0) return ret; + else return c; +} + +int r128_submit_pkt(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_packet_t packet; + u32 *buffer; + int c; + int size; + int ret = 0; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_submit_pkt called without holding the lock\n"); + return -EINVAL; + } + + copy_from_user_ret(&packet, (drm_r128_packet_t *)arg, sizeof(packet), + -EFAULT); + + c = packet.count; + size = c * sizeof(*buffer); + + if (dev_priv->cce_is_bm_mode) { + int left = 0; + + if (c >= dev_priv->ring_entries) { + c = dev_priv->ring_entries-1; + size = c * sizeof(*buffer); + left = packet.count - c; + } + + if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; + copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + + if (dev_priv->cce_secure) + ret = r128_submit_packets_ring_secure(dev, buffer, &c); + else + ret = r128_submit_packets_ring(dev, buffer, &c); + + c += left; + } else { + if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; + copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + + if (dev_priv->cce_secure) + ret = r128_submit_packets_pio_secure(dev, buffer, &c); + else + ret = r128_submit_packets_pio(dev, buffer, &c); + } + + kfree(buffer); + + packet.count = c; + copy_to_user_ret((drm_r128_packet_t *)arg, &packet, sizeof(packet), + -EFAULT); + + if (ret) return ret; + else if (c > 0) return -EAGAIN; + + return 0; +} + +static int r128_send_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) +{ + drm_device_dma_t *dma = dev->dma; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, ret; + u32 cce[2]; + + /* Make sure we have valid data */ + for (i = 0; i < v->send_count; i++) { + int idx = v->send_indices[i]; + + if (idx < 0 || idx >= dma->buf_count) { + DRM_ERROR("Index %d (of %d max)\n", + idx, dma->buf_count - 1); + return -EINVAL; + } + buf = dma->buflist[idx]; + if (buf->pid != current->pid) { + DRM_ERROR("Process %d using buffer owned by %d\n", + current->pid, buf->pid); + return -EINVAL; + } + if (buf->pending) { + DRM_ERROR("Sending pending buffer:" + " buffer %d, offset %d\n", + v->send_indices[i], i); + return -EINVAL; + } + } + + /* Wait for idle, if we've wrapped to make sure that all pending + buffers have been processed */ + if (dev_priv->submit_age == R128_MAX_VBUF_AGE) { + if ((ret = r128_do_cce_wait_for_idle(dev)) < 0) return ret; + dev_priv->submit_age = 0; + r128_mark_vertbufs_done(dev); + } + + /* Make sure WC cache has been flushed (if in PIO mode) */ + if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine(); + + /* FIXME: Add support for sending vertex buffer to the CCE here + instead of in client code. The v->prim holds the primitive + type that should be drawn. Loop over the list buffers in + send_indices[] and submit a packet for each VB. + + This will require us to loop over the clip rects here as + well, which implies that we extend the kernel driver to allow + cliprects to be stored here. Note that the cliprects could + possibly come from the X server instead of the client, but + this will require additional changes to the DRI to allow for + this optimization. */ + + /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */ + cce[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0); + cce[1] = dev_priv->submit_age; + if ((ret = r128_do_submit_packets(dev, cce, 2)) < 0) { + /* Until we add support for sending VBs to the CCE in + this routine, we can recover from this error. After + we add that support, we won't be able to easily + recover, so we will probably have to implement + another mechanism for handling timeouts from packets + submitted directly by the kernel. */ + return ret; + } + + /* Now that the submit packet request has succeeded, we can mark + the buffers as pending */ + for (i = 0; i < v->send_count; i++) { + buf = dma->buflist[v->send_indices[i]]; + buf->pending = 1; + + buf_priv = buf->dev_private; + buf_priv->age = dev_priv->submit_age; + } + + dev_priv->submit_age++; + + return 0; +} + +static drm_buf_t *r128_freelist_get(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, t; + + /* FIXME: Optimize -- use freelist code */ + + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if (buf->pid == 0) return buf; + } + + for (t = 0; t < dev_priv->usec_timeout; t++) { + u32 done_age = R128_READ(R128_VB_AGE_REG); + + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if (buf->pending && buf_priv->age <= done_age) { + /* The buffer has been processed, so it + can now be used */ + buf->pending = 0; + return buf; + } + } + udelay(1); + } + + return NULL; +} + + +static int r128_get_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) +{ + drm_buf_t *buf; + int i; + + for (i = v->granted_count; i < v->request_count; i++) { + buf = r128_freelist_get(dev); + if (!buf) break; + buf->pid = current->pid; + copy_to_user_ret(&v->request_indices[i], + &buf->idx, + sizeof(buf->idx), + -EFAULT); + copy_to_user_ret(&v->request_sizes[i], + &buf->total, + sizeof(buf->total), + -EFAULT); + ++v->granted_count; + } + return 0; +} + +int r128_vertex_buf(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + drm_r128_vertex_t v; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_vertex_buf called without holding the lock\n"); + return -EINVAL; + } + + if (!dev_priv || dev_priv->is_pci) { + DRM_ERROR("r128_vertex_buf called with a PCI card\n"); + return -EINVAL; + } + + copy_from_user_ret(&v, (drm_r128_vertex_t *)arg, sizeof(v), -EFAULT); + DRM_DEBUG("%d: %d send, %d req\n", + current->pid, v.send_count, v.request_count); + + if (v.send_count < 0 || v.send_count > dma->buf_count) { + DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n", + current->pid, v.send_count, dma->buf_count); + return -EINVAL; + } + if (v.request_count < 0 || v.request_count > dma->buf_count) { + DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", + current->pid, v.request_count, dma->buf_count); + return -EINVAL; + } + + if (v.send_count) { + retcode = r128_send_vertbufs(dev, &v); + } + + v.granted_count = 0; + + if (!retcode && v.request_count) { + retcode = r128_get_vertbufs(dev, &v); + } + + DRM_DEBUG("%d returning, granted = %d\n", + current->pid, v.granted_count); + copy_to_user_ret((drm_r128_vertex_t *)arg, &v, sizeof(v), -EFAULT); + + return retcode; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drm.h new file mode 100644 index 000000000..fa90d72db --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drm.h @@ -0,0 +1,111 @@ +/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + */ + +#ifndef _R128_DRM_H_ +#define _R128_DRM_H_ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmR128.h) + */ +typedef struct drm_r128_init { + enum { + R128_INIT_CCE = 0x01, + R128_CLEANUP_CCE = 0x02 + } func; + int sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_fifo_size; + int cce_secure; + int ring_size; + int usec_timeout; + + int fb_offset; + int agp_ring_offset; + int agp_read_ptr_offset; + int agp_vertbufs_offset; + int agp_indbufs_offset; + int agp_textures_offset; + int mmio_offset; +} drm_r128_init_t; + +typedef struct drm_r128_packet { + unsigned long *buffer; + int count; + int flags; +} drm_r128_packet_t; + +typedef enum drm_r128_prim { + _DRM_R128_PRIM_NONE = 0x0001, + _DRM_R128_PRIM_POINT = 0x0002, + _DRM_R128_PRIM_LINE = 0x0004, + _DRM_R128_PRIM_POLY_LINE = 0x0008, + _DRM_R128_PRIM_TRI_LIST = 0x0010, + _DRM_R128_PRIM_TRI_FAN = 0x0020, + _DRM_R128_PRIM_TRI_STRIP = 0x0040, + _DRM_R128_PRIM_TRI_TYPE2 = 0x0080 +} drm_r128_prim_t; + +typedef struct drm_r128_vertex { + /* Indices here refer to the offset into + buflist in drm_buf_get_t. */ + int send_count; /* Number of buffers to send */ + int *send_indices; /* List of handles to buffers */ + int *send_sizes; /* Lengths of data to send */ + drm_r128_prim_t prim; /* Primitive type */ + int request_count; /* Number of buffers requested */ + int *request_indices; /* Buffer information */ + int *request_sizes; + int granted_count; /* Number of buffers granted */ +} drm_r128_vertex_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (r128_sarea.h) + */ +#define R128_LOCAL_TEX_HEAP 0 +#define R128_AGP_TEX_HEAP 1 +#define R128_NR_TEX_HEAPS 2 +#define R128_NR_TEX_REGIONS 64 +#define R128_LOG_TEX_GRANULARITY 16 + +typedef struct drm_tex_region { + unsigned char next, prev; + unsigned char in_use; + int age; +} drm_tex_region_t; + +typedef struct drm_r128_sarea { + drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; + int tex_age[R128_NR_TEX_HEAPS]; + int ctx_owner; + int ring_write; +} drm_r128_sarea_t; + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c new file mode 100644 index 000000000..45ade1def --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c @@ -0,0 +1,737 @@ +/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- + * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define EXPORT_SYMTAB +#include "drmP.h" +#include "r128_drv.h" +EXPORT_SYMBOL(r128_init); +EXPORT_SYMBOL(r128_cleanup); + +#define R128_NAME "r128" +#define R128_DESC "r128" +#define R128_DATE "20000422" +#define R128_MAJOR 0 +#define R128_MINOR 0 +#define R128_PATCHLEVEL 5 + +static drm_device_t r128_device; +drm_ctx_t r128_res_ctx; + +static struct file_operations r128_fops = { + open: r128_open, + flush: drm_flush, + release: r128_release, + ioctl: r128_ioctl, + mmap: drm_mmap, + read: drm_read, + fasync: drm_fasync, + poll: drm_poll, +}; + +static struct miscdevice r128_misc = { + minor: MISC_DYNAMIC_MINOR, + name: R128_NAME, + fops: &r128_fops, +}; + +static drm_ioctl_desc_t r128_ioctls[] = { + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, + +#ifdef DRM_AGP + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, +#endif + + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_submit_pkt, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCEIDL)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 }, +}; +#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) + +#ifdef MODULE +int init_module(void); +void cleanup_module(void); +static char *r128 = NULL; + +MODULE_AUTHOR("Precision Insight, Inc., Cedar Park, Texas."); +MODULE_DESCRIPTION("r128"); +MODULE_PARM(r128, "s"); + +/* init_module is called when insmod is used to load the module */ + +int init_module(void) +{ + return r128_init(); +} + +/* cleanup_module is called when rmmod is used to unload the module */ + +void cleanup_module(void) +{ + r128_cleanup(); +} +#endif + +#ifndef MODULE +/* r128_setup is called by the kernel to parse command-line options passed + * via the boot-loader (e.g., LILO). It calls the insmod option routine, + * drm_parse_drm. + * + * This is not currently supported, since it requires changes to + * linux/init/main.c. */ + + +void __init r128_setup(char *str, int *ints) +{ + if (ints[0] != 0) { + DRM_ERROR("Illegal command line format, ignored\n"); + return; + } + drm_parse_options(str); +} +#endif + +static int r128_setup(drm_device_t *dev) +{ + int i; + + atomic_set(&dev->ioctl_count, 0); + atomic_set(&dev->vma_count, 0); + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + + drm_dma_setup(dev); + + atomic_set(&dev->total_open, 0); + atomic_set(&dev->total_close, 0); + atomic_set(&dev->total_ioctl, 0); + atomic_set(&dev->total_irq, 0); + atomic_set(&dev->total_ctx, 0); + atomic_set(&dev->total_locks, 0); + atomic_set(&dev->total_unlocks, 0); + atomic_set(&dev->total_contends, 0); + atomic_set(&dev->total_sleeps, 0); + + for (i = 0; i < DRM_HASH_SIZE; i++) { + dev->magiclist[i].head = NULL; + dev->magiclist[i].tail = NULL; + } + dev->maplist = NULL; + dev->map_count = 0; + dev->vmalist = NULL; + dev->lock.hw_lock = NULL; + init_waitqueue_head(&dev->lock.lock_queue); + dev->queue_count = 0; + dev->queue_reserved = 0; + dev->queue_slots = 0; + dev->queuelist = NULL; + dev->irq = 0; + dev->context_flag = 0; + dev->interrupt_flag = 0; + dev->dma_flag = 0; + dev->last_context = 0; + dev->last_switch = 0; + dev->last_checked = 0; + init_timer(&dev->timer); + init_waitqueue_head(&dev->context_wait); + + dev->ctx_start = 0; + dev->lck_start = 0; + + dev->buf_rp = dev->buf; + dev->buf_wp = dev->buf; + dev->buf_end = dev->buf + DRM_BSZ; + dev->buf_async = NULL; + init_waitqueue_head(&dev->buf_readers); + init_waitqueue_head(&dev->buf_writers); + + r128_res_ctx.handle=-1; + + DRM_DEBUG("\n"); + + /* The kernel's context could be created here, but is now created + in drm_dma_enqueue. This is more resource-efficient for + hardware that does not do DMA, but may mean that + drm_select_queue fails between the time the interrupt is + initialized and the time the queues are initialized. */ + + return 0; +} + + +static int r128_takedown(drm_device_t *dev) +{ + int i; + drm_magic_entry_t *pt, *next; + drm_map_t *map; + drm_vma_entry_t *vma, *vma_next; + + DRM_DEBUG("\n"); + + down(&dev->struct_sem); + del_timer(&dev->timer); + + if (dev->devname) { + drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); + dev->devname = NULL; + } + + if (dev->unique) { + drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); + dev->unique = NULL; + dev->unique_len = 0; + } + /* Clear pid list */ + for (i = 0; i < DRM_HASH_SIZE; i++) { + for (pt = dev->magiclist[i].head; pt; pt = next) { + next = pt->next; + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + } + dev->magiclist[i].head = dev->magiclist[i].tail = NULL; + } + +#ifdef DRM_AGP + /* Clear AGP information */ + if (dev->agp) { + drm_agp_mem_t *entry; + drm_agp_mem_t *nexte; + + /* Remove AGP resources, but leave dev->agp + intact until r128_cleanup is called. */ + for (entry = dev->agp->memory; entry; entry = nexte) { + nexte = entry->next; + if (entry->bound) drm_unbind_agp(entry->memory); + drm_free_agp(entry->memory, entry->pages); + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + } + dev->agp->memory = NULL; + + if (dev->agp->acquired && drm_agp.release) + (*drm_agp.release)(); + + dev->agp->acquired = 0; + dev->agp->enabled = 0; + } +#endif + + /* Clear vma list (only built for debugging) */ + if (dev->vmalist) { + for (vma = dev->vmalist; vma; vma = vma_next) { + vma_next = vma->next; + drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); + } + dev->vmalist = NULL; + } + + /* Clear map area and mtrr information */ + if (dev->maplist) { + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#ifdef CONFIG_MTRR + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } +#endif + drm_ioremapfree(map->handle, map->size); + break; + case _DRM_SHM: + drm_free_pages((unsigned long)map->handle, + drm_order(map->size) + - PAGE_SHIFT, + DRM_MEM_SAREA); + break; + case _DRM_AGP: + /* Do nothing here, because this is all + handled in the AGP/GART driver. */ + break; + } + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + drm_free(dev->maplist, + dev->map_count * sizeof(*dev->maplist), + DRM_MEM_MAPS); + dev->maplist = NULL; + dev->map_count = 0; + } + + drm_dma_takedown(dev); + + dev->queue_count = 0; + if (dev->lock.hw_lock) { + dev->lock.hw_lock = NULL; /* SHM removed */ + dev->lock.pid = 0; + wake_up_interruptible(&dev->lock.lock_queue); + } + up(&dev->struct_sem); + + return 0; +} + +/* r128_init is called via init_module at module load time, or via + * linux/init/main.c (this is not currently supported). */ + +int r128_init(void) +{ + int retcode; + drm_device_t *dev = &r128_device; + + DRM_DEBUG("\n"); + + memset((void *)dev, 0, sizeof(*dev)); + dev->count_lock = SPIN_LOCK_UNLOCKED; + sema_init(&dev->struct_sem, 1); + +#ifdef MODULE + drm_parse_options(r128); +#endif + + if ((retcode = misc_register(&r128_misc))) { + DRM_ERROR("Cannot register \"%s\"\n", R128_NAME); + return retcode; + } + dev->device = MKDEV(MISC_MAJOR, r128_misc.minor); + dev->name = R128_NAME; + + drm_mem_init(); + drm_proc_init(dev); + +#ifdef DRM_AGP + dev->agp = drm_agp_init(); + +#ifdef CONFIG_MTRR + dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size*1024*1024, + MTRR_TYPE_WRCOMB, + 1); +#endif +#endif + + if((retcode = drm_ctxbitmap_init(dev))) { + DRM_ERROR("Cannot allocate memory for context bitmap.\n"); + drm_proc_cleanup(); + misc_deregister(&r128_misc); + r128_takedown(dev); + return retcode; + } + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + R128_NAME, + R128_MAJOR, + R128_MINOR, + R128_PATCHLEVEL, + R128_DATE, + r128_misc.minor); + + return 0; +} + +/* r128_cleanup is called via cleanup_module at module unload time. */ + +void r128_cleanup(void) +{ + drm_device_t *dev = &r128_device; + + DRM_DEBUG("\n"); + + drm_proc_cleanup(); + if (misc_deregister(&r128_misc)) { + DRM_ERROR("Cannot unload module\n"); + } else { + DRM_INFO("Module unloaded\n"); + } + drm_ctxbitmap_cleanup(dev); + r128_takedown(dev); +#ifdef DRM_AGP + if (dev->agp) { + /* FIXME -- free other information, too */ + drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); + dev->agp = NULL; + } +#endif +} + +int r128_version(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_version_t version; + int len; + + copy_from_user_ret(&version, + (drm_version_t *)arg, + sizeof(version), + -EFAULT); + +#define DRM_COPY(name,value) \ + len = strlen(value); \ + if (len > name##_len) len = name##_len; \ + name##_len = strlen(value); \ + if (len && name) { \ + copy_to_user_ret(name, value, len, -EFAULT); \ + } + + version.version_major = R128_MAJOR; + version.version_minor = R128_MINOR; + version.version_patchlevel = R128_PATCHLEVEL; + + DRM_COPY(version.name, R128_NAME); + DRM_COPY(version.date, R128_DATE); + DRM_COPY(version.desc, R128_DESC); + + copy_to_user_ret((drm_version_t *)arg, + &version, + sizeof(version), + -EFAULT); + return 0; +} + +int r128_open(struct inode *inode, struct file *filp) +{ + drm_device_t *dev = &r128_device; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_open_helper(inode, filp, dev))) { + MOD_INC_USE_COUNT; + atomic_inc(&dev->total_open); + spin_lock(&dev->count_lock); + if (!dev->open_count++) { + spin_unlock(&dev->count_lock); + return r128_setup(dev); + } + spin_unlock(&dev->count_lock); + } + return retcode; +} + +int r128_release(struct inode *inode, struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_release(inode, filp))) { + MOD_DEC_USE_COUNT; + atomic_inc(&dev->total_close); + spin_lock(&dev->count_lock); + if (!--dev->open_count) { + if (atomic_read(&dev->ioctl_count) || dev->blocked) { + DRM_ERROR("Device busy: %d %d\n", + atomic_read(&dev->ioctl_count), + dev->blocked); + spin_unlock(&dev->count_lock); + return -EBUSY; + } + spin_unlock(&dev->count_lock); + return r128_takedown(dev); + } + spin_unlock(&dev->count_lock); + } + return retcode; +} + +/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */ + +int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int nr = DRM_IOCTL_NR(cmd); + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode = 0; + drm_ioctl_desc_t *ioctl; + drm_ioctl_t *func; + + atomic_inc(&dev->ioctl_count); + atomic_inc(&dev->total_ioctl); + ++priv->ioctl_count; + + DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n", + current->pid, cmd, nr, dev->device, priv->authenticated); + + if (nr >= R128_IOCTL_COUNT) { + retcode = -EINVAL; + } else { + ioctl = &r128_ioctls[nr]; + func = ioctl->func; + + if (!func) { + DRM_DEBUG("no function\n"); + retcode = -EINVAL; + } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) + || (ioctl->auth_needed && !priv->authenticated)) { + retcode = -EACCES; + } else { + retcode = (func)(inode, filp, cmd, arg); + } + } + + atomic_dec(&dev->ioctl_count); + return retcode; +} + +int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + DECLARE_WAITQUEUE(entry, current); + int ret = 0; + drm_lock_t lock; +#if DRM_DMA_HISTOGRAM + cycles_t start; + + dev->lck_start = start = get_cycles(); +#endif + + copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", + lock.context, current->pid, dev->lock.hw_lock->lock, + lock.flags); + +#if 0 + /* dev->queue_count == 0 right now for + r128. FIXME? */ + if (lock.context < 0 || lock.context >= dev->queue_count) + return -EINVAL; +#endif + + if (!ret) { +#if 0 + if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) + != lock.context) { + long j = jiffies - dev->lock.lock_time; + + if (lock.context == r128_res_ctx.handle && + j >= 0 && j < DRM_LOCK_SLICE) { + /* Can't take lock if we just had it and + there is contention. */ + DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n", + lock.context, current->pid, j, + dev->lock.lock_time, jiffies); + current->state = TASK_INTERRUPTIBLE; + current->policy |= SCHED_YIELD; + schedule_timeout(DRM_LOCK_SLICE-j); + DRM_DEBUG("jiffies=%d\n", jiffies); + } + } +#endif + add_wait_queue(&dev->lock.lock_queue, &entry); + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + ret = -EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + lock.context)) { + dev->lock.pid = current->pid; + dev->lock.lock_time = jiffies; + atomic_inc(&dev->total_locks); + break; /* Got lock */ + } + + /* Contention */ + atomic_inc(&dev->total_sleeps); + current->state = TASK_INTERRUPTIBLE; +#if 1 + current->policy |= SCHED_YIELD; +#endif + schedule(); + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(&dev->lock.lock_queue, &entry); + } + +#if 0 + if (!ret && dev->last_context != lock.context && + lock.context != r128_res_ctx.handle && + dev->last_context != r128_res_ctx.handle) { + add_wait_queue(&dev->context_wait, &entry); + current->state = TASK_INTERRUPTIBLE; + /* PRE: dev->last_context != lock.context */ + r128_context_switch(dev, dev->last_context, lock.context); + /* POST: we will wait for the context + switch and will dispatch on a later call + when dev->last_context == lock.context + NOTE WE HOLD THE LOCK THROUGHOUT THIS + TIME! */ + current->policy |= SCHED_YIELD; + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&dev->context_wait, &entry); + if (signal_pending(current)) { + ret = -EINTR; + } else if (dev->last_context != lock.context) { + DRM_ERROR("Context mismatch: %d %d\n", + dev->last_context, lock.context); + } + } +#endif + + if (!ret) { + if (lock.flags & _DRM_LOCK_READY) { + /* Wait for space in DMA/FIFO */ + } + if (lock.flags & _DRM_LOCK_QUIESCENT) { + /* Make hardware quiescent */ +#if 0 + r128_quiescent(dev); +#endif + } + } + +#if 0 + DRM_ERROR("pid = %5d, old counter = %5ld\n", + current->pid, current->counter); +#endif + if (lock.context != r128_res_ctx.handle) { + current->counter = 5; + current->priority = DEF_PRIORITY/4; + } +#if 0 + while (current->counter > 25) + current->counter >>= 1; /* decrease time slice */ + DRM_ERROR("pid = %5d, new counter = %5ld\n", + current->pid, current->counter); +#endif + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); + +#if DRM_DMA_HISTOGRAM + atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]); +#endif + + return ret; +} + + +int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_lock_t lock; + + copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d frees lock (%d holds)\n", + lock.context, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + atomic_inc(&dev->total_unlocks); + if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) + atomic_inc(&dev->total_contends); + drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); + /* FIXME: Try to send data to card here */ + if (!dev->context_flag) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("\n"); + } + } + +#if 0 + current->policy |= SCHED_YIELD; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1000); +#endif + + if (lock.context != r128_res_ctx.handle) { + current->counter = 5; + current->priority = DEF_PRIORITY; + } +#if 0 + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(10); +#endif + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.h new file mode 100644 index 000000000..3b888c493 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.h @@ -0,0 +1,226 @@ +/* r128_drv.h -- Private header for r128 driver -*- linux-c -*- + * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#ifndef _R128_DRV_H_ +#define _R128_DRV_H_ + +typedef struct drm_r128_private { + int is_pci; + + int cce_mode; + int cce_fifo_size; + int cce_is_bm_mode; + int cce_secure; + + drm_r128_sarea_t *sarea_priv; + + __volatile__ u32 *ring_read_ptr; + + u32 *ring_start; + u32 *ring_end; + int ring_size; + int ring_sizel2qw; + int ring_entries; + + int submit_age; + + int usec_timeout; + + drm_map_t *sarea; + drm_map_t *fb; + drm_map_t *agp_ring; + drm_map_t *agp_read_ptr; + drm_map_t *agp_vertbufs; + drm_map_t *agp_indbufs; + drm_map_t *agp_textures; + drm_map_t *mmio; +} drm_r128_private_t; + +typedef struct drm_r128_buf_priv { + u32 age; +} drm_r128_buf_priv_t; + + /* r128_drv.c */ +extern int r128_init(void); +extern void r128_cleanup(void); +extern int r128_version(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_open(struct inode *inode, struct file *filp); +extern int r128_release(struct inode *inode, struct file *filp); +extern int r128_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_lock(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_unlock(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + /* r128_dma.c */ +extern int r128_init_cce(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_eng_reset(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_eng_flush(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_submit_pkt(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_cce_idle(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_vertex_buf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + /* r128_bufs.c */ +extern int r128_addbufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_mapbufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + /* r128_context.c */ +extern int r128_resctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_addctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_modctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_getctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_switchctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_newctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int r128_rmctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +extern int r128_context_switch(drm_device_t *dev, int old, int new); +extern int r128_context_switch_complete(drm_device_t *dev, int new); + + +/* Register definitions, register access macros and drmAddMap constants + * for Rage 128 kernel driver. + */ + +#define R128_PC_NGUI_CTLSTAT 0x0184 +# define R128_PC_FLUSH_ALL 0x00ff +# define R128_PC_BUSY (1 << 31) + +#define R128_CLOCK_CNTL_INDEX 0x0008 +#define R128_CLOCK_CNTL_DATA 0x000c +# define R128_PLL_WR_EN (1 << 7) + +#define R128_MCLK_CNTL 0x000f +# define R128_FORCE_GCP (1 << 16) +# define R128_FORCE_PIPE3D_CPP (1 << 17) + +#define R128_GEN_RESET_CNTL 0x00f0 +# define R128_SOFT_RESET_GUI (1 << 0) + +#define R128_PM4_BUFFER_CNTL 0x0704 +# define R128_PM4_NONPM4 (0 << 28) +# define R128_PM4_192PIO (1 << 28) +# define R128_PM4_192BM (2 << 28) +# define R128_PM4_128PIO_64INDBM (3 << 28) +# define R128_PM4_128BM_64INDBM (4 << 28) +# define R128_PM4_64PIO_128INDBM (5 << 28) +# define R128_PM4_64BM_128INDBM (6 << 28) +# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) +# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) +# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) + + +#define R128_PM4_BUFFER_DL_RPTR 0x0710 +#define R128_PM4_BUFFER_DL_WPTR 0x0714 +# define R128_PM4_BUFFER_DL_DONE (1 << 31) + +#define R128_PM4_VC_FPU_SETUP 0x071c + +#define R128_PM4_STAT 0x07b8 +# define R128_PM4_FIFOCNT_MASK 0x0fff +# define R128_PM4_BUSY (1 << 16) +# define R128_PM4_GUI_ACTIVE (1 << 31) + +#define R128_PM4_BUFFER_ADDR 0x07f0 +#define R128_PM4_MICRO_CNTL 0x07fc +# define R128_PM4_MICRO_FREERUN (1 << 30) + +#define R128_PM4_FIFO_DATA_EVEN 0x1000 +#define R128_PM4_FIFO_DATA_ODD 0x1004 + +#define R128_GUI_SCRATCH_REG0 0x15e0 +#define R128_GUI_SCRATCH_REG1 0x15e4 +#define R128_GUI_SCRATCH_REG2 0x15e8 +#define R128_GUI_SCRATCH_REG3 0x15ec +#define R128_GUI_SCRATCH_REG4 0x15f0 +#define R128_GUI_SCRATCH_REG5 0x15f4 + +#define R128_GUI_STAT 0x1740 +# define R128_GUI_FIFOCNT_MASK 0x0fff +# define R128_GUI_ACTIVE (1 << 31) + + +/* CCE command packets */ +#define R128_CCE_PACKET0 0x00000000 +#define R128_CCE_PACKET1 0x40000000 +#define R128_CCE_PACKET2 0x80000000 +# define R128_CCE_PACKET_MASK 0xC0000000 +# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000 +# define R128_CCE_PACKET0_REG_MASK 0x000007ff +# define R128_CCE_PACKET1_REG0_MASK 0x000007ff +# define R128_CCE_PACKET1_REG1_MASK 0x003ff800 + + +#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */ + + +#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle)) +#define R128_ADDR(reg) (R128_BASE(reg) + reg) + +#define R128_DEREF(reg) *(__volatile__ int *)R128_ADDR(reg) +#define R128_READ(reg) R128_DEREF(reg) +#define R128_WRITE(reg,val) do { R128_DEREF(reg) = val; } while (0) + +#define R128_DEREF8(reg) *(__volatile__ char *)R128_ADDR(reg) +#define R128_READ8(reg) R128_DEREF8(reg) +#define R128_WRITE8(reg,val) do { R128_DEREF8(reg) = val; } while (0) + +#define R128_WRITE_PLL(addr,val) \ +do { \ + R128_WRITE8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x1f) | R128_PLL_WR_EN); \ + R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \ +} while (0) + +extern int R128_READ_PLL(drm_device_t *dev, int addr); + +#define R128CCE0(p,r,n) ((p) | ((n) << 16) | ((r) >> 2)) +#define R128CCE1(p,r1,r2) ((p) | (((r2) >> 2) << 11) | ((r1) >> 2)) +#define R128CCE2(p) ((p)) +#define R128CCE3(p,n) ((p) | ((n) << 16)) + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c index 534723a50..0b2b00e0a 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/vm.c @@ -247,6 +247,18 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) /* Check for valid size. */ if (map->size != vma->vm_end - vma->vm_start) return -EINVAL; + if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { + vma->vm_flags &= VM_MAYWRITE; +#if defined(__i386__) + pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; +#else + /* Ye gads this is ugly. With more thought + we could move this up higher and use + `protection_map' instead. */ + vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( + __pte(pgprot_val(vma->vm_page_prot))))); +#endif + } switch (map->type) { case _DRM_FRAME_BUFFER: @@ -266,6 +278,10 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; + DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," + " offset = 0x%lx\n", + map->type, + vma->vm_start, vma->vm_end, VM_OFFSET(vma)); vma->vm_ops = &drm_vm_ops; break; case _DRM_SHM: @@ -278,19 +294,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) return -EINVAL; /* This should never happen. */ } vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ - if (map->flags & _DRM_READ_ONLY) { -#if defined(__i386__) - pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; -#else - /* Ye gads this is ugly. With more thought - we could move this up higher and use - `protection_map' instead. */ - vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( - __pte(pgprot_val(vma->vm_page_prot))))); -#endif - } - #if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */ /* In Linux 2.2.3 and above, this is handled in do_mmap() in mm/mmap.c. */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmI810.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmI810.c new file mode 100644 index 000000000..b2489eeed --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmI810.c @@ -0,0 +1,87 @@ +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# include "xf86Priv.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/stat.h> +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include <sys/sysmacros.h> /* for makedev() */ +#include "xf86drm.h" +#include "xf86drmI810.h" +#include "drm.h" + +Bool drmI810CleanupDma(int driSubFD) +{ + drm_i810_init_t init; + + memset(&init, 0, sizeof(drm_i810_init_t)); + init.func = I810_CLEANUP_DMA; + + if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) { + return FALSE; + } + + return TRUE; +} + +Bool drmI810InitDma(int driSubFD, drmI810Init *info) +{ + drm_i810_init_t init; + + memset(&init, 0, sizeof(drm_i810_init_t)); + + init.func = I810_INIT_DMA; + init.ring_map_idx = info->ring_map_idx; + init.buffer_map_idx = info->buffer_map_idx; + init.ring_start = info->start; + init.ring_end = info->end; + init.ring_size = info->size; + init.sarea_priv_offset = info->sarea_off; + init.front_offset = info->front_offset; + init.back_offset = info->back_offset; + init.depth_offset = info->depth_offset; + init.w = info->w; + init.h = info->h; + init.pitch = info->pitch; + init.pitch_bits = info->pitch_bits; + + if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) { + return FALSE; + } + return TRUE; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c new file mode 100644 index 000000000..99f267f3d --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c @@ -0,0 +1,199 @@ +/* xf86drmR128.c -- User-level interface to Rage 128 DRM device + * Created: Sun Apr 9 18:13:54 2000 by kevin@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * Author: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# include "xf86Priv.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/stat.h> +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include <sys/sysmacros.h> /* for makedev() */ +#include "xf86drm.h" +#include "xf86drmR128.h" +#include "drm.h" + +int drmR128InitCCE(int fd, drmR128Init *info) +{ + drm_r128_init_t init; + + memset(&init, 0, sizeof(drm_r128_init_t)); + + init.func = R128_INIT_CCE; + init.sarea_priv_offset = info->sarea_priv_offset; + init.is_pci = info->is_pci; + init.cce_mode = info->cce_mode; + init.cce_fifo_size = info->cce_fifo_size; + init.cce_secure = info->cce_secure; + init.ring_size = info->ring_size; + init.usec_timeout = info->usec_timeout; + + init.fb_offset = info->fb_offset; + init.agp_ring_offset = info->agp_ring_offset; + init.agp_read_ptr_offset = info->agp_read_ptr_offset; + init.agp_vertbufs_offset = info->agp_vertbufs_offset; + init.agp_indbufs_offset = info->agp_indbufs_offset; + init.agp_textures_offset = info->agp_textures_offset; + init.mmio_offset = info->mmio_offset; + + if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno; + + return 0; +} + +int drmR128CleanupCCE(int fd) +{ + drm_r128_init_t init; + + memset(&init, 0, sizeof(drm_r128_init_t)); + + init.func = R128_CLEANUP_CCE; + + if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno; + + return 0; +} + +int drmR128EngineReset(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_RESET, NULL)) return -errno; + + return 0; +} + +int drmR128EngineFlush(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_FLUSH, NULL)) return -errno; + + return 0; +} + +int drmR128CCEWaitForIdle(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_CCEIDL, NULL)) return -errno; + + return 0; +} + +int drmR128SubmitPackets(int fd, CARD32 *buffer, int *count, int flags) +{ + drm_r128_packet_t packet; + int ret; + + memset(&packet, 0, sizeof(drm_r128_packet_t)); + + packet.count = *count; + packet.flags = flags; + + while (packet.count > 0) { + packet.buffer = buffer + (*count - packet.count); + ret = ioctl(fd, DRM_IOCTL_R128_PACKET, &packet); + if (ret < 0 && ret != -EAGAIN) { + *count = packet.count; + return -errno; + } + } + + *count = 0; + return 0; +} + +int drmR128GetVertexBuffers(int fd, int count, int *indices, int *sizes) +{ + drm_r128_vertex_t v; + + v.send_count = 0; + v.send_indices = NULL; + v.send_sizes = NULL; + v.prim = DRM_R128_PRIM_NONE; + v.request_count = count; + v.request_indices = indices; + v.request_sizes = sizes; + v.granted_count = 0; + + if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v)) return -errno; + + return v.granted_count; +} + +int drmR128FlushVertexBuffers(int fd, int count, int *indices, + int *sizes, drmR128PrimType prim) +{ + drm_r128_vertex_t v; + + v.send_count = count; + v.send_indices = indices; + v.send_sizes = sizes; + v.prim = prim; + v.request_count = 0; + v.request_indices = NULL; + v.request_sizes = NULL; + v.granted_count = 0; + + if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v) < 0) return -errno; + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h index 15491aeeb..c8c5581da 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h @@ -72,9 +72,10 @@ typedef struct drm_clip_rect { unsigned short y2; } drm_clip_rect_t; -/* Seperate include files for the i810/mga specific structures */ +/* Seperate include files for the i810/mga/r128 specific structures */ #include "mga_drm.h" #include "i810_drm.h" +#include "r128_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -297,7 +298,7 @@ typedef struct drm_agp_info { #define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) #define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) -#define DRM_IOCTL_GET_MAGIC DRM_IOW( 0x02, drm_auth_t) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t) #define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) @@ -328,11 +329,11 @@ typedef struct drm_agp_info { #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) #define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) -#define DRM_IOCTL_AGP_ENABLE DRM_IOR( 0x32, drm_agp_mode_t) -#define DRM_IOCTL_AGP_INFO DRM_IOW( 0x33, drm_agp_info_t) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t) #define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t) #define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t) -#define DRM_IOCTL_AGP_BIND DRM_IOWR(0x36, drm_agp_binding_t) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t) #define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t) /* Mga specific ioctls */ @@ -342,12 +343,23 @@ typedef struct drm_agp_info { #define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t) #define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t) #define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t ) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) /* I810 specific ioctls */ #define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) #define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) -#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t) +#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t) #define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) #define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) +#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) +#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46) + +/* Rage 128 specific ioctls */ +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) +#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCEIDL DRM_IO( 0x43) +#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h index 61287e3e2..372ba595e 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h @@ -1,8 +1,7 @@ /* xf86drm.h -- OS-independent header for DRM user-level library interface * Created: Tue Jan 5 08:17:23 1999 by faith@precisioninsight.com - * Revised: Sun Feb 13 23:46:21 2000 by kevin@precisioninsight.com * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -24,6 +23,8 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * + * Author: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.7 2000/02/23 04:47:21 martin Exp $ * */ @@ -65,7 +66,8 @@ typedef struct _drmVersion { typedef enum { DRM_FRAME_BUFFER = 0, /* WC, no caching, no core dump */ DRM_REGISTERS = 1, /* no caching, no core dump */ - DRM_SHM = 2 /* shared, cached */ + DRM_SHM = 2, /* shared, cached */ + DRM_AGP = 3 /* AGP/GART */ } drmMapType; typedef enum { @@ -95,6 +97,11 @@ typedef enum { /* These values *MUST* match drm.h */ } drmDMAFlags; typedef enum { + DRM_PAGE_ALIGN = 0x01, + DRM_AGP_BUFFER = 0x02 +} drmBufDescFlags; + +typedef enum { DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */ DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */ DRM_LOCK_FLUSH = 0x04, /* Flush this context's DMA queue first */ @@ -196,7 +203,7 @@ typedef struct { unsigned int a[100]; } __drm_dummy_lock_t; #endif #ifndef DRM_CAS -#define DRM_CAS(lock,old,new,ret) /* FAST LOCK FAILS */ +#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */ #endif #define DRM_LIGHT_LOCK(fd,lock,context) \ @@ -291,7 +298,9 @@ extern int drmAddMap(int fd, drmMapType type, drmMapFlags flags, drmHandlePtr handle); -extern int drmAddBufs(int fd, int count, int size, int flags); +extern int drmAddBufs(int fd, int count, int size, + drmBufDescFlags flags, + int agp_offset); extern int drmMarkBufs(int fd, double low, double high); extern int drmCreateContext(int fd, drmContextPtr handle); extern int drmSetContextFlags(int fd, drmContext context, @@ -332,6 +341,29 @@ extern int drmGetLock(int fd, extern int drmUnlock(int fd, drmContext context); extern int drmFinish(int fd, int context, drmLockFlags flags); +/* AGP/GART support: X server (root) only */ +extern int drmAgpAcquire(int fd); +extern int drmAgpRelease(int fd); +extern int drmAgpEnable(int fd, unsigned long mode); +extern int drmAgpAlloc(int fd, unsigned long size, + unsigned long type, unsigned long *address, + unsigned long *handle); +extern int drmAgpFree(int fd, unsigned long handle); +extern int drmAgpBind(int fd, unsigned long handle, + unsigned long offset); +extern int drmAgpUnbind(int fd, unsigned long handle); + +/* AGP/GART info: authenticated client and/or X */ +extern int drmAgpVersionMajor(int fd); +extern int drmAgpVersionMinor(int fd); +extern unsigned long drmAgpGetMode(int fd); +extern unsigned long drmAgpBase(int fd); /* Physical location */ +extern unsigned long drmAgpSize(int fd); /* Bytes */ +extern unsigned long drmAgpMemoryUsed(int fd); +extern unsigned long drmAgpMemoryAvail(int fd); +extern unsigned int drmAgpVendorId(int fd); +extern unsigned int drmAgpDeviceId(int fd); + /* Support routines */ extern int drmError(int err, const char *label); extern void *drmMalloc(int size); diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmI810.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmI810.h new file mode 100644 index 000000000..6c11b7a10 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmI810.h @@ -0,0 +1,46 @@ + +/* WARNING: If you change any of these defines, make sure to change + * the kernel include file as well (i810_drm.h) + */ + +#ifndef _XF86DRI_I810_H_ +#define _XF86DRI_I810_H_ + +#ifndef _I810_DEFINES_ +#define _I810_DEFINES_ +#define I810_USE_BATCH 1 + +#define I810_DMA_BUF_ORDER 12 +#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER) +#define I810_DMA_BUF_NR 256 + +#define I810_NR_SAREA_CLIPRECTS 8 + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define I810_NR_TEX_REGIONS 64 +#define I810_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +typedef struct _drmI810Init { + unsigned int start; + unsigned int end; + unsigned int size; + int ring_map_idx; + int buffer_map_idx; + int sarea_off; + + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; +} drmI810Init; + + +Bool drmI810CleanupDma(int driSubFD); +Bool drmI810InitDma(int driSubFD, drmI810Init *info ); + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmMga.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmMga.h new file mode 100644 index 000000000..3b0e4a6fc --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmMga.h @@ -0,0 +1,147 @@ + +/* WARNING: If you change any of these defines, make sure to change + * the kernel include file as well (mga_drm.h) + */ + +#ifndef _XF86DRI_MGA_H_ +#define _XF86DRI_MGA_H_ +#ifndef _MGA_DEFINES_ +#define _MGA_DEFINES_ +#define MGA_F 0x1 /* fog */ +#define MGA_A 0x2 /* alpha */ +#define MGA_S 0x4 /* specular */ +#define MGA_T2 0x8 /* multitexture */ + +#define MGA_WARP_TGZ 0 +#define MGA_WARP_TGZF (MGA_F) +#define MGA_WARP_TGZA (MGA_A) +#define MGA_WARP_TGZAF (MGA_F|MGA_A) +#define MGA_WARP_TGZS (MGA_S) +#define MGA_WARP_TGZSF (MGA_S|MGA_F) +#define MGA_WARP_TGZSA (MGA_S|MGA_A) +#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) +#define MGA_WARP_T2GZ (MGA_T2) +#define MGA_WARP_T2GZF (MGA_T2|MGA_F) +#define MGA_WARP_T2GZA (MGA_T2|MGA_A) +#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) +#define MGA_WARP_T2GZS (MGA_T2|MGA_S) +#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) +#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) +#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) + +#define MGA_MAX_G400_PIPES 16 +#define MGA_MAX_G200_PIPES 8 /* no multitex */ + +#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES + +#define MGA_CARD_TYPE_G200 1 +#define MGA_CARD_TYPE_G400 2 +#define MGA_FRONT 0x1 +#define MGA_BACK 0x2 +#define MGA_DEPTH 0x4 + +/* 3d state excluding texture units: + */ +#define MGA_CTXREG_DSTORG 0 /* validated */ +#define MGA_CTXREG_MACCESS 1 +#define MGA_CTXREG_PLNWT 2 +#define MGA_CTXREG_DWGCTL 3 +#define MGA_CTXREG_ALPHACTRL 4 +#define MGA_CTXREG_FOGCOLOR 5 +#define MGA_CTXREG_WFLAG 6 +#define MGA_CTXREG_TDUAL0 7 +#define MGA_CTXREG_TDUAL1 8 +#define MGA_CTXREG_FCOL 9 +#define MGA_CTX_SETUP_SIZE 10 + +/* 2d state + */ +#define MGA_2DREG_PITCH 0 +#define MGA_2D_SETUP_SIZE 1 + +/* Each texture unit has a state: + */ +#define MGA_TEXREG_CTL 0 +#define MGA_TEXREG_CTL2 1 +#define MGA_TEXREG_FILTER 2 +#define MGA_TEXREG_BORDERCOL 3 +#define MGA_TEXREG_ORG 4 /* validated */ +#define MGA_TEXREG_ORG1 5 +#define MGA_TEXREG_ORG2 6 +#define MGA_TEXREG_ORG3 7 +#define MGA_TEXREG_ORG4 8 +#define MGA_TEXREG_WIDTH 9 +#define MGA_TEXREG_HEIGHT 10 +#define MGA_TEX_SETUP_SIZE 11 + +/* What needs to be changed for the current vertex dma buffer? + */ +#define MGA_UPLOAD_CTX 0x1 +#define MGA_UPLOAD_TEX0 0x2 +#define MGA_UPLOAD_TEX1 0x4 +#define MGA_UPLOAD_PIPE 0x8 +#define MGA_UPLOAD_TEX0IMAGE 0x10 +#define MGA_UPLOAD_TEX1IMAGE 0x20 +#define MGA_UPLOAD_2D 0x40 +#define MGA_WAIT_AGE 0x80 /* handled client-side */ +#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ +#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock + quiescent */ + +/* 32 buffers of 64k each, total 1 meg. + */ +#define MGA_DMA_BUF_ORDER 16 +#define MGA_DMA_BUF_SZ (1<<MGA_DMA_BUF_ORDER) +#define MGA_DMA_BUF_NR 31 + +/* Keep these small for testing. + */ +#define MGA_NR_SAREA_CLIPRECTS 8 + +/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define MGA_CARD_HEAP 0 +#define MGA_AGP_HEAP 1 +#define MGA_NR_TEX_HEAPS 2 +#define MGA_NR_TEX_REGIONS 16 +#define MGA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +typedef struct _drmMgaWarpIndex { + int installed; + unsigned long phys_addr; + int size; +} drmMgaWarpIndex; + +typedef struct _drmMgaInit { + int reserved_map_agpstart; + int reserved_map_idx; + int buffer_map_idx; + int sarea_priv_offset; + int primary_size; + int warp_ucode_size; + unsigned int frontOffset; + unsigned int backOffset; + unsigned int depthOffset; + unsigned int textureOffset; + unsigned int textureSize; + unsigned int agpTextureSize; + unsigned int agpTextureOffset; + unsigned int cpp; + unsigned int stride; + int sgram; + int chipset; + drmMgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES]; + unsigned int mAccess; +} drmMgaInit; + + +Bool drmMgaCleanupDma(int driSubFD); +Bool drmMgaLockUpdate(int driSubFD, drmLockFlags flags); +Bool drmMgaInitDma(int driSubFD, drmMgaInit *info); +#endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h new file mode 100644 index 000000000..46898a53c --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h @@ -0,0 +1,80 @@ +/* xf86drm.h -- OS-independent header for DRM user-level library interface + * Created: Sun Apr 9 18:16:28 2000 by kevin@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + * + * Author: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#ifndef _XF86DRI_R128_H_ +#define _XF86DRI_R128_H_ + +/* WARNING: If you change any of these defines, make sure to change + * the kernel include file as well (r128_drm.h) + */ + +typedef struct _drmR128Init { + int sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_fifo_size; + int cce_secure; + int ring_size; + int usec_timeout; + + int fb_offset; + int agp_ring_offset; + int agp_read_ptr_offset; + int agp_vertbufs_offset; + int agp_indbufs_offset; + int agp_textures_offset; + int mmio_offset; +} drmR128Init; + +typedef enum { + DRM_R128_PRIM_NONE = 0x0001, + DRM_R128_PRIM_POINT = 0x0002, + DRM_R128_PRIM_LINE = 0x0004, + DRM_R128_PRIM_POLY_LINE = 0x0008, + DRM_R128_PRIM_TRI_LIST = 0x0010, + DRM_R128_PRIM_TRI_FAN = 0x0020, + DRM_R128_PRIM_TRI_STRIP = 0x0040, + DRM_R128_PRIM_TRI_TYPE2 = 0x0080 +} drmR128PrimType; + + +extern int drmR128InitCCE(int fd, drmR128Init *info); +extern int drmR128CleanupCCE(int fd); +extern int drmR128EngineReset(int fd); +extern int drmR128EngineFlush(int fd); +extern int drmR128CCEWaitForIdle(int fd); +extern int drmR128SubmitPackets(int fd, CARD32 *buffer, int *count, int flags); +extern int drmR128GetVertexBuffers(int fd, int count, int *indices, + int *sizes); +extern int drmR128FlushVertexBuffers(int fd, int count, int *indices, + int *sizes, drmR128PrimType prim); + +#endif |