diff options
Diffstat (limited to 'src')
212 files changed, 41021 insertions, 1 deletions
diff --git a/src/driclient/include/driclient.h b/src/driclient/include/driclient.h new file mode 100644 index 0000000000..d391525039 --- /dev/null +++ b/src/driclient/include/driclient.h @@ -0,0 +1,97 @@ +#ifndef driclient_h +#define driclient_h + +#include <stdint.h> +#include <X11/Xlib.h> +#include <drm_sarea.h> +#include "xf86dri.h" + +/* TODO: Bring in DRI XML options */ + +typedef struct dri_version +{ +	int major; +	int minor; +	int patch; +} dri_version_t; + +typedef struct dri_screen +{ +	Display			*display; +	unsigned int		num; +	dri_version_t		ddx, dri, drm; +	int			draw_lock_id; +	int			fd; +	drm_sarea_t		*sarea; +	void			*drawable_hash; +	void			*private; +} dri_screen_t; + +struct dri_context; + +typedef struct dri_drawable +{ +	drm_drawable_t		drm_drawable; +	Drawable		x_drawable; +	unsigned int		sarea_index; +	unsigned int		*sarea_stamp; +	unsigned int		last_sarea_stamp; +	int			x, y, w, h; +	int			back_x, back_y; +	int			num_cliprects, num_back_cliprects; +	drm_clip_rect_t		*cliprects, *back_cliprects; +	dri_screen_t		*dri_screen; +	unsigned int		refcount; +	void			*private; +} dri_drawable_t; + +typedef struct dri_context +{ +	XID			id; +	drm_context_t		drm_context; +	dri_screen_t		*dri_screen; +	void			*private; +} dri_context_t; + +typedef struct dri_framebuffer +{ +	drm_handle_t		drm_handle; +	int			base, size, stride; +	int			private_size; +	void			*private; +} dri_framebuffer_t; + +int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf); +int driDestroyScreen(dri_screen_t *dri_screen); +int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable); +int driUpdateDrawableInfo(dri_drawable_t *dri_drawable); +int driDestroyDrawable(dri_drawable_t *dri_drawable); +int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context); +int driDestroyContext(dri_context_t *dri_context); + +#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable)					\ +do											\ +{											\ +	if (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp)		\ +		driUpdateDrawableInfo(dri_drawable);					\ +} while (0) + +#define DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable)					\ +do												\ +{												\ +	while (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp)			\ +	{											\ +		register unsigned int hwContext = dri_screen->sarea->lock.lock &		\ +		~(DRM_LOCK_HELD | DRM_LOCK_CONT);						\ +		DRM_UNLOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext);		\ +												\ +		DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);	\ +		DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable);					\ +		DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);	\ +												\ +		DRM_LIGHT_LOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext);		\ +	}											\ +} while (0) + +#endif + diff --git a/src/driclient/include/xf86dri.h b/src/driclient/include/xf86dri.h new file mode 100644 index 0000000000..baf80a7a9d --- /dev/null +++ b/src/driclient/include/xf86dri.h @@ -0,0 +1,119 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +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, 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 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. + +**************************************************************************/ + +/** + * \file xf86dri.h + * Protocol numbers and function prototypes for DRI X protocol. + * + * \author Kevin E. Martin <martin@valinux.com> + * \author Jens Owen <jens@tungstengraphics.com> + * \author Rickard E. (Rik) Faith <faith@valinux.com> + */ + +#ifndef _XF86DRI_H_ +#define _XF86DRI_H_ + +#include <X11/Xfuncproto.h> +#include <xf86drm.h> + +#define X_XF86DRIQueryVersion			0 +#define X_XF86DRIQueryDirectRenderingCapable	1 +#define X_XF86DRIOpenConnection			2 +#define X_XF86DRICloseConnection		3 +#define X_XF86DRIGetClientDriverName		4 +#define X_XF86DRICreateContext			5 +#define X_XF86DRIDestroyContext			6 +#define X_XF86DRICreateDrawable			7 +#define X_XF86DRIDestroyDrawable		8 +#define X_XF86DRIGetDrawableInfo		9 +#define X_XF86DRIGetDeviceInfo			10 +#define X_XF86DRIAuthConnection                 11 +#define X_XF86DRIOpenFullScreen                 12   /* Deprecated */ +#define X_XF86DRICloseFullScreen                13   /* Deprecated */ + +#define XF86DRINumberEvents		0 + +#define XF86DRIClientNotLocal		0 +#define XF86DRIOperationNotSupported	1 +#define XF86DRINumberErrors		(XF86DRIOperationNotSupported + 1) + +#ifndef _XF86DRI_SERVER_ + +_XFUNCPROTOBEGIN + +Bool XF86DRIQueryExtension( Display *dpy, int *event_base, int *error_base ); + +Bool XF86DRIQueryVersion( Display *dpy, int *majorVersion, int *minorVersion, +    int *patchVersion ); + +Bool XF86DRIQueryDirectRenderingCapable( Display *dpy, int screen, +    Bool *isCapable ); + +Bool XF86DRIOpenConnection( Display *dpy, int screen, drm_handle_t *hSAREA, +    char **busIDString ); + +Bool XF86DRIAuthConnection( Display *dpy, int screen, drm_magic_t magic ); + +Bool XF86DRICloseConnection( Display *dpy, int screen ); + +Bool XF86DRIGetClientDriverName( Display *dpy, int screen, +    int *ddxDriverMajorVersion, int *ddxDriverMinorVersion, +    int *ddxDriverPatchVersion, char **clientDriverName ); + +Bool XF86DRICreateContext( Display *dpy, int screen, Visual *visual, +    XID *ptr_to_returned_context_id, drm_context_t *hHWContext ); + +Bool XF86DRICreateContextWithConfig( Display *dpy, int screen, int configID, +    XID *ptr_to_returned_context_id, drm_context_t *hHWContext ); + +Bool XF86DRIDestroyContext( Display *dpy, int screen, +    XID context_id ); + +Bool XF86DRICreateDrawable( Display *dpy, int screen, +    Drawable drawable, drm_drawable_t *hHWDrawable ); + +Bool XF86DRIDestroyDrawable( Display *dpy, int screen,  +    Drawable drawable); + +Bool XF86DRIGetDrawableInfo( Display *dpy, int screen, Drawable drawable, +    unsigned int *index, unsigned int *stamp,  +    int *X, int *Y, int *W, int *H, +    int *numClipRects, drm_clip_rect_t ** pClipRects, +    int *backX, int *backY, +    int *numBackClipRects, drm_clip_rect_t **pBackClipRects ); + +Bool XF86DRIGetDeviceInfo( Display *dpy, int screen, +    drm_handle_t *hFrameBuffer, int *fbOrigin, int *fbSize, +    int *fbStride, int *devPrivateSize, void **pDevPrivate ); + +_XFUNCPROTOEND + +#endif /* _XF86DRI_SERVER_ */ + +#endif /* _XF86DRI_H_ */ + diff --git a/src/driclient/src/.gitignore b/src/driclient/src/.gitignore new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/src/driclient/src/.gitignore @@ -0,0 +1 @@ +test diff --git a/src/driclient/src/Makefile b/src/driclient/src/Makefile new file mode 100644 index 0000000000..89ffb84477 --- /dev/null +++ b/src/driclient/src/Makefile @@ -0,0 +1,23 @@ +TARGET		= libdriclient.a +OBJECTS		= driclient.o XF86dri.o +DRMDIR		?= /usr + +CFLAGS		+= -g -Wall -fPIC -Werror -I../include -I${DRMDIR}/include -I${DRMDIR}/include/drm + +############################################# + +.PHONY	= all clean + +all: ${TARGET} test + +${TARGET}: ${OBJECTS} +	ar rcs $@ $^ +	if ! test -d ../lib; then mkdir ../lib; fi +	cp ${TARGET} ../lib + +test: test.o +	$(CC) -L../lib -L${DRMDIR}/lib ${LDFLAGS} -o $@ $^ -ldriclient -lX11 -lXext -ldrm + +clean: +	rm -rf ${OBJECTS} ${TARGET} ../lib/${TARGET} test test.o + diff --git a/src/driclient/src/XF86dri.c b/src/driclient/src/XF86dri.c new file mode 100644 index 0000000000..9e359a9238 --- /dev/null +++ b/src/driclient/src/XF86dri.c @@ -0,0 +1,619 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +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, 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 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 <martin@valinux.com> + *   Jens Owen <jens@tungstengraphics.com> + *   Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_REPLIES +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include "xf86dristr.h" + +static XExtensionInfo _xf86dri_info_data; +static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; +static char xf86dri_extension_name[] = XF86DRINAME; + +#define XF86DRICheckExtension(dpy,i,val) \ +  XextCheckExtension (dpy, i, xf86dri_extension_name, val) + +/***************************************************************************** + *                                                                           * + *			   private utility routines                          * + *                                                                           * + *****************************************************************************/ + +static int close_display(Display *dpy, XExtCodes *extCodes); +static /* const */ XExtensionHooks xf86dri_extension_hooks = { +    NULL,				/* create_gc */ +    NULL,				/* copy_gc */ +    NULL,				/* flush_gc */ +    NULL,				/* free_gc */ +    NULL,				/* create_font */ +    NULL,				/* free_font */ +    close_display,			/* close_display */ +    NULL,				/* wire_to_event */ +    NULL,				/* event_to_wire */ +    NULL,				/* error */ +    NULL,				/* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info,  +				   xf86dri_extension_name,  +				   &xf86dri_extension_hooks,  +				   0, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info) + + +/***************************************************************************** + *                                                                           * + *		    public XFree86-DRI Extension routines                    * + *                                                                           * + *****************************************************************************/ + +#if 0 +#include <stdio.h> +#define TRACE(msg)  fprintf(stderr,"XF86DRI%s\n", msg); +#else +#define TRACE(msg) +#endif + +#define PUBLIC + +PUBLIC Bool XF86DRIQueryExtension (dpy, event_basep, error_basep) +    Display *dpy; +    int *event_basep, *error_basep; +{ +    XExtDisplayInfo *info = find_display (dpy); + +    TRACE("QueryExtension..."); +    if (XextHasExtension(info)) { +	*event_basep = info->codes->first_event; +	*error_basep = info->codes->first_error; +        TRACE("QueryExtension... return True"); +	return True; +    } else { +        TRACE("QueryExtension... return False"); +	return False; +    } +} + +PUBLIC Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) +    Display* dpy; +    int* majorVersion;  +    int* minorVersion; +    int* patchVersion; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIQueryVersionReply rep; +    xXF86DRIQueryVersionReq *req; + +    TRACE("QueryVersion..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIQueryVersion, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIQueryVersion; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("QueryVersion... return False"); +	return False; +    } +    *majorVersion = rep.majorVersion; +    *minorVersion = rep.minorVersion; +    *patchVersion = rep.patchVersion; +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("QueryVersion... return True"); +    return True; +} + +PUBLIC Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable) +    Display* dpy; +    int screen; +    Bool* isCapable; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIQueryDirectRenderingCapableReply rep; +    xXF86DRIQueryDirectRenderingCapableReq *req; + +    TRACE("QueryDirectRenderingCapable..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIQueryDirectRenderingCapable, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIQueryDirectRenderingCapable; +    req->screen = screen; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("QueryDirectRenderingCapable... return False"); +	return False; +    } +    *isCapable = rep.isCapable; +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("QueryDirectRenderingCapable... return True"); +    return True; +} + +PUBLIC Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString) +    Display* dpy; +    int screen; +    drm_handle_t * hSAREA; +    char **busIdString; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIOpenConnectionReply rep; +    xXF86DRIOpenConnectionReq *req; + +    TRACE("OpenConnection..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIOpenConnection, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIOpenConnection; +    req->screen = screen; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("OpenConnection... return False"); +	return False; +    } + +    *hSAREA = rep.hSAREALow; +    if (sizeof(drm_handle_t) == 8) { +       int shift = 32; /* var to prevent warning on next line */ +       *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift; +    } + +    if (rep.length) { +        if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) { +            _XEatData(dpy, ((rep.busIdStringLength+3) & ~3)); +            UnlockDisplay(dpy); +            SyncHandle(); +            TRACE("OpenConnection... return False"); +            return False; +        } +	_XReadPad(dpy, *busIdString, rep.busIdStringLength); +    } else { +        *busIdString = NULL; +    } +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("OpenConnection... return True"); +    return True; +} + +PUBLIC Bool XF86DRIAuthConnection(dpy, screen, magic) +    Display* dpy; +    int screen; +    drm_magic_t magic; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIAuthConnectionReq *req; +    xXF86DRIAuthConnectionReply rep; + +    TRACE("AuthConnection..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIAuthConnection, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIAuthConnection; +    req->screen = screen; +    req->magic = magic; +    rep.authenticated = 0; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("AuthConnection... return False"); +	return False; +    } +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("AuthConnection... return True"); +    return True; +} + +PUBLIC Bool XF86DRICloseConnection(dpy, screen) +    Display* dpy; +    int screen; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRICloseConnectionReq *req; + +    TRACE("CloseConnection..."); + +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRICloseConnection, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRICloseConnection; +    req->screen = screen; +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("CloseConnection... return True"); +    return True; +} + +PUBLIC Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,  +	ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName) +    Display* dpy; +    int screen; +    int* ddxDriverMajorVersion; +    int* ddxDriverMinorVersion; +    int* ddxDriverPatchVersion; +    char** clientDriverName; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIGetClientDriverNameReply rep; +    xXF86DRIGetClientDriverNameReq *req; + +    TRACE("GetClientDriverName..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIGetClientDriverName, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIGetClientDriverName; +    req->screen = screen; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("GetClientDriverName... return False"); +	return False; +    } + +    *ddxDriverMajorVersion = rep.ddxDriverMajorVersion; +    *ddxDriverMinorVersion = rep.ddxDriverMinorVersion; +    *ddxDriverPatchVersion = rep.ddxDriverPatchVersion; + +    if (rep.length) { +        if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) { +            _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3)); +            UnlockDisplay(dpy); +            SyncHandle(); +            TRACE("GetClientDriverName... return False"); +            return False; +        } +	_XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength); +    } else { +        *clientDriverName = NULL; +    } +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("GetClientDriverName... return True"); +    return True; +} + +PUBLIC Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context, +	hHWContext) +    Display* dpy; +    int screen; +    int configID; +    XID* context; +    drm_context_t * hHWContext; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRICreateContextReply rep; +    xXF86DRICreateContextReq *req; + +    TRACE("CreateContext..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRICreateContext, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRICreateContext; +    req->visual = configID; +    req->screen = screen; +    *context = XAllocID(dpy); +    req->context = *context; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("CreateContext... return False"); +	return False; +    } +    *hHWContext = rep.hHWContext; +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("CreateContext... return True"); +    return True; +} + +PUBLIC Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext) +    Display* dpy; +    int screen; +    Visual* visual; +    XID* context; +    drm_context_t * hHWContext; +{ +    return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid, +					   context, hHWContext ); +} + +PUBLIC Bool XF86DRIDestroyContext( Display * ndpy, int screen,  +    XID context ) +{ +    Display * const dpy = (Display *) ndpy; +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIDestroyContextReq *req; + +    TRACE("DestroyContext..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIDestroyContext, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIDestroyContext; +    req->screen = screen; +    req->context = context; +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("DestroyContext... return True"); +    return True; +} + +PUBLIC Bool XF86DRICreateDrawable( Display * ndpy, int screen,  +    Drawable drawable, drm_drawable_t * hHWDrawable ) +{ +    Display * const dpy = (Display *) ndpy; +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRICreateDrawableReply rep; +    xXF86DRICreateDrawableReq *req; + +    TRACE("CreateDrawable..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRICreateDrawable, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRICreateDrawable; +    req->screen = screen; +    req->drawable = drawable; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("CreateDrawable... return False"); +	return False; +    } +    *hHWDrawable = rep.hHWDrawable; +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("CreateDrawable... return True"); +    return True; +} + +PUBLIC Bool XF86DRIDestroyDrawable( Display * ndpy, int screen, +    Drawable drawable ) +{ +    Display * const dpy = (Display *) ndpy; +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIDestroyDrawableReq *req; + +    TRACE("DestroyDrawable..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIDestroyDrawable, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIDestroyDrawable; +    req->screen = screen; +    req->drawable = drawable; +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("DestroyDrawable... return True"); +    return True; +} + +PUBLIC Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable, +    unsigned int* index, unsigned int* stamp, +    int* X, int* Y, int* W, int* H, +    int* numClipRects, drm_clip_rect_t ** pClipRects, +    int* backX, int* backY, +    int* numBackClipRects, drm_clip_rect_t ** pBackClipRects ) +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIGetDrawableInfoReply rep; +    xXF86DRIGetDrawableInfoReq *req; +    int total_rects; + +    TRACE("GetDrawableInfo..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIGetDrawableInfo, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIGetDrawableInfo; +    req->screen = screen; +    req->drawable = drawable; + +    if (!_XReply(dpy, (xReply *)&rep, 1, xFalse))  +    { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("GetDrawableInfo... return False"); +	return False; +    } +    *index = rep.drawableTableIndex; +    *stamp = rep.drawableTableStamp; +    *X = (int)rep.drawableX; +    *Y = (int)rep.drawableY; +    *W = (int)rep.drawableWidth; +    *H = (int)rep.drawableHeight; +    *numClipRects = rep.numClipRects; +    total_rects = *numClipRects; + +    *backX = rep.backX; +    *backY = rep.backY; +    *numBackClipRects = rep.numBackClipRects; +    total_rects += *numBackClipRects; + +#if 0 +    /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks +     * backwards compatibility (Because of the >> 2 shift) but the fix +     * enables multi-threaded apps to work. +     */ +    if (rep.length !=  ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -  +		       SIZEOF(xGenericReply) +  +		       total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) { +        _XEatData(dpy, rep.length); +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("GetDrawableInfo... return False"); +        return False; +    } +#endif + +    if (*numClipRects) { +       int len = sizeof(drm_clip_rect_t) * (*numClipRects); + +       *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1); +       if (*pClipRects)  +	  _XRead(dpy, (char*)*pClipRects, len); +    } else { +        *pClipRects = NULL; +    } + +    if (*numBackClipRects) { +       int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); + +       *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1); +       if (*pBackClipRects)  +	  _XRead(dpy, (char*)*pBackClipRects, len); +    } else { +        *pBackClipRects = NULL; +    } + +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("GetDrawableInfo... return True"); +    return True; +} + +PUBLIC Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer,  +	fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate) +    Display* dpy; +    int screen; +    drm_handle_t * hFrameBuffer; +    int* fbOrigin; +    int* fbSize; +    int* fbStride; +    int* devPrivateSize; +    void** pDevPrivate; +{ +    XExtDisplayInfo *info = find_display (dpy); +    xXF86DRIGetDeviceInfoReply rep; +    xXF86DRIGetDeviceInfoReq *req; + +    TRACE("GetDeviceInfo..."); +    XF86DRICheckExtension (dpy, info, False); + +    LockDisplay(dpy); +    GetReq(XF86DRIGetDeviceInfo, req); +    req->reqType = info->codes->major_opcode; +    req->driReqType = X_XF86DRIGetDeviceInfo; +    req->screen = screen; +    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { +	UnlockDisplay(dpy); +	SyncHandle(); +        TRACE("GetDeviceInfo... return False"); +	return False; +    } + +    *hFrameBuffer = rep.hFrameBufferLow; +    if (sizeof(drm_handle_t) == 8) { +       int shift = 32; /* var to prevent warning on next line */ +       *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift; +    } + +    *fbOrigin = rep.framebufferOrigin; +    *fbSize = rep.framebufferSize; +    *fbStride = rep.framebufferStride; +    *devPrivateSize = rep.devPrivateSize; + +    if (rep.length) { +        if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) { +            _XEatData(dpy, ((rep.devPrivateSize+3) & ~3)); +            UnlockDisplay(dpy); +            SyncHandle(); +            TRACE("GetDeviceInfo... return False"); +            return False; +        } +	_XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize); +    } else { +        *pDevPrivate = NULL; +    } + +    UnlockDisplay(dpy); +    SyncHandle(); +    TRACE("GetDeviceInfo... return True"); +    return True; +} + +PUBLIC Bool XF86DRIOpenFullScreen(dpy, screen, drawable) +    Display* dpy; +    int screen; +    Drawable drawable; +{ +    /* This function and the underlying X protocol are deprecated. +     */ +    (void) dpy; +    (void) screen; +    (void) drawable; +    return False; +} + +PUBLIC Bool XF86DRICloseFullScreen(dpy, screen, drawable) +    Display* dpy; +    int screen; +    Drawable drawable; +{ +    /* This function and the underlying X protocol are deprecated. +     */ +    (void) dpy; +    (void) screen; +    (void) drawable; +    return True; +} + diff --git a/src/driclient/src/driclient.c b/src/driclient/src/driclient.c new file mode 100644 index 0000000000..94d01aca4f --- /dev/null +++ b/src/driclient/src/driclient.c @@ -0,0 +1,287 @@ +#include "driclient.h" +#include <assert.h> +#include <stdlib.h> + +int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf) +{ +	int		evbase, errbase; +	char		*driver_name; +	int		newly_opened; +	drm_magic_t	magic; +	drmVersionPtr	drm_version; +	drm_handle_t	sarea_handle; +	char		*bus_id; +	dri_screen_t	*dri_scrn; +	 +	assert(display); +	assert(dri_screen); +	 +	if (!XF86DRIQueryExtension(display, &evbase, &errbase)) +		return 1; +	 +	dri_scrn = calloc(1, sizeof(dri_screen_t)); +	 +	if (!dri_scrn) +		return 1; + +	if (!XF86DRIQueryVersion(display, &dri_scrn->dri.major, &dri_scrn->dri.minor, &dri_scrn->dri.patch)) +		goto free_screen; +	 +	dri_scrn->display = display; +	dri_scrn->num = screen; +	dri_scrn->draw_lock_id = 1; +	 +	if (!XF86DRIOpenConnection(display, screen, &sarea_handle, &bus_id)) +		goto free_screen; +	 +	dri_scrn->fd = -1; +	dri_scrn->fd = drmOpenOnce(NULL, bus_id, &newly_opened); +	XFree(bus_id); + +	if (dri_scrn->fd < 0) +		goto close_connection; +	 +	if (drmGetMagic(dri_scrn->fd, &magic)) +		goto close_drm; +	 +	drm_version = drmGetVersion(dri_scrn->fd); +	 +	if (!drm_version) +		goto close_drm; + +	dri_scrn->drm.major = drm_version->version_major; +	dri_scrn->drm.minor = drm_version->version_minor; +	dri_scrn->drm.patch = drm_version->version_patchlevel; +	drmFreeVersion(drm_version); +				 +	if (!XF86DRIAuthConnection(display, screen, magic)) +		goto close_drm; +	 +	if (!XF86DRIGetClientDriverName +	( +		display, +		screen, +		&dri_scrn->ddx.major, +		&dri_scrn->ddx.minor, +		&dri_scrn->ddx.patch, +		&driver_name +	)) +		goto close_drm; +	 +	if (drmMap(dri_scrn->fd, sarea_handle, SAREA_MAX, (drmAddress)&dri_scrn->sarea)) +		goto close_drm; +	 +	dri_scrn->drawable_hash = drmHashCreate(); +	 +	if (!dri_scrn->drawable_hash) +		goto unmap_sarea; +	 +	if (dri_framebuf) +	{ +		if (!XF86DRIGetDeviceInfo +		( +			display, +			screen, &dri_framebuf->drm_handle, +			&dri_framebuf->base, +			&dri_framebuf->size, +			&dri_framebuf->stride, +			&dri_framebuf->private_size, +			&dri_framebuf->private +		)) +			goto destroy_hash; +	} +	 +	*dri_screen = dri_scrn; +	 +	return 0; + +destroy_hash: +	drmHashDestroy(dri_scrn->drawable_hash); +unmap_sarea: +	drmUnmap(dri_scrn->sarea, SAREA_MAX); +close_drm: +	drmCloseOnce(dri_scrn->fd); +close_connection: +	XF86DRICloseConnection(display, screen); +free_screen: +	free(dri_scrn); +	 +	return 1; +} + +int driDestroyScreen(dri_screen_t *dri_screen) +{ +	assert(dri_screen); +	 +	drmHashDestroy(dri_screen->drawable_hash); +	drmUnmap(dri_screen->sarea, SAREA_MAX); +	drmCloseOnce(dri_screen->fd); +	XF86DRICloseConnection(dri_screen->display, dri_screen->num); +	free(dri_screen); +	 +	return 0; +} + +int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable) +{ +	int		evbase, errbase; +	dri_drawable_t	*dri_draw; +	 +	assert(dri_screen); +	assert(dri_drawable); +	 +	if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase)) +		return 1; +	 +	if (!drmHashLookup(dri_screen->drawable_hash, drawable, (void**)dri_drawable)) +	{ +		/* Found */ +		(*dri_drawable)->refcount++; +		return 0; +	} +	 +	dri_draw = calloc(1, sizeof(dri_drawable_t)); +	 +	if (!dri_draw) +		return 1; +	 +	if (!XF86DRICreateDrawable(dri_screen->display, 0, drawable, &dri_draw->drm_drawable)) +	{ +		free(dri_draw); +		return 1; +	} +	 +	dri_draw->x_drawable = drawable; +	dri_draw->sarea_index = 0; +	dri_draw->sarea_stamp = NULL; +	dri_draw->last_sarea_stamp = 0; +	dri_draw->dri_screen = dri_screen; +	dri_draw->refcount = 1; +	 +	if (drmHashInsert(dri_screen->drawable_hash, drawable, dri_draw)) +	{ +		XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable); +		free(dri_draw); +		return 1; +	} +	 +	/* +	 * XXX: Need this to initialize sarea pointer and other stuff in dri_drawable_t +	 * to be able to use the DRI_VALIDATE_DRAWABLE_INFO macro, but is it safe to +	 * call without any sync? +	 */ +	if (driUpdateDrawableInfo(dri_draw)) +	{ +		XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable); +		free(dri_draw); +		return 1; +	} +	 +	*dri_drawable = dri_draw; +	 +	return 0; +} + +int driUpdateDrawableInfo(dri_drawable_t *dri_drawable) +{ +	assert(dri_drawable); +	 +	if (dri_drawable->cliprects) +		XFree(dri_drawable->cliprects); +	if (dri_drawable->back_cliprects) +		XFree(dri_drawable->back_cliprects); +	 +	DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id); +	 +	if (!XF86DRIGetDrawableInfo +	( +		dri_drawable->dri_screen->display, +		dri_drawable->dri_screen->num, +		dri_drawable->x_drawable, +    		&dri_drawable->sarea_index, +    		&dri_drawable->last_sarea_stamp, +    		&dri_drawable->x, +    		&dri_drawable->y, +    		&dri_drawable->w, +    		&dri_drawable->h, +		&dri_drawable->num_cliprects, +		&dri_drawable->cliprects, +		&dri_drawable->back_x, +		&dri_drawable->back_y, +		&dri_drawable->num_back_cliprects, +		&dri_drawable->back_cliprects +	)) +	{ +		dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp; +		dri_drawable->num_cliprects = 0; +		dri_drawable->cliprects = NULL; +		dri_drawable->num_back_cliprects = 0; +		dri_drawable->back_cliprects = 0; +		 +		return 1; +	} +	else +		dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp; +	 +	DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id); +	 +	return 0; +} + +int driDestroyDrawable(dri_drawable_t *dri_drawable) +{ +	assert(dri_drawable); +	 +	if (--dri_drawable->refcount == 0) +	{ +		if (dri_drawable->cliprects) +			XFree(dri_drawable->cliprects); +		if (dri_drawable->back_cliprects) +			XFree(dri_drawable->back_cliprects); +		drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable); +		XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable); +		free(dri_drawable); +	} +	 +	return 0; +} + +int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context) +{ +	int		evbase, errbase; +	dri_context_t	*dri_ctx; +	 +	assert(dri_screen); +	assert(visual); +	assert(dri_context); +	 +	if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase)) +		return 1; +	 +	dri_ctx = calloc(1, sizeof(dri_context_t)); +	 +	if (!dri_ctx) +		return 1; +	 +	if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context)) +	{ +		free(dri_ctx); +		return 1; +	} +	 +	dri_ctx->dri_screen = dri_screen;	 +	*dri_context = dri_ctx; +	 +	return 0; +} + +int driDestroyContext(dri_context_t *dri_context) +{ +	assert(dri_context); +	 +	XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id); +	free(dri_context); +	 +	return 0; +} + diff --git a/src/driclient/src/test.c b/src/driclient/src/test.c new file mode 100644 index 0000000000..15f75d928b --- /dev/null +++ b/src/driclient/src/test.c @@ -0,0 +1,41 @@ +#include <assert.h> +#include <stdio.h> +#include "driclient.h" + +int main(int argc, char **argv) +{ +	Display		*dpy; +	Window		root, window; +	 +	dri_screen_t	*screen; +	dri_drawable_t	*dri_drawable; +	dri_context_t	*context; +	 +	dpy = XOpenDisplay(NULL); +	root = XDefaultRootWindow(dpy); +	window = XCreateSimpleWindow(dpy, root, 0, 0, 100, 100, 0, 0, 0); + +	XSelectInput(dpy, window, 0); +	XMapWindow(dpy, window); +	XSync(dpy, 0); +	 +	assert(driCreateScreen(dpy, 0, &screen, NULL) == 0); +	assert(driCreateDrawable(screen, window, &dri_drawable) == 0); +	assert(driCreateContext(screen, XDefaultVisual(dpy, 0), &context) == 0); +	assert(driUpdateDrawableInfo(dri_drawable) == 0); +	 +	DRI_VALIDATE_DRAWABLE_INFO(screen, dri_drawable); +	 +	assert(drmGetLock(screen->fd, context->drm_context, 0) == 0); +	assert(drmUnlock(screen->fd, context->drm_context) == 0); +	 +	assert(driDestroyContext(context) == 0); +	assert(driDestroyDrawable(dri_drawable) == 0); +	assert(driDestroyScreen(screen) == 0); +	 +	XDestroyWindow(dpy, window); +	XCloseDisplay(dpy); +	 +	return 0; +} + diff --git a/src/driclient/src/xf86dri.h b/src/driclient/src/xf86dri.h new file mode 100644 index 0000000000..baf80a7a9d --- /dev/null +++ b/src/driclient/src/xf86dri.h @@ -0,0 +1,119 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +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, 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 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. + +**************************************************************************/ + +/** + * \file xf86dri.h + * Protocol numbers and function prototypes for DRI X protocol. + * + * \author Kevin E. Martin <martin@valinux.com> + * \author Jens Owen <jens@tungstengraphics.com> + * \author Rickard E. (Rik) Faith <faith@valinux.com> + */ + +#ifndef _XF86DRI_H_ +#define _XF86DRI_H_ + +#include <X11/Xfuncproto.h> +#include <xf86drm.h> + +#define X_XF86DRIQueryVersion			0 +#define X_XF86DRIQueryDirectRenderingCapable	1 +#define X_XF86DRIOpenConnection			2 +#define X_XF86DRICloseConnection		3 +#define X_XF86DRIGetClientDriverName		4 +#define X_XF86DRICreateContext			5 +#define X_XF86DRIDestroyContext			6 +#define X_XF86DRICreateDrawable			7 +#define X_XF86DRIDestroyDrawable		8 +#define X_XF86DRIGetDrawableInfo		9 +#define X_XF86DRIGetDeviceInfo			10 +#define X_XF86DRIAuthConnection                 11 +#define X_XF86DRIOpenFullScreen                 12   /* Deprecated */ +#define X_XF86DRICloseFullScreen                13   /* Deprecated */ + +#define XF86DRINumberEvents		0 + +#define XF86DRIClientNotLocal		0 +#define XF86DRIOperationNotSupported	1 +#define XF86DRINumberErrors		(XF86DRIOperationNotSupported + 1) + +#ifndef _XF86DRI_SERVER_ + +_XFUNCPROTOBEGIN + +Bool XF86DRIQueryExtension( Display *dpy, int *event_base, int *error_base ); + +Bool XF86DRIQueryVersion( Display *dpy, int *majorVersion, int *minorVersion, +    int *patchVersion ); + +Bool XF86DRIQueryDirectRenderingCapable( Display *dpy, int screen, +    Bool *isCapable ); + +Bool XF86DRIOpenConnection( Display *dpy, int screen, drm_handle_t *hSAREA, +    char **busIDString ); + +Bool XF86DRIAuthConnection( Display *dpy, int screen, drm_magic_t magic ); + +Bool XF86DRICloseConnection( Display *dpy, int screen ); + +Bool XF86DRIGetClientDriverName( Display *dpy, int screen, +    int *ddxDriverMajorVersion, int *ddxDriverMinorVersion, +    int *ddxDriverPatchVersion, char **clientDriverName ); + +Bool XF86DRICreateContext( Display *dpy, int screen, Visual *visual, +    XID *ptr_to_returned_context_id, drm_context_t *hHWContext ); + +Bool XF86DRICreateContextWithConfig( Display *dpy, int screen, int configID, +    XID *ptr_to_returned_context_id, drm_context_t *hHWContext ); + +Bool XF86DRIDestroyContext( Display *dpy, int screen, +    XID context_id ); + +Bool XF86DRICreateDrawable( Display *dpy, int screen, +    Drawable drawable, drm_drawable_t *hHWDrawable ); + +Bool XF86DRIDestroyDrawable( Display *dpy, int screen,  +    Drawable drawable); + +Bool XF86DRIGetDrawableInfo( Display *dpy, int screen, Drawable drawable, +    unsigned int *index, unsigned int *stamp,  +    int *X, int *Y, int *W, int *H, +    int *numClipRects, drm_clip_rect_t ** pClipRects, +    int *backX, int *backY, +    int *numBackClipRects, drm_clip_rect_t **pBackClipRects ); + +Bool XF86DRIGetDeviceInfo( Display *dpy, int screen, +    drm_handle_t *hFrameBuffer, int *fbOrigin, int *fbSize, +    int *fbStride, int *devPrivateSize, void **pDevPrivate ); + +_XFUNCPROTOEND + +#endif /* _XF86DRI_SERVER_ */ + +#endif /* _XF86DRI_H_ */ + diff --git a/src/driclient/src/xf86dristr.h b/src/driclient/src/xf86dristr.h new file mode 100644 index 0000000000..b834bd1a1a --- /dev/null +++ b/src/driclient/src/xf86dristr.h @@ -0,0 +1,342 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +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, 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 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 <martin@valinux.com> + *   Jens Owen <jens@tungstengraphics.com> + *   Rickard E. (Rik) Fiath <faith@valinux.com> + * + */ + +#ifndef _XF86DRISTR_H_ +#define _XF86DRISTR_H_ + +#include "xf86dri.h" + +#define XF86DRINAME "XFree86-DRI" + +/* The DRI version number.  This was originally set to be the same of the + * XFree86 version number.  However, this version is really indepedent of + * the XFree86 version. + * + * Version History: + *    4.0.0: Original + *    4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02 + *    4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02 + */ +#define XF86DRI_MAJOR_VERSION	4 +#define XF86DRI_MINOR_VERSION	1 +#define XF86DRI_PATCH_VERSION	0 + +typedef struct _XF86DRIQueryVersion { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRIQueryVersion */ +    CARD16	length B16; +} xXF86DRIQueryVersionReq; +#define sz_xXF86DRIQueryVersionReq	4 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    CARD16	majorVersion B16;	/* major version of DRI protocol */ +    CARD16	minorVersion B16;	/* minor version of DRI protocol */ +    CARD32	patchVersion B32;       /* patch version of DRI protocol */ +    CARD32	pad3 B32; +    CARD32	pad4 B32; +    CARD32	pad5 B32; +    CARD32	pad6 B32; +} xXF86DRIQueryVersionReply; +#define sz_xXF86DRIQueryVersionReply	32 + +typedef struct _XF86DRIQueryDirectRenderingCapable { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* X_DRIQueryDirectRenderingCapable */ +    CARD16	length B16; +    CARD32	screen B32; +} xXF86DRIQueryDirectRenderingCapableReq; +#define sz_xXF86DRIQueryDirectRenderingCapableReq	8 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    BOOL	isCapable; +    BOOL	pad2; +    BOOL	pad3; +    BOOL	pad4; +    CARD32	pad5 B32; +    CARD32	pad6 B32; +    CARD32	pad7 B32; +    CARD32	pad8 B32; +    CARD32	pad9 B32; +} xXF86DRIQueryDirectRenderingCapableReply; +#define sz_xXF86DRIQueryDirectRenderingCapableReply	32 + +typedef struct _XF86DRIOpenConnection { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRIOpenConnection */ +    CARD16	length B16; +    CARD32	screen B32; +} xXF86DRIOpenConnectionReq; +#define sz_xXF86DRIOpenConnectionReq	8 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    CARD32	hSAREALow B32; +    CARD32	hSAREAHigh B32; +    CARD32	busIdStringLength B32; +    CARD32	pad6 B32; +    CARD32	pad7 B32; +    CARD32	pad8 B32; +} xXF86DRIOpenConnectionReply; +#define sz_xXF86DRIOpenConnectionReply	32 + +typedef struct _XF86DRIAuthConnection { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRICloseConnection */ +    CARD16	length B16; +    CARD32	screen B32; +    CARD32      magic B32; +} xXF86DRIAuthConnectionReq; +#define sz_xXF86DRIAuthConnectionReq	12 + +typedef struct { +    BYTE        type; +    BOOL        pad1; +    CARD16      sequenceNumber B16; +    CARD32      length B32; +    CARD32      authenticated B32; +    CARD32      pad2 B32; +    CARD32      pad3 B32; +    CARD32      pad4 B32; +    CARD32      pad5 B32; +    CARD32      pad6 B32; +} xXF86DRIAuthConnectionReply; +#define zx_xXF86DRIAuthConnectionReply  32 + +typedef struct _XF86DRICloseConnection { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRICloseConnection */ +    CARD16	length B16; +    CARD32	screen B32; +} xXF86DRICloseConnectionReq; +#define sz_xXF86DRICloseConnectionReq	8 + +typedef struct _XF86DRIGetClientDriverName { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRIGetClientDriverName */ +    CARD16	length B16; +    CARD32	screen B32; +} xXF86DRIGetClientDriverNameReq; +#define sz_xXF86DRIGetClientDriverNameReq	8 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    CARD32	ddxDriverMajorVersion B32; +    CARD32	ddxDriverMinorVersion B32; +    CARD32	ddxDriverPatchVersion B32; +    CARD32	clientDriverNameLength B32; +    CARD32	pad5 B32; +    CARD32	pad6 B32; +} xXF86DRIGetClientDriverNameReply; +#define sz_xXF86DRIGetClientDriverNameReply	32 + +typedef struct _XF86DRICreateContext { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRICreateContext */ +    CARD16	length B16; +    CARD32	screen B32; +    CARD32	visual B32; +    CARD32	context B32; +} xXF86DRICreateContextReq; +#define sz_xXF86DRICreateContextReq	16 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    CARD32	hHWContext B32; +    CARD32	pad2 B32; +    CARD32	pad3 B32; +    CARD32	pad4 B32; +    CARD32	pad5 B32; +    CARD32	pad6 B32; +} xXF86DRICreateContextReply; +#define sz_xXF86DRICreateContextReply	32 + +typedef struct _XF86DRIDestroyContext { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRIDestroyContext */ +    CARD16	length B16; +    CARD32	screen B32; +    CARD32	context B32; +} xXF86DRIDestroyContextReq; +#define sz_xXF86DRIDestroyContextReq	12 + +typedef struct _XF86DRICreateDrawable { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRICreateDrawable */ +    CARD16	length B16; +    CARD32	screen B32; +    CARD32	drawable B32; +} xXF86DRICreateDrawableReq; +#define sz_xXF86DRICreateDrawableReq	12 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    CARD32	hHWDrawable B32; +    CARD32	pad2 B32; +    CARD32	pad3 B32; +    CARD32	pad4 B32; +    CARD32	pad5 B32; +    CARD32	pad6 B32; +} xXF86DRICreateDrawableReply; +#define sz_xXF86DRICreateDrawableReply	32 + +typedef struct _XF86DRIDestroyDrawable { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRIDestroyDrawable */ +    CARD16	length B16; +    CARD32	screen B32; +    CARD32	drawable B32; +} xXF86DRIDestroyDrawableReq; +#define sz_xXF86DRIDestroyDrawableReq	12 + +typedef struct _XF86DRIGetDrawableInfo { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRIGetDrawableInfo */ +    CARD16	length B16; +    CARD32	screen B32; +    CARD32	drawable B32; +} xXF86DRIGetDrawableInfoReq; +#define sz_xXF86DRIGetDrawableInfoReq	12 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    CARD32	drawableTableIndex B32; +    CARD32	drawableTableStamp B32; +    INT16	drawableX B16; +    INT16	drawableY B16; +    INT16	drawableWidth B16; +    INT16	drawableHeight B16; +    CARD32	numClipRects B32; +    INT16       backX B16; +    INT16       backY B16; +    CARD32      numBackClipRects B32; +} xXF86DRIGetDrawableInfoReply; + +#define sz_xXF86DRIGetDrawableInfoReply	36 + + +typedef struct _XF86DRIGetDeviceInfo { +    CARD8	reqType;		/* always DRIReqCode */ +    CARD8	driReqType;		/* always X_DRIGetDeviceInfo */ +    CARD16	length B16; +    CARD32	screen B32; +} xXF86DRIGetDeviceInfoReq; +#define sz_xXF86DRIGetDeviceInfoReq	8 + +typedef struct { +    BYTE	type;			/* X_Reply */ +    BOOL	pad1; +    CARD16	sequenceNumber B16; +    CARD32	length B32; +    CARD32	hFrameBufferLow B32; +    CARD32	hFrameBufferHigh B32; +    CARD32	framebufferOrigin B32; +    CARD32	framebufferSize B32; +    CARD32	framebufferStride B32; +    CARD32	devPrivateSize B32; +} xXF86DRIGetDeviceInfoReply; +#define sz_xXF86DRIGetDeviceInfoReply	32 + +typedef struct _XF86DRIOpenFullScreen { +    CARD8       reqType;	/* always DRIReqCode */ +    CARD8       driReqType;	/* always X_DRIOpenFullScreen */ +    CARD16      length B16; +    CARD32      screen B32; +    CARD32      drawable B32; +} xXF86DRIOpenFullScreenReq; +#define sz_xXF86DRIOpenFullScreenReq    12 + +typedef struct { +    BYTE        type; +    BOOL        pad1; +    CARD16      sequenceNumber B16; +    CARD32      length B32; +    CARD32      isFullScreen B32; +    CARD32      pad2 B32; +    CARD32      pad3 B32; +    CARD32      pad4 B32; +    CARD32      pad5 B32; +    CARD32      pad6 B32; +} xXF86DRIOpenFullScreenReply; +#define sz_xXF86DRIOpenFullScreenReply  32 + +typedef struct _XF86DRICloseFullScreen { +    CARD8       reqType;	/* always DRIReqCode */ +    CARD8       driReqType;	/* always X_DRICloseFullScreen */ +    CARD16      length B16; +    CARD32      screen B32; +    CARD32      drawable B32; +} xXF86DRICloseFullScreenReq; +#define sz_xXF86DRICloseFullScreenReq   12 + +typedef struct { +    BYTE        type; +    BOOL        pad1; +    CARD16      sequenceNumber B16; +    CARD32      length B32; +    CARD32      pad2 B32; +    CARD32      pad3 B32; +    CARD32      pad4 B32; +    CARD32      pad5 B32; +    CARD32      pad6 B32; +    CARD32      pad7 B32; +} xXF86DRICloseFullScreenReply; +#define sz_xXF86DRICloseFullScreenReply  32 + + +#endif /* _XF86DRISTR_H_ */ diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 2f263cf06a..678c70e478 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -63,8 +63,10 @@ struct draw_context *draw_create( void )     if (!draw_pt_init( draw ))        goto fail; +#ifdef PIPE_ARCH_X86     if (!draw_vs_init( draw ))        goto fail; +#endif     return draw; diff --git a/src/gallium/drivers/nouveau/nouveau_bo.h b/src/gallium/drivers/nouveau/nouveau_bo.h new file mode 100644 index 0000000000..65b138283c --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_bo.h @@ -0,0 +1,53 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_BO_H__ +#define __NOUVEAU_BO_H__ + +/* Relocation/Buffer type flags */ +#define NOUVEAU_BO_VRAM  (1 << 0) +#define NOUVEAU_BO_GART  (1 << 1) +#define NOUVEAU_BO_RD    (1 << 2) +#define NOUVEAU_BO_WR    (1 << 3) +#define NOUVEAU_BO_RDWR  (NOUVEAU_BO_RD | NOUVEAU_BO_WR) +#define NOUVEAU_BO_MAP   (1 << 4) +#define NOUVEAU_BO_PIN   (1 << 5) +#define NOUVEAU_BO_LOW   (1 << 6) +#define NOUVEAU_BO_HIGH  (1 << 7) +#define NOUVEAU_BO_OR    (1 << 8) +#define NOUVEAU_BO_LOCAL (1 << 9) +#define NOUVEAU_BO_TILED (1 << 10) +#define NOUVEAU_BO_ZTILE (1 << 11) +#define NOUVEAU_BO_DUMMY (1 << 31) + +struct nouveau_bo { +	struct nouveau_device *device; +	uint64_t handle; + +	uint64_t size; +	void *map; + +	uint32_t flags; +	uint64_t offset; +}; + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_channel.h b/src/gallium/drivers/nouveau/nouveau_channel.h new file mode 100644 index 0000000000..cd99a676bd --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_channel.h @@ -0,0 +1,40 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_CHANNEL_H__ +#define __NOUVEAU_CHANNEL_H__ + +struct nouveau_channel { +	struct nouveau_device *device; +	int id; + +	struct nouveau_pushbuf *pushbuf; + +	struct nouveau_grobj *nullobj; +	struct nouveau_grobj *vram; +	struct nouveau_grobj *gart; + +	void *user_private; +	void (*hang_notify)(struct nouveau_channel *); +}; + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_class.h b/src/gallium/drivers/nouveau/nouveau_class.h new file mode 100644 index 0000000000..c3d8d7539d --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_class.h @@ -0,0 +1,6259 @@ +/************************************************************************* + +   Autogenerated file, do not edit ! + +************************************************************************** + +   Copyright (C) 2006-2008 : +   Dmitry Baryshkov, +   Laurent Carlier, +   Matthieu Castet, +   Dawid Gajownik, +   Jeremy Kolb, +   Stephane Loeuillet, +   Patrice Mandin, +   Stephane Marchesin, +   Serge Martin, +   Sylvain Munaut, +   Simon Raffeiner, +   Ben Skeggs, +   Erik Waling, +   koala_br, + +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 THE COPYRIGHT OWNER(S) 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. + +*************************************************************************/ + + +#ifndef NOUVEAU_REG_H +#define NOUVEAU_REG_H 1 + + +#define NV01_ROOT									0x00000001 + + + +#define NV01_CONTEXT_DMA								0x00000002 + + + +#define NV01_DEVICE									0x00000003 + + + +#define NV01_TIMER									0x00000004 + +#define  NV01_TIMER_SYNCHRONIZE								0x00000100 +#define  NV01_TIMER_STOP_ALARM								0x00000104 +#define  NV01_TIMER_DMA_NOTIFY								0x00000180 +#define  NV01_TIMER_TIME(x)								(0x00000300+((x)*4)) +#define  NV01_TIMER_TIME__SIZE								0x00000002 +#define  NV01_TIMER_ALARM_NOTIFY							0x00000308 + + +#define NV_IMAGE_STENCIL								0x00000010 + +#define  NV_IMAGE_STENCIL_NOTIFY							0x00000104 +#define  NV_IMAGE_STENCIL_DMA_NOTIFY							0x00000180 +#define  NV_IMAGE_STENCIL_IMAGE_OUTPUT							0x00000200 +#define  NV_IMAGE_STENCIL_IMAGE_INPUT(x)						(0x00000204+((x)*4)) +#define  NV_IMAGE_STENCIL_IMAGE_INPUT__SIZE						0x00000002 + + +#define NV_IMAGE_BLEND_AND								0x00000011 + +#define  NV_IMAGE_BLEND_AND_NOP								0x00000100 +#define  NV_IMAGE_BLEND_AND_NOTIFY							0x00000104 +#define  NV_IMAGE_BLEND_AND_DMA_NOTIFY							0x00000180 +#define  NV_IMAGE_BLEND_AND_IMAGE_OUTPUT						0x00000200 +#define  NV_IMAGE_BLEND_AND_BETA_INPUT							0x00000204 +#define  NV_IMAGE_BLEND_AND_IMAGE_INPUT							0x00000208 + + +#define NV01_CONTEXT_BETA1								0x00000012 + +#define  NV01_CONTEXT_BETA1_NOP								0x00000100 +#define  NV01_CONTEXT_BETA1_NOTIFY							0x00000104 +#define  NV01_CONTEXT_BETA1_DMA_NOTIFY							0x00000180 +#define  NV01_CONTEXT_BETA1_BETA_1D31							0x00000300 + + +#define NV_IMAGE_ROP_AND								0x00000013 + +#define  NV_IMAGE_ROP_AND_NOTIFY							0x00000104 +#define  NV_IMAGE_ROP_AND_DMA_NOTIFY							0x00000180 +#define  NV_IMAGE_ROP_AND_IMAGE_OUTPUT							0x00000200 +#define  NV_IMAGE_ROP_AND_ROP_INPUT							0x00000204 +#define  NV_IMAGE_ROP_AND_IMAGE_INPUT(x)						(0x00000208+((x)*4)) +#define  NV_IMAGE_ROP_AND_IMAGE_INPUT__SIZE						0x00000002 + + +#define NV_IMAGE_COLOR_KEY								0x00000015 + + + +#define NV01_CONTEXT_COLOR_KEY								0x00000017 + +#define  NV01_CONTEXT_COLOR_KEY_NOP							0x00000100 +#define  NV01_CONTEXT_COLOR_KEY_NOTIFY							0x00000104 +#define  NV01_CONTEXT_COLOR_KEY_DMA_NOTIFY						0x00000180 +#define  NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT						0x00000300 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X16A8Y8					0x00000001 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X24Y8					0x00000002 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X16A1R5G5B5				0x00000003 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X17R5G5B5					0x00000004 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_A8R8G8B8					0x00000005 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X8R8G8B8					0x00000006 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_A16Y16					0x00000007 +#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X16Y16					0x00000008 +#define  NV01_CONTEXT_COLOR_KEY_COLOR							0x00000304 + + +#define NV01_CONTEXT_PATTERN								0x00000018 + +#define  NV01_CONTEXT_PATTERN_NOP							0x00000100 +#define  NV01_CONTEXT_PATTERN_NOTIFY							0x00000104 +#define  NV01_CONTEXT_PATTERN_DMA_NOTIFY						0x00000180 +#define  NV01_CONTEXT_PATTERN_COLOR_FORMAT						0x00000300 +#define  NV01_CONTEXT_PATTERN_MONOCHROME_FORMAT						0x00000304 +#define  NV01_CONTEXT_PATTERN_SHAPE							0x00000308 +#define  NV01_CONTEXT_PATTERN_COLOR(x)							(0x00000310+((x)*4)) +#define  NV01_CONTEXT_PATTERN_COLOR__SIZE						0x00000002 +#define  NV01_CONTEXT_PATTERN_PATTERN(x)						(0x00000318+((x)*4)) +#define  NV01_CONTEXT_PATTERN_PATTERN__SIZE						0x00000002 + + +#define NV01_CONTEXT_CLIP_RECTANGLE							0x00000019 + +#define  NV01_CONTEXT_CLIP_RECTANGLE_NOP						0x00000100 +#define  NV01_CONTEXT_CLIP_RECTANGLE_NOTIFY						0x00000104 +#define  NV01_CONTEXT_CLIP_RECTANGLE_DMA_NOTIFY						0x00000180 +#define  NV01_CONTEXT_CLIP_RECTANGLE_POINT						0x00000300 +#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_X_SHIFT					0 +#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_X_MASK					0x0000ffff +#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_Y_SHIFT					16 +#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_Y_MASK					0xffff0000 +#define  NV01_CONTEXT_CLIP_RECTANGLE_SIZE						0x00000304 +#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_W_SHIFT					0 +#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_W_MASK					0x0000ffff +#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_H_SHIFT					16 +#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_H_MASK					0xffff0000 + + +#define NV01_RENDER_SOLID_LINE								0x0000001c + +#define  NV01_RENDER_SOLID_LINE_NOP							0x00000100 +#define  NV01_RENDER_SOLID_LINE_NOTIFY							0x00000104 +#define  NV01_RENDER_SOLID_LINE_PATCH							0x0000010c +#define  NV01_RENDER_SOLID_LINE_DMA_NOTIFY						0x00000180 +#define  NV01_RENDER_SOLID_LINE_CLIP_RECTANGLE						0x00000184 +#define  NV01_RENDER_SOLID_LINE_PATTERN							0x00000188 +#define  NV01_RENDER_SOLID_LINE_ROP							0x0000018c +#define  NV01_RENDER_SOLID_LINE_BETA1							0x00000190 +#define  NV01_RENDER_SOLID_LINE_SURFACE							0x00000194 +#define  NV01_RENDER_SOLID_LINE_OPERATION						0x000002fc +#define   NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY_AND					0x00000000 +#define   NV01_RENDER_SOLID_LINE_OPERATION_ROP_AND					0x00000001 +#define   NV01_RENDER_SOLID_LINE_OPERATION_BLEND_AND					0x00000002 +#define   NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY					0x00000003 +#define   NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY_PREMULT				0x00000004 +#define   NV01_RENDER_SOLID_LINE_OPERATION_BLEND_PREMULT				0x00000005 +#define  NV01_RENDER_SOLID_LINE_COLOR_FORMAT						0x00000300 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X16A8Y8					0x00000001 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X24Y8					0x00000002 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X16A1R5G5B5				0x00000003 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X17R5G5B5					0x00000004 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_A8R8G8B8					0x00000005 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X8R8G8B8					0x00000006 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_A16Y16					0x00000007 +#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X16Y16					0x00000008 +#define  NV01_RENDER_SOLID_LINE_COLOR							0x00000304 +#define  NV01_RENDER_SOLID_LINE_LINE_POINT0(x)						(0x00000400+((x)*8)) +#define  NV01_RENDER_SOLID_LINE_LINE_POINT0__SIZE					0x00000010 +#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_X_SHIFT					0 +#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_X_MASK					0x0000ffff +#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_Y_SHIFT					16 +#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_Y_MASK					0xffff0000 +#define  NV01_RENDER_SOLID_LINE_LINE_POINT1(x)						(0x00000404+((x)*8)) +#define  NV01_RENDER_SOLID_LINE_LINE_POINT1__SIZE					0x00000010 +#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_X_SHIFT					0 +#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_X_MASK					0x0000ffff +#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_Y_SHIFT					16 +#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_Y_MASK					0xffff0000 +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_X(x)					(0x00000480+((x)*16)) +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_X__SIZE					0x00000010 +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_Y(x)					(0x00000484+((x)*16)) +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_Y__SIZE					0x00000010 +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_X(x)					(0x00000488+((x)*16)) +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_X__SIZE					0x00000010 +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_Y(x)					(0x0000048c+((x)*16)) +#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_Y__SIZE					0x00000010 +#define  NV01_RENDER_SOLID_LINE_POLYLINE(x)						(0x00000500+((x)*4)) +#define  NV01_RENDER_SOLID_LINE_POLYLINE__SIZE						0x00000020 +#define   NV01_RENDER_SOLID_LINE_POLYLINE_X_SHIFT					0 +#define   NV01_RENDER_SOLID_LINE_POLYLINE_X_MASK					0x0000ffff +#define   NV01_RENDER_SOLID_LINE_POLYLINE_Y_SHIFT					16 +#define   NV01_RENDER_SOLID_LINE_POLYLINE_Y_MASK					0xffff0000 +#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_X(x)					(0x00000580+((x)*8)) +#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_X__SIZE				0x00000010 +#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_Y(x)					(0x00000584+((x)*8)) +#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_Y__SIZE				0x00000010 +#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_COLOR(x)					(0x00000600+((x)*8)) +#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_COLOR__SIZE					0x00000010 +#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT(x)					(0x00000604+((x)*8)) +#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT__SIZE					0x00000010 +#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_X_SHIFT				0 +#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_X_MASK					0x0000ffff +#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_Y_MASK					0xffff0000 + + +#define NV01_RENDER_SOLID_TRIANGLE							0x0000001d + +#define  NV01_RENDER_SOLID_TRIANGLE_NOP							0x00000100 +#define  NV01_RENDER_SOLID_TRIANGLE_NOTIFY						0x00000104 +#define  NV01_RENDER_SOLID_TRIANGLE_PATCH						0x0000010c +#define  NV01_RENDER_SOLID_TRIANGLE_DMA_NOTIFY						0x00000180 +#define  NV01_RENDER_SOLID_TRIANGLE_CLIP_RECTANGLE					0x00000184 +#define  NV01_RENDER_SOLID_TRIANGLE_PATTERN						0x00000188 +#define  NV01_RENDER_SOLID_TRIANGLE_ROP							0x0000018c +#define  NV01_RENDER_SOLID_TRIANGLE_BETA1						0x00000190 +#define  NV01_RENDER_SOLID_TRIANGLE_SURFACE						0x00000194 +#define  NV01_RENDER_SOLID_TRIANGLE_OPERATION						0x000002fc +#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY_AND				0x00000000 +#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_ROP_AND					0x00000001 +#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_BLEND_AND				0x00000002 +#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY					0x00000003 +#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY_PREMULT				0x00000004 +#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_BLEND_PREMULT				0x00000005 +#define  NV01_RENDER_SOLID_TRIANGLE_COLOR_FORMAT					0x00000300 +#define  NV01_RENDER_SOLID_TRIANGLE_COLOR						0x00000304 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0					0x00000310 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_X_SHIFT				0 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_Y_MASK				0xffff0000 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1					0x00000314 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_X_SHIFT				0 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_Y_MASK				0xffff0000 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2					0x00000318 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_X_SHIFT				0 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_Y_MASK				0xffff0000 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT0_X					0x00000320 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT0_Y					0x00000324 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT1_X					0x00000328 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT1_Y					0x0000032c +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT2_X					0x00000330 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT2_Y					0x00000334 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH(x)						(0x00000400+((x)*4)) +#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH__SIZE					0x00000020 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_X_SHIFT					0 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_X_MASK					0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_Y_SHIFT					16 +#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_Y_MASK					0xffff0000 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_X(x)				(0x00000480+((x)*8)) +#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_X__SIZE				0x00000010 +#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_Y(x)				(0x00000484+((x)*8)) +#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_Y__SIZE				0x00000010 +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_COLOR(x)					(0x00000500+((x)*16)) +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_COLOR__SIZE				0x00000008 +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0(x)					(0x00000504+((x)*16)) +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0__SIZE				0x00000008 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_X_SHIFT				0 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_Y_MASK				0xffff0000 +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1(x)					(0x00000508+((x)*16)) +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1__SIZE				0x00000008 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_X_SHIFT				0 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_Y_MASK				0xffff0000 +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2(x)					(0x0000050c+((x)*16)) +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2__SIZE				0x00000008 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_X_SHIFT				0 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_Y_MASK				0xffff0000 +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_COLOR(x)					(0x00000580+((x)*8)) +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_COLOR__SIZE				0x00000010 +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT(x)					(0x00000584+((x)*8)) +#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT__SIZE				0x00000010 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_X_SHIFT				0 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_Y_MASK				0xffff0000 + + +#define NV01_RENDER_SOLID_RECTANGLE							0x0000001e + +#define  NV01_RENDER_SOLID_RECTANGLE_NOP						0x00000100 +#define  NV01_RENDER_SOLID_RECTANGLE_NOTIFY						0x00000104 +#define  NV01_RENDER_SOLID_RECTANGLE_PATCH						0x0000010c +#define  NV01_RENDER_SOLID_RECTANGLE_DMA_NOTIFY						0x00000180 +#define  NV01_RENDER_SOLID_RECTANGLE_CLIP_RECTANGLE					0x00000184 +#define  NV01_RENDER_SOLID_RECTANGLE_PATTERN						0x00000188 +#define  NV01_RENDER_SOLID_RECTANGLE_ROP						0x0000018c +#define  NV01_RENDER_SOLID_RECTANGLE_BETA1						0x00000190 +#define  NV01_RENDER_SOLID_RECTANGLE_SURFACE						0x00000194 +#define  NV01_RENDER_SOLID_RECTANGLE_OPERATION						0x000002fc +#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY_AND				0x00000000 +#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_ROP_AND					0x00000001 +#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_BLEND_AND				0x00000002 +#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY					0x00000003 +#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY_PREMULT				0x00000004 +#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_BLEND_PREMULT				0x00000005 +#define  NV01_RENDER_SOLID_RECTANGLE_COLOR_FORMAT					0x00000300 +#define  NV01_RENDER_SOLID_RECTANGLE_COLOR						0x00000304 +#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT(x)					(0x00000400+((x)*8)) +#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT__SIZE				0x00000010 +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_X_SHIFT				0 +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_X_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_Y_SHIFT				16 +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_Y_MASK				0xffff0000 +#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE(x)					(0x00000404+((x)*8)) +#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE__SIZE				0x00000010 +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_W_SHIFT				0 +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_W_MASK				0x0000ffff +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_H_SHIFT				16 +#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_H_MASK				0xffff0000 + + +#define NV01_IMAGE_BLIT									0x0000001f + +#define  NV01_IMAGE_BLIT_NOP								0x00000100 +#define  NV01_IMAGE_BLIT_NOTIFY								0x00000104 +#define  NV01_IMAGE_BLIT_PATCH								0x0000010c +#define  NV01_IMAGE_BLIT_DMA_NOTIFY							0x00000180 +#define  NV01_IMAGE_BLIT_COLOR_KEY							0x00000184 +#define  NV01_IMAGE_BLIT_CLIP_RECTANGLE							0x00000188 +#define  NV01_IMAGE_BLIT_PATTERN							0x0000018c +#define  NV01_IMAGE_BLIT_ROP								0x00000190 +#define  NV01_IMAGE_BLIT_BETA1								0x00000194 +#define  NV01_IMAGE_BLIT_SURFACE							0x0000019c +#define  NV01_IMAGE_BLIT_OPERATION							0x000002fc +#define  NV01_IMAGE_BLIT_IMAGE_INPUT							0x00000204 +#define  NV01_IMAGE_BLIT_POINT_IN							0x00000300 +#define   NV01_IMAGE_BLIT_POINT_IN_X_SHIFT						0 +#define   NV01_IMAGE_BLIT_POINT_IN_X_MASK						0x0000ffff +#define   NV01_IMAGE_BLIT_POINT_IN_Y_SHIFT						16 +#define   NV01_IMAGE_BLIT_POINT_IN_Y_MASK						0xffff0000 +#define  NV01_IMAGE_BLIT_POINT_OUT							0x00000304 +#define   NV01_IMAGE_BLIT_POINT_OUT_X_SHIFT						0 +#define   NV01_IMAGE_BLIT_POINT_OUT_X_MASK						0x0000ffff +#define   NV01_IMAGE_BLIT_POINT_OUT_Y_SHIFT						16 +#define   NV01_IMAGE_BLIT_POINT_OUT_Y_MASK						0xffff0000 +#define  NV01_IMAGE_BLIT_SIZE								0x00000308 +#define   NV01_IMAGE_BLIT_SIZE_W_SHIFT							0 +#define   NV01_IMAGE_BLIT_SIZE_W_MASK							0x0000ffff +#define   NV01_IMAGE_BLIT_SIZE_H_SHIFT							16 +#define   NV01_IMAGE_BLIT_SIZE_H_MASK							0xffff0000 + + +#define NV01_IMAGE_FROM_CPU								0x00000021 + +#define  NV01_IMAGE_FROM_CPU_NOP							0x00000100 +#define  NV01_IMAGE_FROM_CPU_NOTIFY							0x00000104 +#define  NV01_IMAGE_FROM_CPU_PATCH							0x0000010c +#define  NV01_IMAGE_FROM_CPU_DMA_NOTIFY							0x00000180 +#define  NV01_IMAGE_FROM_CPU_COLOR_KEY							0x00000184 +#define  NV01_IMAGE_FROM_CPU_CLIP_RECTANGLE						0x00000188 +#define  NV01_IMAGE_FROM_CPU_PATTERN							0x0000018c +#define  NV01_IMAGE_FROM_CPU_ROP							0x00000190 +#define  NV01_IMAGE_FROM_CPU_BETA1							0x00000194 +#define  NV01_IMAGE_FROM_CPU_SURFACE							0x00000198 +#define  NV01_IMAGE_FROM_CPU_OPERATION							0x000002fc +#define   NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY_AND					0x00000000 +#define   NV01_IMAGE_FROM_CPU_OPERATION_ROP_AND						0x00000001 +#define   NV01_IMAGE_FROM_CPU_OPERATION_BLEND_AND					0x00000002 +#define   NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY						0x00000003 +#define   NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY_PREMULT					0x00000004 +#define   NV01_IMAGE_FROM_CPU_OPERATION_BLEND_PREMULT					0x00000005 +#define  NV01_IMAGE_FROM_CPU_COLOR_FORMAT						0x00000300 +#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_Y8						0x00000001 +#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_A1R5G5B5					0x00000002 +#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_X1R5G5B5					0x00000003 +#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_A8R8G8B8					0x00000004 +#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_X8R8G8B8					0x00000005 +#define  NV01_IMAGE_FROM_CPU_POINT							0x00000304 +#define   NV01_IMAGE_FROM_CPU_POINT_X_SHIFT						0 +#define   NV01_IMAGE_FROM_CPU_POINT_X_MASK						0x0000ffff +#define   NV01_IMAGE_FROM_CPU_POINT_Y_SHIFT						16 +#define   NV01_IMAGE_FROM_CPU_POINT_Y_MASK						0xffff0000 +#define  NV01_IMAGE_FROM_CPU_SIZE_OUT							0x00000308 +#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_W_SHIFT						0 +#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_W_MASK						0x0000ffff +#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_H_SHIFT						16 +#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_H_MASK						0xffff0000 +#define  NV01_IMAGE_FROM_CPU_SIZE_IN							0x0000030c +#define   NV01_IMAGE_FROM_CPU_SIZE_IN_W_SHIFT						0 +#define   NV01_IMAGE_FROM_CPU_SIZE_IN_W_MASK						0x0000ffff +#define   NV01_IMAGE_FROM_CPU_SIZE_IN_H_SHIFT						16 +#define   NV01_IMAGE_FROM_CPU_SIZE_IN_H_MASK						0xffff0000 +#define  NV01_IMAGE_FROM_CPU_COLOR(x)							(0x00000400+((x)*4)) +#define  NV01_IMAGE_FROM_CPU_COLOR__SIZE						0x00000020 + + +#define NV01_NULL									0x00000030 + + + +#define NV03_STRETCHED_IMAGE_FROM_CPU							0x00000036 + +#define  NV03_STRETCHED_IMAGE_FROM_CPU_NOP						0x00000100 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_NOTIFY						0x00000104 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_PATCH						0x0000010c +#define  NV03_STRETCHED_IMAGE_FROM_CPU_DMA_NOTIFY					0x00000180 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR_KEY					0x00000184 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_PATTERN						0x00000188 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_ROP						0x0000018c +#define  NV03_STRETCHED_IMAGE_FROM_CPU_BETA1						0x00000190 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_SURFACE						0x00000194 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_OPERATION					0x000002fc +#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR_FORMAT					0x00000300 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN						0x00000304 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_W_SHIFT					0 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_W_MASK					0x0000ffff +#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_H_SHIFT					16 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_H_MASK					0xffff0000 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_DX_DU						0x00000308 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_DY_DV						0x0000030c +#define  NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT					0x00000310 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_X_SHIFT				0 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_X_MASK				0x0000ffff +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_Y_SHIFT				16 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_Y_MASK				0xffff0000 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE					0x00000314 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_W_SHIFT				0 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_W_MASK				0x0000ffff +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_H_SHIFT				16 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_H_MASK				0xffff0000 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4					0x00000318 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_X_SHIFT				0 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_X_MASK				0x0000ffff +#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_Y_SHIFT				16 +#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_Y_MASK				0xffff0000 +#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR(x)						(0x00000400+((x)*4)) +#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR__SIZE					0x00000020 + + +#define NV03_SCALED_IMAGE_FROM_MEMORY							0x00000037 + +#define  NV03_SCALED_IMAGE_FROM_MEMORY_NOP						0x00000100 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_NOTIFY						0x00000104 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY					0x00000180 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE					0x00000184 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_PATTERN						0x00000188 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_ROP						0x0000018c +#define  NV03_SCALED_IMAGE_FROM_MEMORY_BETA1						0x00000190 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_SURFACE						0x00000194 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT					0x00000300 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5				0x00000001 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5				0x00000002 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8				0x00000003 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8				0x00000004 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8				0x00000005 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8				0x00000006 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5				0x00000007 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8					0x00000008 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8				0x00000009 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION					0x00000304 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_AND				0x00000000 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_ROP_AND				0x00000001 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_AND				0x00000002 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY				0x00000003 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_PREMULT			0x00000004 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_PREMULT				0x00000005 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT					0x00000308 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_SHIFT				0 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_MASK				0x0000ffff +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT				16 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_MASK				0xffff0000 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE					0x0000030c +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_SHIFT				0 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_MASK				0x0000ffff +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT				16 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_MASK				0xffff0000 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT					0x00000310 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_X_SHIFT				0 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_X_MASK				0x0000ffff +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_Y_SHIFT				16 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_Y_MASK				0xffff0000 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE					0x00000314 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_W_SHIFT				0 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_W_MASK				0x0000ffff +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_H_SHIFT				16 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_H_MASK				0xffff0000 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_DELTA_DU_DX					0x00000318 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_DELTA_DV_DY					0x0000031c +#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE					0x00000400 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_W_SHIFT				0 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_W_MASK				0x0000ffff +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_H_SHIFT				16 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_H_MASK				0xffff0000 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT					0x00000404 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_PITCH_SHIFT			0 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_PITCH_MASK			0x0000ffff +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_SHIFT			16 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_MASK			0x00ff0000 +#define    NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_CENTER			0x00010000 +#define    NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_CORNER			0x00020000 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_INTERPOLATOR_SHIFT		24 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_INTERPOLATOR_MASK		0xff000000 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_OFFSET					0x00000408 +#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT					0x0000040c +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_U_SHIFT				0 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_U_MASK				0x0000ffff +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_V_SHIFT				16 +#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_V_MASK				0xffff0000 + + +#define NV04_DVD_SUBPICTURE								0x00000038 + +#define  NV04_DVD_SUBPICTURE_NOP							0x00000100 +#define  NV04_DVD_SUBPICTURE_NOTIFY							0x00000104 +#define  NV04_DVD_SUBPICTURE_WAIT_FOR_IDLE						0x00000108 +#define  NV04_DVD_SUBPICTURE_DMA_NOTIFY							0x00000180 +#define  NV04_DVD_SUBPICTURE_DMA_OVERLAY						0x00000184 +#define  NV04_DVD_SUBPICTURE_DMA_IMAGEIN						0x00000188 +#define  NV04_DVD_SUBPICTURE_DMA_IMAGEOUT						0x0000018c +#define  NV04_DVD_SUBPICTURE_IMAGEOUT_POINT						0x00000300 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_X_SHIFT					0 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_X_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_Y_SHIFT					16 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_Y_MASK					0xffff0000 +#define  NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE						0x00000304 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_W_SHIFT					0 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_W_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_H_SHIFT					16 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_H_MASK					0xffff0000 +#define  NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT						0x00000308 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_PITCH_SHIFT				0 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_PITCH_MASK				0x0000ffff +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_COLOR_SHIFT				16 +#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_COLOR_MASK				0xffff0000 +#define  NV04_DVD_SUBPICTURE_IMAGEOUT_OFFSET						0x0000030c +#define  NV04_DVD_SUBPICTURE_IMAGEIN_DELTA_DU_DX					0x00000310 +#define  NV04_DVD_SUBPICTURE_IMAGEIN_DELTA_DV_DY					0x00000314 +#define  NV04_DVD_SUBPICTURE_IMAGEIN_SIZE						0x00000318 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_W_SHIFT					0 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_W_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_H_SHIFT					16 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_H_MASK					0xffff0000 +#define  NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT						0x0000031c +#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_PITCH_SHIFT				0 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_PITCH_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_COLOR_SHIFT				16 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_COLOR_MASK					0xffff0000 +#define  NV04_DVD_SUBPICTURE_IMAGEIN_OFFSET						0x00000320 +#define  NV04_DVD_SUBPICTURE_IMAGEIN_POINT						0x00000324 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_U_SHIFT					0 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_U_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_V_SHIFT					16 +#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_V_MASK					0xffff0000 +#define  NV04_DVD_SUBPICTURE_OVERLAY_DELTA_DU_DX					0x00000328 +#define  NV04_DVD_SUBPICTURE_OVERLAY_DELTA_DV_DY					0x0000032c +#define  NV04_DVD_SUBPICTURE_OVERLAY_SIZE						0x00000330 +#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_W_SHIFT					0 +#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_W_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_H_SHIFT					16 +#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_H_MASK					0xffff0000 +#define  NV04_DVD_SUBPICTURE_OVERLAY_FORMAT						0x00000334 +#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_PITCH_SHIFT				0 +#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_PITCH_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_COLOR_SHIFT				16 +#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_COLOR_MASK					0xffff0000 +#define  NV04_DVD_SUBPICTURE_OVERLAY_OFFSET						0x00000338 +#define  NV04_DVD_SUBPICTURE_OVERLAY_POINT						0x0000033c +#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_U_SHIFT					0 +#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_U_MASK					0x0000ffff +#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_V_SHIFT					16 +#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_V_MASK					0xffff0000 + + +#define NV04_MEMORY_TO_MEMORY_FORMAT							0x00000039 + +#define  NV04_MEMORY_TO_MEMORY_FORMAT_NOP						0x00000100 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY						0x00000104 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY					0x00000180 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN					0x00000184 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT					0x00000188 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN						0x0000030c +#define  NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT					0x00000310 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_IN						0x00000314 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT						0x00000318 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN					0x0000031c +#define  NV04_MEMORY_TO_MEMORY_FORMAT_LINE_COUNT					0x00000320 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT						0x00000324 +#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_INPUT_INC_SHIFT				0 +#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_INPUT_INC_MASK				0x0000000f +#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_OUTPUT_INC_SHIFT				8 +#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_OUTPUT_INC_MASK				0x00000f00 +#define  NV04_MEMORY_TO_MEMORY_FORMAT_BUF_NOTIFY					0x00000328 + + +#define NV01_MEMORY_LOCAL_BANKED							0x0000003d + + + +#define NV01_MAPPING_SYSTEM								0x0000003e + + + +#define NV03_MEMORY_LOCAL_CURSOR							0x0000003f + + + +#define NV01_MEMORY_LOCAL_LINEAR							0x00000040 + + + +#define NV01_MAPPING_LOCAL								0x00000041 + + + +#define NV04_CONTEXT_SURFACES_2D							0x00000042 + +#define  NV04_CONTEXT_SURFACES_2D_NOP							0x00000100 +#define  NV04_CONTEXT_SURFACES_2D_NOTIFY						0x00000104 +#define  NV04_CONTEXT_SURFACES_2D_PM_TRIGGER						0x00000140 +#define  NV04_CONTEXT_SURFACES_2D_DMA_NOTIFY						0x00000180 +#define  NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE					0x00000184 +#define  NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_DESTIN					0x00000188 +#define  NV04_CONTEXT_SURFACES_2D_FORMAT						0x00000300 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_Y8						0x00000001 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_Z1R5G5B5				0x00000002 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_X1R5G5B5				0x00000003 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5					0x00000004 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_Y16						0x00000005 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8				0x00000006 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_X8R8G8B8				0x00000007 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1A7R8G8B8_Z1A7R8G8B8				0x00000008 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1A7R8G8B8_X1A7R8G8B8				0x00000009 +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8					0x0000000a +#define   NV04_CONTEXT_SURFACES_2D_FORMAT_Y32						0x0000000b +#define  NV04_CONTEXT_SURFACES_2D_PITCH							0x00000304 +#define   NV04_CONTEXT_SURFACES_2D_PITCH_SOURCE_SHIFT					0 +#define   NV04_CONTEXT_SURFACES_2D_PITCH_SOURCE_MASK					0x0000ffff +#define   NV04_CONTEXT_SURFACES_2D_PITCH_DESTIN_SHIFT					16 +#define   NV04_CONTEXT_SURFACES_2D_PITCH_DESTIN_MASK					0xffff0000 +#define  NV04_CONTEXT_SURFACES_2D_OFFSET_SOURCE						0x00000308 +#define  NV04_CONTEXT_SURFACES_2D_OFFSET_DESTIN						0x0000030c + + +#define NV03_CONTEXT_ROP								0x00000043 + +#define  NV03_CONTEXT_ROP_NOP								0x00000100 +#define  NV03_CONTEXT_ROP_NOTIFY							0x00000104 +#define  NV03_CONTEXT_ROP_DMA_NOTIFY							0x00000180 +#define  NV03_CONTEXT_ROP_ROP								0x00000300 +#define   NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_SHIFT					0 +#define   NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_MASK					0x0000000f +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_CLEAR					0x00000000 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_NOR					0x00000001 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_AND_INVERTED				0x00000002 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_COPY_INVERTED				0x00000003 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_AND_REVERSE				0x00000004 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_INVERT					0x00000005 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_XOR					0x00000006 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_NAND					0x00000007 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_AND					0x00000008 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_EQUI					0x00000009 +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_NOOP					0x0000000a +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_OR_INVERTED				0x0000000b +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_COPY					0x0000000c +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_OR_REVERSE					0x0000000d +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_OR						0x0000000e +#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_SET					0x0000000f +#define   NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_SHIFT					4 +#define   NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_MASK					0x000000f0 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_CLEAR					0x00000000 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_NOR					0x00000010 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_AND_INVERTED				0x00000020 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_COPY_INVERTED				0x00000030 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_AND_REVERSE				0x00000040 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_INVERT					0x00000050 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_XOR					0x00000060 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_NAND					0x00000070 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_AND					0x00000080 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_EQUI					0x00000090 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_NOOP					0x000000a0 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_OR_INVERTED				0x000000b0 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_COPY					0x000000c0 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_OR_REVERSE					0x000000d0 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_OR						0x000000e0 +#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_SET					0x000000f0 + + +#define NV04_IMAGE_PATTERN								0x00000044 + +#define  NV04_IMAGE_PATTERN_NOP								0x00000100 +#define  NV04_IMAGE_PATTERN_NOTIFY							0x00000104 +#define  NV04_IMAGE_PATTERN_DMA_NOTIFY							0x00000180 +#define  NV04_IMAGE_PATTERN_COLOR_FORMAT						0x00000300 +#define   NV04_IMAGE_PATTERN_COLOR_FORMAT_A16R5G6B5					0x00000001 +#define   NV04_IMAGE_PATTERN_COLOR_FORMAT_X16A1R5G5B5					0x00000002 +#define   NV04_IMAGE_PATTERN_COLOR_FORMAT_A8R8G8B8					0x00000003 +#define  NV04_IMAGE_PATTERN_MONOCHROME_FORMAT						0x00000304 +#define   NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_CGA6					0x00000001 +#define   NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE					0x00000002 +#define  NV04_IMAGE_PATTERN_MONOCHROME_SHAPE						0x00000308 +#define   NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8					0x00000000 +#define   NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_64X1					0x00000001 +#define   NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_1X64					0x00000002 +#define  NV04_IMAGE_PATTERN_PATTERN_SELECT						0x0000030c +#define   NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO					0x00000001 +#define   NV04_IMAGE_PATTERN_PATTERN_SELECT_COLOR					0x00000002 +#define  NV04_IMAGE_PATTERN_MONOCHROME_COLOR0						0x00000310 +#define  NV04_IMAGE_PATTERN_MONOCHROME_COLOR1						0x00000314 +#define  NV04_IMAGE_PATTERN_MONOCHROME_PATTERN0						0x00000318 +#define  NV04_IMAGE_PATTERN_MONOCHROME_PATTERN1						0x0000031c +#define  NV04_IMAGE_PATTERN_PATTERN_Y8(x)						(0x00000400+((x)*4)) +#define  NV04_IMAGE_PATTERN_PATTERN_Y8__SIZE						0x00000010 +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y0_SHIFT					0 +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y0_MASK						0x000000ff +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y1_SHIFT					8 +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y1_MASK						0x0000ff00 +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y2_SHIFT					16 +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y2_MASK						0x00ff0000 +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y3_SHIFT					24 +#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y3_MASK						0xff000000 +#define  NV04_IMAGE_PATTERN_PATTERN_R5G6B5(x)						(0x00000500+((x)*4)) +#define  NV04_IMAGE_PATTERN_PATTERN_R5G6B5__SIZE					0x00000020 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B0_SHIFT					0 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B0_MASK					0x0000001f +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G0_SHIFT					5 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G0_MASK					0x000007e0 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R0_SHIFT					11 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R0_MASK					0x0000f800 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B1_SHIFT					16 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B1_MASK					0x001f0000 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G1_SHIFT					21 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G1_MASK					0x07e00000 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R1_SHIFT					27 +#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R1_MASK					0xf8000000 +#define  NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5(x)						(0x00000600+((x)*4)) +#define  NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5__SIZE					0x00000020 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B0_SHIFT					0 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B0_MASK					0x0000001f +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G0_SHIFT					5 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G0_MASK					0x000003e0 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R0_SHIFT					10 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R0_MASK					0x00007c00 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B1_SHIFT					16 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B1_MASK					0x001f0000 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G1_SHIFT					21 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G1_MASK					0x03e00000 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R1_SHIFT					26 +#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R1_MASK					0x7c000000 +#define  NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8(x)						(0x00000700+((x)*4)) +#define  NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8__SIZE					0x00000040 +#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_B_SHIFT					0 +#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_B_MASK					0x000000ff +#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_G_SHIFT					8 +#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_G_MASK					0x0000ff00 +#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_R_SHIFT					16 +#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_R_MASK					0x00ff0000 + + +#define NV03_VIDEO_LUT_CURSOR_DAC							0x00000046 + +#define  NV03_VIDEO_LUT_CURSOR_DAC_SYNCHRONIZE						0x00000100 +#define  NV03_VIDEO_LUT_CURSOR_DAC_STOP_IMAGE						0x00000104 +#define  NV03_VIDEO_LUT_CURSOR_DAC_STOP_CURSOR						0x00000108 +#define  NV03_VIDEO_LUT_CURSOR_DAC_STOP_DAC						0x0000010c +#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_NOTIFY						0x00000180 +#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_IMAGE(x)						(0x00000184+((x)*4)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_IMAGE__SIZE					0x00000002 +#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_LUT(x)						(0x0000018c+((x)*4)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_LUT__SIZE					0x00000002 +#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_CURSOR(x)					(0x00000194+((x)*4)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_CURSOR__SIZE					0x00000002 +#define  NV03_VIDEO_LUT_CURSOR_DAC_GET							0x000002fc +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_OFFSET(x)					(0x00000300+((x)*8)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_OFFSET__SIZE				0x00000002 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT(x)					(0x00000304+((x)*8)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT__SIZE				0x00000002 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_PITCH_SHIFT			0 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_PITCH_MASK				0x0000ffff +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_COLOR_SHIFT			16 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_COLOR_MASK				0x0fff0000 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_NOTIFY_SHIFT			28 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_NOTIFY_MASK			0xf0000000 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_OFFSET(x)					(0x00000340+((x)*12)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_OFFSET__SIZE				0x00000002 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT(x)				(0x00000344+((x)*12)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT__SIZE				0x00000002 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_X_SHIFT			0 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_X_MASK				0x0000ffff +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_Y_SHIFT			16 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_Y_MASK				0xffff0000 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_FORMAT(x)					(0x00000348+((x)*12)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_FORMAT__SIZE				0x00000002 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A				0x00000358 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_X_SHIFT			0 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_X_MASK			0x0000ffff +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_Y_SHIFT			16 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_Y_MASK			0xffff0000 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE(x)				(0x00000380+((x)*16)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE__SIZE				0x00000002 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_W_SHIFT				0 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_W_MASK				0x0000ffff +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_H_SHIFT				16 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_H_MASK				0xffff0000 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC(x)					(0x00000384+((x)*16)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC__SIZE					0x00000002 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_START_SHIFT				0 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_START_MASK				0x0000ffff +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_WIDTH_SHIFT				16 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_WIDTH_MASK				0x0fff0000 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_POLARITY_SHIFT			28 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_POLARITY_MASK				0xf0000000 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC(x)					(0x00000388+((x)*16)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC__SIZE					0x00000002 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_START_SHIFT				0 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_START_MASK				0x0000ffff +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_WIDTH_SHIFT				16 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_WIDTH_MASK				0x0fff0000 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_POLARITY_SHIFT			28 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_POLARITY_MASK				0xf0000000 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE(x)				(0x0000038c+((x)*16)) +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE__SIZE				0x00000002 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_WIDTH_SHIFT			0 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_WIDTH_MASK			0x0000ffff +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_HEIGHT_SHIFT			16 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_HEIGHT_MASK			0x0fff0000 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_NOTIFY_SHIFT			28 +#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_NOTIFY_MASK			0xf0000000 +#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_PIXEL_CLOCK					0x000003a0 + + +#define NV03_DX3_TEXTURED_TRIANGLE							0x00000048 + +#define  NV03_DX3_TEXTURED_TRIANGLE_NOP							0x00000100 +#define  NV03_DX3_TEXTURED_TRIANGLE_NOTIFY						0x00000104 +#define  NV03_DX3_TEXTURED_TRIANGLE_PATCH						0x0000010c +#define  NV03_DX3_TEXTURED_TRIANGLE_DMA_NOTIFY						0x00000180 +#define  NV03_DX3_TEXTURED_TRIANGLE_DMA_TEXTURE						0x00000184 +#define  NV03_DX3_TEXTURED_TRIANGLE_CLIP_RECTANGLE					0x00000188 +#define  NV03_DX3_TEXTURED_TRIANGLE_SURFACE						0x0000018c +#define  NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_OFFSET					0x00000304 +#define  NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT					0x00000308 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_MASK_SHIFT		0 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_MASK_MASK			0x0000ffff +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_ENABLE_SHIFT		16 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_ENABLE_MASK		0x000f0000 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_SHIFT				20 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_MASK				0x00f00000 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MIN_SHIFT			24 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MIN_MASK			0x0f000000 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MAX_SHIFT			28 +#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MAX_MASK			0xf0000000 +#define  NV03_DX3_TEXTURED_TRIANGLE_FILTER						0x0000030c +#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_X_SHIFT				0 +#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_X_MASK				0x0000001f +#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_Y_SHIFT				8 +#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_Y_MASK				0x00001f00 +#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SIZE_ADJUST_SHIFT				16 +#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SIZE_ADJUST_MASK				0x00ff0000 +#define  NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR						0x00000310 +#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_B_SHIFT					0 +#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_B_MASK					0x000000ff +#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_G_SHIFT					8 +#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_G_MASK					0x0000ff00 +#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_R_SHIFT					16 +#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_R_MASK					0x00ff0000 +#define  NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT						0x00000314 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_INTERPOLATOR_SHIFT			0 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_INTERPOLATOR_MASK			0x0000000f +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_U_SHIFT				4 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_U_MASK				0x00000030 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_V_SHIFT				6 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_V_MASK				0x000000c0 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_SOURCE_COLOR_SHIFT			8 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_SOURCE_COLOR_MASK			0x00000f00 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_CULLING_SHIFT				12 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_CULLING_MASK				0x00007000 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_PERSPECTIVE_ENABLE			(1 << 15) +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_FUNC_SHIFT				16 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_FUNC_MASK				0x000f0000 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_WRITE_ENABLE_SHIFT			20 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_WRITE_ENABLE_MASK			0x00f00000 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_COLOR_WRITE_ENABLE_SHIFT		24 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_COLOR_WRITE_ENABLE_MASK		0x07000000 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_ROP_SHIFT				27 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_ROP_MASK				0x18000000 +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_BETA					(1 << 29) +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_DST_BLEND				(1 << 30) +#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_SRC_BLEND				(1 << 31) +#define  NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL					0x00000318 +#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_REF_SHIFT			0 +#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_REF_MASK			0x000000ff +#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_FUNC_SHIFT			8 +#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_FUNC_MASK			0xffffff00 +#define  NV03_DX3_TEXTURED_TRIANGLE_SPECULAR(x)						(0x00001000+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_SPECULAR__SIZE					0x00000040 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I0_SHIFT					0 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I0_MASK					0x0000000f +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I1_SHIFT					4 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I1_MASK					0x000000f0 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I2_SHIFT					8 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I2_MASK					0x00000f00 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I3_SHIFT					12 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I3_MASK					0x0000f000 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I4_SHIFT					16 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I4_MASK					0x000f0000 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I5_SHIFT					20 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I5_MASK					0x00f00000 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_FOG_SHIFT					24 +#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_FOG_MASK					0xff000000 +#define  NV03_DX3_TEXTURED_TRIANGLE_COLOR(x)						(0x00001004+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_COLOR__SIZE						0x00000040 +#define  NV03_DX3_TEXTURED_TRIANGLE_X(x)						(0x00001008+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_X__SIZE						0x00000040 +#define  NV03_DX3_TEXTURED_TRIANGLE_Y(x)						(0x0000100c+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_Y__SIZE						0x00000040 +#define  NV03_DX3_TEXTURED_TRIANGLE_Z(x)						(0x00001010+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_Z__SIZE						0x00000040 +#define  NV03_DX3_TEXTURED_TRIANGLE_M(x)						(0x00001014+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_M__SIZE						0x00000040 +#define  NV03_DX3_TEXTURED_TRIANGLE_U(x)						(0x00001018+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_U__SIZE						0x00000040 +#define  NV03_DX3_TEXTURED_TRIANGLE_V(x)						(0x0000101c+((x)*32)) +#define  NV03_DX3_TEXTURED_TRIANGLE_V__SIZE						0x00000040 + + +#define NV04_GDI_RECTANGLE_TEXT								0x0000004a + +#define  NV04_GDI_RECTANGLE_TEXT_NOP							0x00000100 +#define  NV04_GDI_RECTANGLE_TEXT_NOTIFY							0x00000104 +#define  NV04_GDI_RECTANGLE_TEXT_PATCH							0x0000010c +#define  NV04_GDI_RECTANGLE_TEXT_PM_TRIGGER						0x00000140 +#define  NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY						0x00000180 +#define  NV04_GDI_RECTANGLE_TEXT_DMA_FONTS						0x00000184 +#define  NV04_GDI_RECTANGLE_TEXT_PATTERN						0x00000188 +#define  NV04_GDI_RECTANGLE_TEXT_ROP							0x0000018c +#define  NV04_GDI_RECTANGLE_TEXT_BETA1							0x00000190 +#define  NV04_GDI_RECTANGLE_TEXT_BETA4							0x00000194 +#define  NV04_GDI_RECTANGLE_TEXT_SURFACE						0x00000198 +#define  NV04_GDI_RECTANGLE_TEXT_OPERATION						0x000002fc +#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY_AND					0x00000000 +#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND					0x00000001 +#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_BLEND_AND					0x00000002 +#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY					0x00000003 +#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY_PREMULT				0x00000004 +#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_BLEND_PREMULT				0x00000005 +#define  NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT						0x00000300 +#define   NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5				0x00000001 +#define   NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_X16A1R5G5B5				0x00000002 +#define   NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8					0x00000003 +#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT					0x00000304 +#define   NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_CGA6				0x00000001 +#define   NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE					0x00000002 +#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_A						0x000003fc +#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(x)				(0x00000400+((x)*8)) +#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT__SIZE			0x00000020 +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_SHIFT			0 +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_MASK			0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_SHIFT			16 +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_MASK			0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE(x)				(0x00000404+((x)*8)) +#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE__SIZE				0x00000020 +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_SHIFT			0 +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_MASK			0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_SHIFT			16 +#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_MASK			0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0						0x000005f4 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_L_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_L_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_T_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_T_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1						0x000005f8 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_R_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_R_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_B_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_B_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_B						0x000005fc +#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0(x)				(0x00000600+((x)*8)) +#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0__SIZE			0x00000020 +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_SHIFT			0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_MASK			0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_SHIFT			16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_MASK			0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1(x)				(0x00000604+((x)*8)) +#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1__SIZE			0x00000020 +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_SHIFT			0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_MASK			0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_SHIFT			16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_MASK			0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0						0x000007ec +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1						0x000007f0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_C						0x000007f4 +#define  NV04_GDI_RECTANGLE_TEXT_SIZE_C							0x000007f8 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_W_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_W_MASK						0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_H_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_H_MASK						0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_POINT_C						0x000007fc +#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_X_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_X_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_Y_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_Y_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C(x)					(0x00000800+((x)*4)) +#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__SIZE				0x00000080 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0						0x00000be4 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1						0x00000be8 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_COLOR0_E						0x00000bec +#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_E						0x00000bf0 +#define  NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E						0x00000bf4 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E						0x00000bf8 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_POINT_E						0x00000bfc +#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_X_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_X_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_Y_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_Y_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E(x)				(0x00000c00+((x)*4)) +#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__SIZE				0x00000080 +#define  NV04_GDI_RECTANGLE_TEXT_FONT_F							0x00000ff0 +#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_OFFSET_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_OFFSET_MASK					0x0fffffff +#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_PITCH_SHIFT					28 +#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_PITCH_MASK					0xf0000000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0						0x00000ff4 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_L_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_L_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_T_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_T_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1						0x00000ff8 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_R_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_R_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_B_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_B_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_F						0x00000ffc +#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F(x)					(0x00001000+((x)*4)) +#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F__SIZE				0x00000100 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_INDEX_SHIFT			0 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_INDEX_MASK				0x000000ff +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_X_SHIFT				8 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_X_MASK				0x000fff00 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_Y_SHIFT				20 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_Y_MASK				0xfff00000 +#define  NV04_GDI_RECTANGLE_TEXT_FONT_G							0x000017f0 +#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_OFFSET_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_OFFSET_MASK					0x0fffffff +#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_PITCH_SHIFT					28 +#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_PITCH_MASK					0xf0000000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0						0x000017f4 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_L_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_L_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_T_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_T_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1						0x000017f8 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_R_SHIFT					0 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_R_MASK					0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_B_SHIFT					16 +#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_B_MASK					0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_G						0x000017fc +#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT(x)				(0x00001800+((x)*8)) +#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT__SIZE				0x00000100 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_X_SHIFT			0 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_X_MASK			0x0000ffff +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_Y_SHIFT			16 +#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_Y_MASK			0xffff0000 +#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_INDEX(x)				(0x00001804+((x)*8)) +#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_INDEX__SIZE				0x00000100 + + +#define NV03_GDI_RECTANGLE_TEXT								0x0000004b + +#define  NV03_GDI_RECTANGLE_TEXT_NOP							0x00000100 +#define  NV03_GDI_RECTANGLE_TEXT_NOTIFY							0x00000104 +#define  NV03_GDI_RECTANGLE_TEXT_DMA_NOTIFY						0x00000180 +#define  NV03_GDI_RECTANGLE_TEXT_PATTERN						0x00000184 +#define  NV03_GDI_RECTANGLE_TEXT_ROP							0x00000188 +#define  NV03_GDI_RECTANGLE_TEXT_BETA1							0x0000018c +#define  NV03_GDI_RECTANGLE_TEXT_SURFACE						0x00000190 +#define  NV03_GDI_RECTANGLE_TEXT_OPERATION						0x000002fc +#define  NV03_GDI_RECTANGLE_TEXT_COLOR_FORMAT						0x00000300 +#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT					0x00000304 +#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_A						0x000003fc +#define  NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT				0x00000400 +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_SHIFT			0 +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_MASK			0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_SHIFT			16 +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_MASK			0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE				0x00000404 +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_SHIFT			0 +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_MASK			0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_SHIFT			16 +#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_MASK			0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B						0x000007f4 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_L_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_L_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_T_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_T_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B						0x000007f8 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_R_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_R_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_B_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_B_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_B						0x000007fc +#define  NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0				0x00000800 +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_SHIFT			0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_MASK			0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_SHIFT			16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_MASK			0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1				0x00000804 +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_SHIFT			0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_MASK			0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_SHIFT			16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_MASK			0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0						0x00000bec +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1						0x00000bf0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_C						0x00000bf4 +#define  NV03_GDI_RECTANGLE_TEXT_SIZE_C							0x00000bf8 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_W_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_W_MASK						0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_H_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_H_MASK						0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_POINT_C						0x00000bfc +#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_X_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_X_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_Y_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_Y_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C(x)					(0x00000c00+((x)*4)) +#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__SIZE				0x00000020 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0						0x00000fe8 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_L_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_L_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_T_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_T_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1						0x00000fec +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_R_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_R_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_B_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_B_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_D						0x00000ff0 +#define  NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D						0x00000ff4 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_W_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_W_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_H_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_H_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D						0x00000ff8 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_W_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_W_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_H_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_H_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_POINT_D						0x00000ffc +#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_X_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_X_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_Y_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_Y_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_D(x)					(0x00001000+((x)*4)) +#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_D__SIZE				0x00000020 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0						0x000013e4 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1						0x000013e8 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_COLOR0_E						0x000013ec +#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_E						0x000013f0 +#define  NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E						0x000013f4 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E						0x000013f8 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_POINT_E						0x000013fc +#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_X_SHIFT					0 +#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_X_MASK					0x0000ffff +#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_Y_SHIFT					16 +#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_Y_MASK					0xffff0000 +#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E(x)				(0x00001400+((x)*4)) +#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__SIZE				0x00000020 + + +#define NV04_SWIZZLED_SURFACE								0x00000052 + +#define  NV04_SWIZZLED_SURFACE_NOP							0x00000100 +#define  NV04_SWIZZLED_SURFACE_NOTIFY							0x00000104 +#define  NV04_SWIZZLED_SURFACE_DMA_NOTIFY						0x00000180 +#define  NV04_SWIZZLED_SURFACE_DMA_IMAGE						0x00000184 +#define  NV04_SWIZZLED_SURFACE_FORMAT							0x00000300 +#define   NV04_SWIZZLED_SURFACE_FORMAT_COLOR_SHIFT					0 +#define   NV04_SWIZZLED_SURFACE_FORMAT_COLOR_MASK					0x000000ff +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8					0x00000001 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1R5G5B5_Z1R5G5B5				0x00000002 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1R5G5B5_X1R5G5B5				0x00000003 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5					0x00000004 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y16					0x00000005 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X8R8G8B8_Z8R8G8B8				0x00000006 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X8R8G8B8_X8R8G8B8				0x00000007 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1A7R8G8B8_Z1A7R8G8B8			0x00000008 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1A7R8G8B8_X1A7R8G8B8			0x00000009 +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8					0x0000000a +#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y32					0x0000000b +#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT				16 +#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_MASK					0x00ff0000 +#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT				24 +#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_MASK					0xff000000 +#define  NV04_SWIZZLED_SURFACE_OFFSET							0x00000304 + + +#define NV04_CONTEXT_SURFACES_3D							0x00000053 + +#define  NV04_CONTEXT_SURFACES_3D_NOP							0x00000100 +#define  NV04_CONTEXT_SURFACES_3D_NOTIFY						0x00000104 +#define  NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY						0x00000180 +#define  NV04_CONTEXT_SURFACES_3D_DMA_COLOR						0x00000184 +#define  NV04_CONTEXT_SURFACES_3D_DMA_ZETA						0x00000188 +#define  NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL					0x000002f8 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_X_SHIFT				0 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_X_MASK				0x0000ffff +#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_W_SHIFT				16 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_W_MASK				0xffff0000 +#define  NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL						0x000002fc +#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_Y_SHIFT				0 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_Y_MASK					0x0000ffff +#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_H_SHIFT				16 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_H_MASK					0xffff0000 +#define  NV04_CONTEXT_SURFACES_3D_FORMAT						0x00000300 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_SHIFT					0 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_MASK					0x000000ff +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1R5G5B5_Z1R5G5B5			0x00000001 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1R5G5B5_X1R5G5B5			0x00000002 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_R5G6B5					0x00000003 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X8R8G8B8_Z8R8G8B8			0x00000004 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X8R8G8B8_X8R8G8B8			0x00000005 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1A7R8G8B8_Z1A7R8G8B8			0x00000006 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1A7R8G8B8_X1A7R8G8B8			0x00000007 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_A8R8G8B8				0x00000008 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_SHIFT					8 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_MASK					0x0000ff00 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_PITCH					0x00000100 +#define    NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_SWIZZLE					0x00000200 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_U_SHIFT				16 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_U_MASK				0x00ff0000 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_V_SHIFT				24 +#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_V_MASK				0xff000000 +#define  NV04_CONTEXT_SURFACES_3D_CLIP_SIZE						0x00000304 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_W_SHIFT					0 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_W_MASK					0x0000ffff +#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_H_SHIFT					16 +#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_H_MASK					0xffff0000 +#define  NV04_CONTEXT_SURFACES_3D_PITCH							0x00000308 +#define   NV04_CONTEXT_SURFACES_3D_PITCH_COLOR_SHIFT					0 +#define   NV04_CONTEXT_SURFACES_3D_PITCH_COLOR_MASK					0x0000ffff +#define   NV04_CONTEXT_SURFACES_3D_PITCH_ZETA_SHIFT					16 +#define   NV04_CONTEXT_SURFACES_3D_PITCH_ZETA_MASK					0xffff0000 +#define  NV04_CONTEXT_SURFACES_3D_OFFSET_COLOR						0x0000030c +#define  NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA						0x00000310 + + +#define NV04_DX5_TEXTURED_TRIANGLE							0x00000054 + +#define  NV04_DX5_TEXTURED_TRIANGLE_NOP							0x00000100 +#define  NV04_DX5_TEXTURED_TRIANGLE_NOTIFY						0x00000104 +#define  NV04_DX5_TEXTURED_TRIANGLE_DMA_NOTIFY						0x00000180 +#define  NV04_DX5_TEXTURED_TRIANGLE_DMA_A						0x00000184 +#define  NV04_DX5_TEXTURED_TRIANGLE_DMA_B						0x00000188 +#define  NV04_DX5_TEXTURED_TRIANGLE_SURFACE						0x0000018c +#define  NV04_DX5_TEXTURED_TRIANGLE_COLORKEY						0x00000300 +#define  NV04_DX5_TEXTURED_TRIANGLE_OFFSET						0x00000304 +#define  NV04_DX5_TEXTURED_TRIANGLE_FORMAT						0x00000308 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_DMA_SHIFT					0 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_DMA_MASK					0x00000003 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_KEY_MATCH_SHIFT			2 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_KEY_MATCH_MASK			0x0000000c +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_SHIFT				4 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_MASK				0x00000030 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CENTER				0x00000010 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER				0x00000020 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_SHIFT				6 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_MASK				0x000000c0 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CENTER				0x00000040 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER				0x00000080 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_SHIFT					8 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_MASK					0x00000f00 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_Y8					0x00000100 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_A1R5G5B5				0x00000200 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_X1R5G5B5				0x00000300 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_A4R4G4B4				0x00000400 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_R5G6B5				0x00000500 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8				0x00000600 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_X8R8G8B8				0x00000700 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT				12 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_MASK				0x0000f000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT				16 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_MASK				0x000f0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT				20 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_MASK				0x00f00000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT				24 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MASK				0x07000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT				0x01000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT			0x02000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE			0x03000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER			0x04000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP				0x05000000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_WRAPU					(1 << 27) +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_SHIFT				28 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_MASK				0x70000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_REPEAT				0x10000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_MIRRORED_REPEAT			0x20000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE			0x30000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_BORDER			0x40000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP				0x50000000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_WRAPV					(1 << 31) +#define  NV04_DX5_TEXTURED_TRIANGLE_FILTER						0x0000030c +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_X_SHIFT				0 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_X_MASK				0x000000ff +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_Y_SHIFT				8 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_Y_MASK				0x00007f00 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MIPMAP_DITHER_ENABLE			(1 << 15) +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MIPMAP_LODBIAS_SHIFT			16 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MIPMAP_LODBIAS_MASK				0x00ff0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_SHIFT				24 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_MASK					0x07000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST				0x01000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR				0x02000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST		0x03000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST		0x04000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR		0x05000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR		0x06000000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE			(1 << 27) +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_SHIFT				28 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_MASK				0x70000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST				0x10000000 +#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR				0x20000000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE			(1 << 31) +#define  NV04_DX5_TEXTURED_TRIANGLE_BLEND						0x00000310 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_SHIFT				0 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_MASK				0x0000000f +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_MASK_BIT_SHIFT				4 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_MASK_BIT_MASK				0x00000030 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_SHIFT				6 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_MASK				0x000000c0 +#define    NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT				0x00000040 +#define    NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD				0x00000080 +#define    NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_PHONG				0x000000c0 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_SHIFT		8 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_MASK		0x00000f00 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE_SHIFT			12 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE_MASK				0x0000f000 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE_SHIFT				16 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE_MASK				0x000f0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_ALPHA_ENABLE_SHIFT				20 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_ALPHA_ENABLE_MASK				0x00f00000 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SRC_SHIFT					24 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SRC_MASK					0x0f000000 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_DST_SHIFT					28 +#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_DST_MASK					0xf0000000 +#define  NV04_DX5_TEXTURED_TRIANGLE_CONTROL						0x00000314 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_REF_SHIFT				0 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_REF_MASK				0x000000ff +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_SHIFT				8 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_MASK				0x00000f00 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_TEST_ENABLE				(1 << 12) +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ORIGIN					(1 << 13) +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_SHIFT				14 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_MASK				0x0000c000 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_SHIFT				16 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_MASK				0x000f0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_SHIFT				20 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_MASK				0x00300000 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE				(1 << 22) +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE			(1 << 23) +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_SHIFT			24 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_MASK			0x3f000000 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_SHIFT				30 +#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_MASK				0xc0000000 +#define  NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR						0x00000318 +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_B_SHIFT					0 +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_B_MASK					0x000000ff +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_G_SHIFT					8 +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_G_MASK					0x0000ff00 +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_R_SHIFT					16 +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_R_MASK					0x00ff0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_A_SHIFT					24 +#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_A_MASK					0xff000000 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(x)					(0x00000400+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX__SIZE					0x00000010 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SY(x)					(0x00000404+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SY__SIZE					0x00000010 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SZ(x)					(0x00000408+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SZ__SIZE					0x00000010 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_RHW(x)					(0x0000040c+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_RHW__SIZE					0x00000010 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR(x)					(0x00000410+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR__SIZE				0x00000010 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_B_SHIFT				0 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_B_MASK				0x000000ff +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_G_SHIFT				8 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_G_MASK				0x0000ff00 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_R_SHIFT				16 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_R_MASK				0x00ff0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_A_SHIFT				24 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_A_MASK				0xff000000 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR(x)				(0x00000414+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR__SIZE				0x00000010 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_B_SHIFT				0 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_B_MASK				0x000000ff +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_G_SHIFT				8 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_G_MASK				0x0000ff00 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_R_SHIFT				16 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_R_MASK				0x00ff0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_FOG_SHIFT			24 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_FOG_MASK				0xff000000 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TU(x)					(0x00000418+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TU__SIZE					0x00000010 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TV(x)					(0x0000041c+((x)*32)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TV__SIZE					0x00000010 +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(x)				(0x00000600+((x)*4)) +#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE__SIZE			0x00000040 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I0_SHIFT			0 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I0_MASK			0x0000000f +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I1_SHIFT			4 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I1_MASK			0x000000f0 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I2_SHIFT			8 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I2_MASK			0x00000f00 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I3_SHIFT			12 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I3_MASK			0x0000f000 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I4_SHIFT			16 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I4_MASK			0x000f0000 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I5_SHIFT			20 +#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I5_MASK			0x00f00000 + + +#define NV04_DX6_MULTITEX_TRIANGLE							0x00000055 + +#define  NV04_DX6_MULTITEX_TRIANGLE_NOP							0x00000100 +#define  NV04_DX6_MULTITEX_TRIANGLE_NOTIFY						0x00000104 +#define  NV04_DX6_MULTITEX_TRIANGLE_DMA_NOTIFY						0x00000180 +#define  NV04_DX6_MULTITEX_TRIANGLE_DMA_A						0x00000184 +#define  NV04_DX6_MULTITEX_TRIANGLE_DMA_B						0x00000188 +#define  NV04_DX6_MULTITEX_TRIANGLE_SURFACE						0x0000018c +#define  NV04_DX6_MULTITEX_TRIANGLE_OFFSET(x)						(0x00000308+((x)*4)) +#define  NV04_DX6_MULTITEX_TRIANGLE_OFFSET__SIZE					0x00000002 +#define  NV04_DX6_MULTITEX_TRIANGLE_FORMAT(x)						(0x00000310+((x)*4)) +#define  NV04_DX6_MULTITEX_TRIANGLE_FORMAT__SIZE					0x00000002 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_DMA_SHIFT					0 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_DMA_MASK					0x0000000f +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH_SHIFT				4 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH_MASK				0x00000030 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH_SHIFT				6 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH_MASK				0x000000c0 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_COLOR_SHIFT					8 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_COLOR_MASK					0x00000f00 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT				12 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_MIPMAP_LEVELS_MASK				0x0000f000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT				16 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_U_MASK				0x000f0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT				20 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_V_MASK				0x00f00000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_SHIFT				24 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_MASK				0x07000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_WRAPU					(1 << 27) +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_SHIFT				28 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_MASK				0x70000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_WRAPV					(1 << 31) +#define  NV04_DX6_MULTITEX_TRIANGLE_FILTER(x)						(0x00000318+((x)*4)) +#define  NV04_DX6_MULTITEX_TRIANGLE_FILTER__SIZE					0x00000002 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_X_SHIFT				0 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_X_MASK				0x000000ff +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_Y_SHIFT				8 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_Y_MASK				0x00007f00 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MIPMAP_DITHER_ENABLE			(1 << 15) +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MIPMAP_LODBIAS_SHIFT			16 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MIPMAP_LODBIAS_MASK				0x00ff0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MINIFY_SHIFT				24 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MINIFY_MASK					0x07000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE			(1 << 27) +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MAGNIFY_SHIFT				28 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MAGNIFY_MASK				0x70000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE			(1 << 31) +#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA					0x00000320 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE0				(1 <<  0) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA0				(1 <<  1) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT0_SHIFT			2 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT0_MASK			0x000000fc +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE1				(1 <<  8) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA1				(1 <<  9) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT1_SHIFT			10 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT1_MASK			0x0000fc00 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE2				(1 << 16) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA2				(1 << 17) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT2_SHIFT			18 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT2_MASK			0x00fc0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE3				(1 << 24) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA3				(1 << 25) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT3_SHIFT			26 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT3_MASK			0x1c000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_OPERATION_SHIFT			29 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_OPERATION_MASK			0xe0000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR					0x00000324 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE0				(1 <<  0) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA0				(1 <<  1) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT0_SHIFT			2 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT0_MASK			0x000000fc +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE1				(1 <<  8) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA1				(1 <<  9) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT1_SHIFT			10 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT1_MASK			0x0000fc00 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE2				(1 << 16) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA2				(1 << 17) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT2_SHIFT			18 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT2_MASK			0x00fc0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE3				(1 << 24) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA3				(1 << 25) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT3_SHIFT			26 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT3_MASK			0x1c000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_OPERATION_SHIFT			29 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_OPERATION_MASK			0xe0000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA					0x0000032c +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE0				(1 <<  0) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA0				(1 <<  1) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT0_SHIFT			2 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT0_MASK			0x000000fc +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE1				(1 <<  8) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA1				(1 <<  9) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT1_SHIFT			10 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT1_MASK			0x0000fc00 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE2				(1 << 16) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA2				(1 << 17) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT2_SHIFT			18 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT2_MASK			0x00fc0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE3				(1 << 24) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA3				(1 << 25) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT3_SHIFT			26 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT3_MASK			0x1c000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_OPERATION_SHIFT			29 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_OPERATION_MASK			0xe0000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR					0x00000330 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE0				(1 <<  0) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA0				(1 <<  1) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT0_SHIFT			2 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT0_MASK			0x000000fc +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE1				(1 <<  8) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA1				(1 <<  9) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT1_SHIFT			10 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT1_MASK			0x0000fc00 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE2				(1 << 16) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA2				(1 << 17) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT2_SHIFT			18 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT2_MASK			0x00fc0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE3				(1 << 24) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA3				(1 << 25) +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT3_SHIFT			26 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT3_MASK			0x1c000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_OPERATION_SHIFT			29 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_OPERATION_MASK			0xe0000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR					0x00000334 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_B_SHIFT				0 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_B_MASK				0x000000ff +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_G_SHIFT				8 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_G_MASK				0x0000ff00 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_R_SHIFT				16 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_R_MASK				0x00ff0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_A_SHIFT				24 +#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_A_MASK				0xff000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_BLEND						0x00000338 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_MASK_BIT_SHIFT				4 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_MASK_BIT_MASK				0x00000030 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_SHIFT				6 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_MASK				0x000000c0 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_SHIFT		8 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_MASK		0x00000f00 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE_SHIFT			12 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE_MASK				0x0000f000 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE_SHIFT				16 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE_MASK				0x000f0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_ALPHA_ENABLE_SHIFT				20 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_ALPHA_ENABLE_MASK				0x00f00000 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SRC_SHIFT					24 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SRC_MASK					0x0f000000 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_DST_SHIFT					28 +#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_DST_MASK					0xf0000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_CONTROL0						0x0000033c +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_REF_SHIFT				0 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_REF_MASK				0x000000ff +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_SHIFT				8 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_MASK				0x00000f00 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_TEST_ENABLE				(1 << 12) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ORIGIN					(1 << 13) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE_SHIFT				14 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE_MASK				0x0000c000 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_SHIFT				16 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_MASK				0x000f0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_SHIFT				20 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_MASK				0x00300000 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_DITHER_ENABLE				(1 << 22) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_PERSPECTIVE_ENABLE			(1 << 23) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_WRITE_ENABLE				(1 << 24) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE_ENABLE			(1 << 25) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE_ENABLE			(1 << 26) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE_ENABLE				(1 << 27) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE_ENABLE			(1 << 28) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE_ENABLE				(1 << 29) +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT_SHIFT				30 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT_MASK				0xc0000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_CONTROL1						0x00000340 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_TEST_ENABLE_SHIFT			0 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_TEST_ENABLE_MASK			0x0000000f +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_FUNC_SHIFT			4 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_FUNC_MASK				0x000000f0 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_REF_SHIFT				8 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_REF_MASK				0x0000ff00 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_READ_SHIFT			16 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_READ_MASK			0x00ff0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_WRITE_SHIFT			24 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_WRITE_MASK			0xff000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_CONTROL2						0x00000344 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_FAIL_SHIFT			0 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_FAIL_MASK			0x0000000f +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZFAIL_SHIFT			4 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZFAIL_MASK			0x000000f0 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZPASS_SHIFT			8 +#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZPASS_MASK			0x00000f00 +#define  NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR						0x00000348 +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_B_SHIFT					0 +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_B_MASK					0x000000ff +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_G_SHIFT					8 +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_G_MASK					0x0000ff00 +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_R_SHIFT					16 +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_R_MASK					0x00ff0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_A_SHIFT					24 +#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_A_MASK					0xff000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SX(x)					(0x00000400+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SX__SIZE					0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SY(x)					(0x00000404+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SY__SIZE					0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SZ(x)					(0x00000408+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SZ__SIZE					0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_RHW(x)					(0x0000040c+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_RHW__SIZE				0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR(x)					(0x00000410+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR__SIZE				0x00000008 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_B_SHIFT				0 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_B_MASK				0x000000ff +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_G_SHIFT				8 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_G_MASK				0x0000ff00 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_R_SHIFT				16 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_R_MASK				0x00ff0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_A_SHIFT				24 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_A_MASK				0xff000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR(x)				(0x00000414+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR__SIZE				0x00000008 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_B_SHIFT			0 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_B_MASK				0x000000ff +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_G_SHIFT			8 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_G_MASK				0x0000ff00 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_R_SHIFT			16 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_R_MASK				0x00ff0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_FOG_SHIFT			24 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_FOG_MASK			0xff000000 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU0(x)					(0x00000418+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU0__SIZE				0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV0(x)					(0x0000041c+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV0__SIZE				0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU1(x)					(0x00000420+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU1__SIZE				0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV1(x)					(0x00000424+((x)*40)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV1__SIZE				0x00000008 +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE(x)				(0x00000540+((x)*4)) +#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE__SIZE			0x00000030 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I0_SHIFT			0 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I0_MASK			0x0000000f +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I1_SHIFT			4 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I1_MASK			0x000000f0 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I2_SHIFT			8 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I2_MASK			0x00000f00 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I3_SHIFT			12 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I3_MASK			0x0000f000 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I4_SHIFT			16 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I4_MASK			0x000f0000 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I5_SHIFT			20 +#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I5_MASK			0x00f00000 + + +#define NV10_DX5_TEXTURED_TRIANGLE							0x00000094 + + + +#define NV10TCL										0x00000056 + +#define  NV10TCL_NOP									0x00000100 +#define  NV10TCL_NOTIFY									0x00000104 +#define  NV10TCL_DMA_NOTIFY								0x00000180 +#define  NV10TCL_DMA_IN_MEMORY0								0x00000184 +#define  NV10TCL_DMA_IN_MEMORY1								0x00000188 +#define  NV10TCL_DMA_VTXBUF0								0x0000018c +#define  NV10TCL_DMA_IN_MEMORY2								0x00000194 +#define  NV10TCL_DMA_IN_MEMORY3								0x00000198 +#define  NV10TCL_RT_HORIZ								0x00000200 +#define   NV10TCL_RT_HORIZ_X_SHIFT							0 +#define   NV10TCL_RT_HORIZ_X_MASK							0x0000ffff +#define   NV10TCL_RT_HORIZ_W_SHIFT							16 +#define   NV10TCL_RT_HORIZ_W_MASK							0xffff0000 +#define  NV10TCL_RT_VERT								0x00000204 +#define   NV10TCL_RT_VERT_Y_SHIFT							0 +#define   NV10TCL_RT_VERT_Y_MASK							0x0000ffff +#define   NV10TCL_RT_VERT_H_SHIFT							16 +#define   NV10TCL_RT_VERT_H_MASK							0xffff0000 +#define  NV10TCL_RT_FORMAT								0x00000208 +#define   NV10TCL_RT_FORMAT_TYPE_SHIFT							8 +#define   NV10TCL_RT_FORMAT_TYPE_MASK							0x00000f00 +#define    NV10TCL_RT_FORMAT_TYPE_LINEAR						0x00000100 +#define    NV10TCL_RT_FORMAT_TYPE_SWIZZLED						0x00000200 +#define   NV10TCL_RT_FORMAT_COLOR_SHIFT							0 +#define   NV10TCL_RT_FORMAT_COLOR_MASK							0x0000001f +#define    NV10TCL_RT_FORMAT_COLOR_R5G6B5						0x00000003 +#define    NV10TCL_RT_FORMAT_COLOR_X8R8G8B8						0x00000005 +#define    NV10TCL_RT_FORMAT_COLOR_A8R8G8B8						0x00000008 +#define    NV10TCL_RT_FORMAT_COLOR_B8							0x00000009 +#define    NV10TCL_RT_FORMAT_COLOR_X8B8G8R8						0x0000000f +#define    NV10TCL_RT_FORMAT_COLOR_A8B8G8R8						0x00000010 +#define  NV10TCL_RT_PITCH								0x0000020c +#define   NV10TCL_RT_PITCH_COLOR_PITCH_SHIFT						0 +#define   NV10TCL_RT_PITCH_COLOR_PITCH_MASK						0x0000ffff +#define   NV10TCL_RT_PITCH_ZETA_PITCH_SHIFT						16 +#define   NV10TCL_RT_PITCH_ZETA_PITCH_MASK						0xffff0000 +#define  NV10TCL_COLOR_OFFSET								0x00000210 +#define  NV10TCL_ZETA_OFFSET								0x00000214 +#define  NV10TCL_TX_OFFSET(x)								(0x00000218+((x)*4)) +#define  NV10TCL_TX_OFFSET__SIZE							0x00000002 +#define  NV10TCL_TX_FORMAT(x)								(0x00000220+((x)*4)) +#define  NV10TCL_TX_FORMAT__SIZE							0x00000002 +#define   NV10TCL_TX_FORMAT_DMA0							(1 <<  0) +#define   NV10TCL_TX_FORMAT_DMA1							(1 <<  1) +#define   NV10TCL_TX_FORMAT_CUBE_MAP							(1 <<  2) +#define   NV10TCL_TX_FORMAT_FORMAT_SHIFT						7 +#define   NV10TCL_TX_FORMAT_FORMAT_MASK							0x00000780 +#define    NV10TCL_TX_FORMAT_FORMAT_L8							0x00000000 +#define    NV10TCL_TX_FORMAT_FORMAT_A8							0x00000080 +#define    NV10TCL_TX_FORMAT_FORMAT_A1R5G5B5						0x00000100 +#define    NV10TCL_TX_FORMAT_FORMAT_A8_RECT						0x00000180 +#define    NV10TCL_TX_FORMAT_FORMAT_A4R4G4B4						0x00000200 +#define    NV10TCL_TX_FORMAT_FORMAT_R5G6B5						0x00000280 +#define    NV10TCL_TX_FORMAT_FORMAT_A8R8G8B8						0x00000300 +#define    NV10TCL_TX_FORMAT_FORMAT_X8R8G8B8						0x00000380 +#define    NV10TCL_TX_FORMAT_FORMAT_INDEX8						0x00000580 +#define    NV10TCL_TX_FORMAT_FORMAT_DXT1						0x00000600 +#define    NV10TCL_TX_FORMAT_FORMAT_DXT3						0x00000700 +#define    NV10TCL_TX_FORMAT_FORMAT_DXT5						0x00000780 +#define    NV10TCL_TX_FORMAT_FORMAT_A1R5G5B5_RECT					0x00000800 +#define    NV10TCL_TX_FORMAT_FORMAT_R5G6B5_RECT						0x00000880 +#define    NV10TCL_TX_FORMAT_FORMAT_A8R8G8B8_RECT					0x00000900 +#define    NV10TCL_TX_FORMAT_FORMAT_L8_RECT						0x00000980 +#define    NV10TCL_TX_FORMAT_FORMAT_A8L8						0x00000d00 +#define    NV10TCL_TX_FORMAT_FORMAT_A8_RECT2						0x00000d80 +#define    NV10TCL_TX_FORMAT_FORMAT_A4R4G4B4_RECT					0x00000e80 +#define    NV10TCL_TX_FORMAT_FORMAT_R8G8B8_RECT						0x00000f00 +#define    NV10TCL_TX_FORMAT_FORMAT_L8A8_RECT						0x00001000 +#define    NV10TCL_TX_FORMAT_FORMAT_A16							0x00001900 +#define    NV10TCL_TX_FORMAT_FORMAT_HILO16						0x00001980 +#define    NV10TCL_TX_FORMAT_FORMAT_A16_RECT						0x00001a80 +#define    NV10TCL_TX_FORMAT_FORMAT_HILO16_RECT						0x00001b00 +#define    NV10TCL_TX_FORMAT_FORMAT_HILO8						0x00002200 +#define    NV10TCL_TX_FORMAT_FORMAT_SIGNED_HILO8					0x00002280 +#define    NV10TCL_TX_FORMAT_FORMAT_HILO8_RECT						0x00002300 +#define    NV10TCL_TX_FORMAT_FORMAT_SIGNED_HILO8_RECT					0x00002380 +#define    NV10TCL_TX_FORMAT_FORMAT_FLOAT_RGBA16_NV					0x00002500 +#define    NV10TCL_TX_FORMAT_FORMAT_FLOAT_RGBA32_NV					0x00002580 +#define    NV10TCL_TX_FORMAT_FORMAT_FLOAT_R32_NV					0x00002600 +#define   NV10TCL_TX_FORMAT_NPOT							(1 << 11) +#define   NV10TCL_TX_FORMAT_MIPMAP_LEVELS_SHIFT						12 +#define   NV10TCL_TX_FORMAT_MIPMAP_LEVELS_MASK						0x0000f000 +#define   NV10TCL_TX_FORMAT_BASE_SIZE_U_SHIFT						16 +#define   NV10TCL_TX_FORMAT_BASE_SIZE_U_MASK						0x000f0000 +#define   NV10TCL_TX_FORMAT_BASE_SIZE_V_SHIFT						20 +#define   NV10TCL_TX_FORMAT_BASE_SIZE_V_MASK						0x00f00000 +#define   NV10TCL_TX_FORMAT_WRAP_S_SHIFT						24 +#define   NV10TCL_TX_FORMAT_WRAP_S_MASK							0x0f000000 +#define    NV10TCL_TX_FORMAT_WRAP_S_REPEAT						0x01000000 +#define    NV10TCL_TX_FORMAT_WRAP_S_MIRRORED_REPEAT					0x02000000 +#define    NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE					0x03000000 +#define    NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_BORDER					0x04000000 +#define    NV10TCL_TX_FORMAT_WRAP_S_CLAMP						0x05000000 +#define   NV10TCL_TX_FORMAT_WRAP_T_SHIFT						28 +#define   NV10TCL_TX_FORMAT_WRAP_T_MASK							0xf0000000 +#define    NV10TCL_TX_FORMAT_WRAP_T_REPEAT						0x10000000 +#define    NV10TCL_TX_FORMAT_WRAP_T_MIRRORED_REPEAT					0x20000000 +#define    NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE					0x30000000 +#define    NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_BORDER					0x40000000 +#define    NV10TCL_TX_FORMAT_WRAP_T_CLAMP						0x50000000 +#define  NV10TCL_TX_ENABLE(x)								(0x00000228+((x)*4)) +#define  NV10TCL_TX_ENABLE__SIZE							0x00000002 +#define   NV10TCL_TX_ENABLE_ANISOTROPY_SHIFT						4 +#define   NV10TCL_TX_ENABLE_ANISOTROPY_MASK						0x00000030 +#define   NV10TCL_TX_ENABLE_ENABLE							(1 << 30) +#define  NV10TCL_TX_NPOT_PITCH(x)							(0x00000230+((x)*4)) +#define  NV10TCL_TX_NPOT_PITCH__SIZE							0x00000002 +#define   NV10TCL_TX_NPOT_PITCH_PITCH_SHIFT						16 +#define   NV10TCL_TX_NPOT_PITCH_PITCH_MASK						0xffff0000 +#define  NV10TCL_TX_NPOT_SIZE(x)							(0x00000240+((x)*4)) +#define  NV10TCL_TX_NPOT_SIZE__SIZE							0x00000002 +#define   NV10TCL_TX_NPOT_SIZE_H_SHIFT							0 +#define   NV10TCL_TX_NPOT_SIZE_H_MASK							0x0000ffff +#define   NV10TCL_TX_NPOT_SIZE_W_SHIFT							16 +#define   NV10TCL_TX_NPOT_SIZE_W_MASK							0xffff0000 +#define  NV10TCL_TX_FILTER(x)								(0x00000248+((x)*4)) +#define  NV10TCL_TX_FILTER__SIZE							0x00000002 +#define   NV10TCL_TX_FILTER_MINIFY_SHIFT						24 +#define   NV10TCL_TX_FILTER_MINIFY_MASK							0x0f000000 +#define    NV10TCL_TX_FILTER_MINIFY_NEAREST						0x01000000 +#define    NV10TCL_TX_FILTER_MINIFY_LINEAR						0x02000000 +#define    NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST				0x03000000 +#define    NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST				0x04000000 +#define    NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR				0x05000000 +#define    NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR				0x06000000 +#define   NV10TCL_TX_FILTER_MAGNIFY_SHIFT						28 +#define   NV10TCL_TX_FILTER_MAGNIFY_MASK						0xf0000000 +#define    NV10TCL_TX_FILTER_MAGNIFY_NEAREST						0x10000000 +#define    NV10TCL_TX_FILTER_MAGNIFY_LINEAR						0x20000000 +#define  NV10TCL_TX_PALETTE_OFFSET(x)							(0x00000250+((x)*4)) +#define  NV10TCL_TX_PALETTE_OFFSET__SIZE						0x00000002 +#define  NV10TCL_RC_IN_ALPHA(x)								(0x00000260+((x)*4)) +#define  NV10TCL_RC_IN_ALPHA__SIZE							0x00000002 +#define   NV10TCL_RC_IN_ALPHA_D_INPUT_SHIFT						0 +#define   NV10TCL_RC_IN_ALPHA_D_INPUT_MASK						0x0000000f +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR0_NV				0x00000001 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR1_NV				0x00000002 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_FOG						0x00000003 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_PRIMARY_COLOR_NV					0x00000004 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SECONDARY_COLOR_NV				0x00000005 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_TEXTURE0_ARB					0x00000008 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_TEXTURE1_ARB					0x00000009 +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SPARE0_NV					0x0000000c +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SPARE1_NV					0x0000000d +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0000000e +#define    NV10TCL_RC_IN_ALPHA_D_INPUT_E_TIMES_F_NV					0x0000000f +#define   NV10TCL_RC_IN_ALPHA_D_COMPONENT_USAGE						(1 <<  4) +#define    NV10TCL_RC_IN_ALPHA_D_COMPONENT_USAGE_BLUE					0x00000000 +#define    NV10TCL_RC_IN_ALPHA_D_COMPONENT_USAGE_ALPHA					0x00000010 +#define   NV10TCL_RC_IN_ALPHA_D_MAPPING_SHIFT						5 +#define   NV10TCL_RC_IN_ALPHA_D_MAPPING_MASK						0x000000e0 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_UNSIGNED_INVERT_NV				0x00000020 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_EXPAND_NORMAL_NV				0x00000040 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_EXPAND_NEGATE_NV				0x00000060 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NORMAL_NV				0x00000080 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NEGATE_NV				0x000000a0 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_SIGNED_IDENTITY_NV				0x000000c0 +#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_SIGNED_NEGATE_NV				0x000000e0 +#define   NV10TCL_RC_IN_ALPHA_C_INPUT_SHIFT						8 +#define   NV10TCL_RC_IN_ALPHA_C_INPUT_MASK						0x00000f00 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR0_NV				0x00000100 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR1_NV				0x00000200 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_FOG						0x00000300 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_PRIMARY_COLOR_NV					0x00000400 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SECONDARY_COLOR_NV				0x00000500 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_TEXTURE0_ARB					0x00000800 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_TEXTURE1_ARB					0x00000900 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SPARE0_NV					0x00000c00 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SPARE1_NV					0x00000d00 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x00000e00 +#define    NV10TCL_RC_IN_ALPHA_C_INPUT_E_TIMES_F_NV					0x00000f00 +#define   NV10TCL_RC_IN_ALPHA_C_COMPONENT_USAGE						(1 << 12) +#define    NV10TCL_RC_IN_ALPHA_C_COMPONENT_USAGE_BLUE					0x00000000 +#define    NV10TCL_RC_IN_ALPHA_C_COMPONENT_USAGE_ALPHA					0x00001000 +#define   NV10TCL_RC_IN_ALPHA_C_MAPPING_SHIFT						13 +#define   NV10TCL_RC_IN_ALPHA_C_MAPPING_MASK						0x0000e000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_UNSIGNED_INVERT_NV				0x00002000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_EXPAND_NORMAL_NV				0x00004000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_EXPAND_NEGATE_NV				0x00006000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NORMAL_NV				0x00008000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NEGATE_NV				0x0000a000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_SIGNED_IDENTITY_NV				0x0000c000 +#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_SIGNED_NEGATE_NV				0x0000e000 +#define   NV10TCL_RC_IN_ALPHA_B_INPUT_SHIFT						16 +#define   NV10TCL_RC_IN_ALPHA_B_INPUT_MASK						0x000f0000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR0_NV				0x00010000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR1_NV				0x00020000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_FOG						0x00030000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_PRIMARY_COLOR_NV					0x00040000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SECONDARY_COLOR_NV				0x00050000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_TEXTURE0_ARB					0x00080000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_TEXTURE1_ARB					0x00090000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SPARE0_NV					0x000c0000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SPARE1_NV					0x000d0000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x000e0000 +#define    NV10TCL_RC_IN_ALPHA_B_INPUT_E_TIMES_F_NV					0x000f0000 +#define   NV10TCL_RC_IN_ALPHA_B_COMPONENT_USAGE						(1 << 20) +#define    NV10TCL_RC_IN_ALPHA_B_COMPONENT_USAGE_BLUE					0x00000000 +#define    NV10TCL_RC_IN_ALPHA_B_COMPONENT_USAGE_ALPHA					0x00100000 +#define   NV10TCL_RC_IN_ALPHA_B_MAPPING_SHIFT						21 +#define   NV10TCL_RC_IN_ALPHA_B_MAPPING_MASK						0x00e00000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_UNSIGNED_INVERT_NV				0x00200000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_EXPAND_NORMAL_NV				0x00400000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_EXPAND_NEGATE_NV				0x00600000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NORMAL_NV				0x00800000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NEGATE_NV				0x00a00000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_SIGNED_IDENTITY_NV				0x00c00000 +#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_SIGNED_NEGATE_NV				0x00e00000 +#define   NV10TCL_RC_IN_ALPHA_A_INPUT_SHIFT						24 +#define   NV10TCL_RC_IN_ALPHA_A_INPUT_MASK						0x0f000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR0_NV				0x01000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR1_NV				0x02000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_FOG						0x03000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_PRIMARY_COLOR_NV					0x04000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SECONDARY_COLOR_NV				0x05000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_TEXTURE0_ARB					0x08000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_TEXTURE1_ARB					0x09000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SPARE0_NV					0x0c000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SPARE1_NV					0x0d000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0e000000 +#define    NV10TCL_RC_IN_ALPHA_A_INPUT_E_TIMES_F_NV					0x0f000000 +#define   NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE						(1 << 28) +#define    NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE_BLUE					0x00000000 +#define    NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA					0x10000000 +#define   NV10TCL_RC_IN_ALPHA_A_MAPPING_SHIFT						29 +#define   NV10TCL_RC_IN_ALPHA_A_MAPPING_MASK						0xe0000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_UNSIGNED_INVERT_NV				0x20000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_EXPAND_NORMAL_NV				0x40000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_EXPAND_NEGATE_NV				0x60000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NORMAL_NV				0x80000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NEGATE_NV				0xa0000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_SIGNED_IDENTITY_NV				0xc0000000 +#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_SIGNED_NEGATE_NV				0xe0000000 +#define  NV10TCL_RC_IN_RGB(x)								(0x00000268+((x)*4)) +#define  NV10TCL_RC_IN_RGB__SIZE							0x00000002 +#define   NV10TCL_RC_IN_RGB_D_INPUT_SHIFT						0 +#define   NV10TCL_RC_IN_RGB_D_INPUT_MASK						0x0000000f +#define    NV10TCL_RC_IN_RGB_D_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_RGB_D_INPUT_CONSTANT_COLOR0_NV					0x00000001 +#define    NV10TCL_RC_IN_RGB_D_INPUT_CONSTANT_COLOR1_NV					0x00000002 +#define    NV10TCL_RC_IN_RGB_D_INPUT_FOG						0x00000003 +#define    NV10TCL_RC_IN_RGB_D_INPUT_PRIMARY_COLOR_NV					0x00000004 +#define    NV10TCL_RC_IN_RGB_D_INPUT_SECONDARY_COLOR_NV					0x00000005 +#define    NV10TCL_RC_IN_RGB_D_INPUT_TEXTURE0_ARB					0x00000008 +#define    NV10TCL_RC_IN_RGB_D_INPUT_TEXTURE1_ARB					0x00000009 +#define    NV10TCL_RC_IN_RGB_D_INPUT_SPARE0_NV						0x0000000c +#define    NV10TCL_RC_IN_RGB_D_INPUT_SPARE1_NV						0x0000000d +#define    NV10TCL_RC_IN_RGB_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0000000e +#define    NV10TCL_RC_IN_RGB_D_INPUT_E_TIMES_F_NV					0x0000000f +#define   NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE						(1 <<  4) +#define    NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE_ALPHA					0x00000010 +#define   NV10TCL_RC_IN_RGB_D_MAPPING_SHIFT						5 +#define   NV10TCL_RC_IN_RGB_D_MAPPING_MASK						0x000000e0 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_UNSIGNED_INVERT_NV				0x00000020 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_EXPAND_NORMAL_NV					0x00000040 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_EXPAND_NEGATE_NV					0x00000060 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_HALF_BIAS_NORMAL_NV				0x00000080 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_HALF_BIAS_NEGATE_NV				0x000000a0 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_SIGNED_IDENTITY_NV				0x000000c0 +#define    NV10TCL_RC_IN_RGB_D_MAPPING_SIGNED_NEGATE_NV					0x000000e0 +#define   NV10TCL_RC_IN_RGB_C_INPUT_SHIFT						8 +#define   NV10TCL_RC_IN_RGB_C_INPUT_MASK						0x00000f00 +#define    NV10TCL_RC_IN_RGB_C_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_RGB_C_INPUT_CONSTANT_COLOR0_NV					0x00000100 +#define    NV10TCL_RC_IN_RGB_C_INPUT_CONSTANT_COLOR1_NV					0x00000200 +#define    NV10TCL_RC_IN_RGB_C_INPUT_FOG						0x00000300 +#define    NV10TCL_RC_IN_RGB_C_INPUT_PRIMARY_COLOR_NV					0x00000400 +#define    NV10TCL_RC_IN_RGB_C_INPUT_SECONDARY_COLOR_NV					0x00000500 +#define    NV10TCL_RC_IN_RGB_C_INPUT_TEXTURE0_ARB					0x00000800 +#define    NV10TCL_RC_IN_RGB_C_INPUT_TEXTURE1_ARB					0x00000900 +#define    NV10TCL_RC_IN_RGB_C_INPUT_SPARE0_NV						0x00000c00 +#define    NV10TCL_RC_IN_RGB_C_INPUT_SPARE1_NV						0x00000d00 +#define    NV10TCL_RC_IN_RGB_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x00000e00 +#define    NV10TCL_RC_IN_RGB_C_INPUT_E_TIMES_F_NV					0x00000f00 +#define   NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE						(1 << 12) +#define    NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE_ALPHA					0x00001000 +#define   NV10TCL_RC_IN_RGB_C_MAPPING_SHIFT						13 +#define   NV10TCL_RC_IN_RGB_C_MAPPING_MASK						0x0000e000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_UNSIGNED_INVERT_NV				0x00002000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_EXPAND_NORMAL_NV					0x00004000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_EXPAND_NEGATE_NV					0x00006000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_HALF_BIAS_NORMAL_NV				0x00008000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_HALF_BIAS_NEGATE_NV				0x0000a000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_SIGNED_IDENTITY_NV				0x0000c000 +#define    NV10TCL_RC_IN_RGB_C_MAPPING_SIGNED_NEGATE_NV					0x0000e000 +#define   NV10TCL_RC_IN_RGB_B_INPUT_SHIFT						16 +#define   NV10TCL_RC_IN_RGB_B_INPUT_MASK						0x000f0000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_CONSTANT_COLOR0_NV					0x00010000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_CONSTANT_COLOR1_NV					0x00020000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_FOG						0x00030000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_PRIMARY_COLOR_NV					0x00040000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_SECONDARY_COLOR_NV					0x00050000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_TEXTURE0_ARB					0x00080000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_TEXTURE1_ARB					0x00090000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_SPARE0_NV						0x000c0000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_SPARE1_NV						0x000d0000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x000e0000 +#define    NV10TCL_RC_IN_RGB_B_INPUT_E_TIMES_F_NV					0x000f0000 +#define   NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE						(1 << 20) +#define    NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_ALPHA					0x00100000 +#define   NV10TCL_RC_IN_RGB_B_MAPPING_SHIFT						21 +#define   NV10TCL_RC_IN_RGB_B_MAPPING_MASK						0x00e00000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_UNSIGNED_INVERT_NV				0x00200000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_EXPAND_NORMAL_NV					0x00400000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_EXPAND_NEGATE_NV					0x00600000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_HALF_BIAS_NORMAL_NV				0x00800000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_HALF_BIAS_NEGATE_NV				0x00a00000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_SIGNED_IDENTITY_NV				0x00c00000 +#define    NV10TCL_RC_IN_RGB_B_MAPPING_SIGNED_NEGATE_NV					0x00e00000 +#define   NV10TCL_RC_IN_RGB_A_INPUT_SHIFT						24 +#define   NV10TCL_RC_IN_RGB_A_INPUT_MASK						0x0f000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_CONSTANT_COLOR0_NV					0x01000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_CONSTANT_COLOR1_NV					0x02000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_FOG						0x03000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_PRIMARY_COLOR_NV					0x04000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_SECONDARY_COLOR_NV					0x05000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE0_ARB					0x08000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE1_ARB					0x09000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_SPARE0_NV						0x0c000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_SPARE1_NV						0x0d000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0e000000 +#define    NV10TCL_RC_IN_RGB_A_INPUT_E_TIMES_F_NV					0x0f000000 +#define   NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE						(1 << 28) +#define    NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA					0x10000000 +#define   NV10TCL_RC_IN_RGB_A_MAPPING_SHIFT						29 +#define   NV10TCL_RC_IN_RGB_A_MAPPING_MASK						0xe0000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_UNSIGNED_INVERT_NV				0x20000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_EXPAND_NORMAL_NV					0x40000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_EXPAND_NEGATE_NV					0x60000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_HALF_BIAS_NORMAL_NV				0x80000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_HALF_BIAS_NEGATE_NV				0xa0000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_SIGNED_IDENTITY_NV				0xc0000000 +#define    NV10TCL_RC_IN_RGB_A_MAPPING_SIGNED_NEGATE_NV					0xe0000000 +#define  NV10TCL_RC_COLOR(x)								(0x00000270+((x)*4)) +#define  NV10TCL_RC_COLOR__SIZE								0x00000002 +#define   NV10TCL_RC_COLOR_B_SHIFT							0 +#define   NV10TCL_RC_COLOR_B_MASK							0x000000ff +#define   NV10TCL_RC_COLOR_G_SHIFT							8 +#define   NV10TCL_RC_COLOR_G_MASK							0x0000ff00 +#define   NV10TCL_RC_COLOR_R_SHIFT							16 +#define   NV10TCL_RC_COLOR_R_MASK							0x00ff0000 +#define   NV10TCL_RC_COLOR_A_SHIFT							24 +#define   NV10TCL_RC_COLOR_A_MASK							0xff000000 +#define  NV10TCL_RC_OUT_ALPHA(x)							(0x00000278+((x)*4)) +#define  NV10TCL_RC_OUT_ALPHA__SIZE							0x00000002 +#define   NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SHIFT						0 +#define   NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_MASK						0x0000000f +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_ZERO						0x00000000 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR0_NV				0x00000001 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR1_NV				0x00000002 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_FOG						0x00000003 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_PRIMARY_COLOR_NV				0x00000004 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SECONDARY_COLOR_NV				0x00000005 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE0_ARB					0x00000008 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE1_ARB					0x00000009 +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SPARE0_NV					0x0000000c +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SPARE1_NV					0x0000000d +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV		0x0000000e +#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_E_TIMES_F_NV					0x0000000f +#define   NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SHIFT						4 +#define   NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_MASK						0x000000f0 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_ZERO						0x00000000 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR0_NV				0x00000010 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR1_NV				0x00000020 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_FOG						0x00000030 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_PRIMARY_COLOR_NV				0x00000040 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SECONDARY_COLOR_NV				0x00000050 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE0_ARB					0x00000080 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE1_ARB					0x00000090 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SPARE0_NV					0x000000c0 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SPARE1_NV					0x000000d0 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV		0x000000e0 +#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_E_TIMES_F_NV					0x000000f0 +#define   NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SHIFT						8 +#define   NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_MASK						0x00000f00 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_ZERO						0x00000000 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR0_NV				0x00000100 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR1_NV				0x00000200 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_FOG						0x00000300 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_PRIMARY_COLOR_NV				0x00000400 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SECONDARY_COLOR_NV				0x00000500 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE0_ARB					0x00000800 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE1_ARB					0x00000900 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0_NV					0x00000c00 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SPARE1_NV					0x00000d00 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV		0x00000e00 +#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_E_TIMES_F_NV					0x00000f00 +#define   NV10TCL_RC_OUT_ALPHA_CD_DOT_PRODUCT						(1 << 12) +#define   NV10TCL_RC_OUT_ALPHA_AB_DOT_PRODUCT						(1 << 13) +#define   NV10TCL_RC_OUT_ALPHA_MUX_SUM							(1 << 14) +#define   NV10TCL_RC_OUT_ALPHA_BIAS							(1 << 15) +#define    NV10TCL_RC_OUT_ALPHA_BIAS_NONE						0x00000000 +#define    NV10TCL_RC_OUT_ALPHA_BIAS_BIAS_BY_NEGATIVE_ONE_HALF_NV			0x00008000 +#define   NV10TCL_RC_OUT_ALPHA_SCALE_SHIFT						17 +#define   NV10TCL_RC_OUT_ALPHA_SCALE_MASK						0x00000000 +#define    NV10TCL_RC_OUT_ALPHA_SCALE_NONE						0x00000000 +#define    NV10TCL_RC_OUT_ALPHA_SCALE_SCALE_BY_TWO_NV					0x00020000 +#define    NV10TCL_RC_OUT_ALPHA_SCALE_SCALE_BY_FOUR_NV					0x00040000 +#define    NV10TCL_RC_OUT_ALPHA_SCALE_SCALE_BY_ONE_HALF_NV				0x00060000 +#define  NV10TCL_RC_OUT_RGB(x)								(0x00000280+((x)*4)) +#define  NV10TCL_RC_OUT_RGB__SIZE							0x00000002 +#define   NV10TCL_RC_OUT_RGB_CD_OUTPUT_SHIFT						0 +#define   NV10TCL_RC_OUT_RGB_CD_OUTPUT_MASK						0x0000000f +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_ZERO						0x00000000 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR0_NV				0x00000001 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR1_NV				0x00000002 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_FOG						0x00000003 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_PRIMARY_COLOR_NV				0x00000004 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SECONDARY_COLOR_NV				0x00000005 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_TEXTURE0_ARB					0x00000008 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_TEXTURE1_ARB					0x00000009 +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SPARE0_NV					0x0000000c +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SPARE1_NV					0x0000000d +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0000000e +#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_E_TIMES_F_NV					0x0000000f +#define   NV10TCL_RC_OUT_RGB_AB_OUTPUT_SHIFT						4 +#define   NV10TCL_RC_OUT_RGB_AB_OUTPUT_MASK						0x000000f0 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_ZERO						0x00000000 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR0_NV				0x00000010 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR1_NV				0x00000020 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_FOG						0x00000030 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_PRIMARY_COLOR_NV				0x00000040 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SECONDARY_COLOR_NV				0x00000050 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_TEXTURE0_ARB					0x00000080 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_TEXTURE1_ARB					0x00000090 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE0_NV					0x000000c0 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE1_NV					0x000000d0 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x000000e0 +#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_E_TIMES_F_NV					0x000000f0 +#define   NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SHIFT						8 +#define   NV10TCL_RC_OUT_RGB_SUM_OUTPUT_MASK						0x00000f00 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_ZERO						0x00000000 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR0_NV				0x00000100 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR1_NV				0x00000200 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_FOG						0x00000300 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_PRIMARY_COLOR_NV				0x00000400 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SECONDARY_COLOR_NV				0x00000500 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_TEXTURE0_ARB					0x00000800 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_TEXTURE1_ARB					0x00000900 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SPARE0_NV					0x00000c00 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SPARE1_NV					0x00000d00 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x00000e00 +#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_E_TIMES_F_NV					0x00000f00 +#define   NV10TCL_RC_OUT_RGB_CD_DOT_PRODUCT						(1 << 12) +#define   NV10TCL_RC_OUT_RGB_AB_DOT_PRODUCT						(1 << 13) +#define   NV10TCL_RC_OUT_RGB_MUX_SUM							(1 << 14) +#define   NV10TCL_RC_OUT_RGB_BIAS							(1 << 15) +#define    NV10TCL_RC_OUT_RGB_BIAS_NONE							0x00000000 +#define    NV10TCL_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF_NV				0x00008000 +#define   NV10TCL_RC_OUT_RGB_SCALE_SHIFT						17 +#define   NV10TCL_RC_OUT_RGB_SCALE_MASK							0x00000000 +#define    NV10TCL_RC_OUT_RGB_SCALE_NONE						0x00000000 +#define    NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_TWO_NV					0x00020000 +#define    NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_FOUR_NV					0x00040000 +#define    NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_ONE_HALF_NV				0x00060000 +#define   NV10TCL_RC_OUT_RGB_OPERATION_SHIFT						27 +#define   NV10TCL_RC_OUT_RGB_OPERATION_MASK						0x38000000 +#define  NV10TCL_RC_FINAL0								0x00000288 +#define   NV10TCL_RC_FINAL0_D_INPUT_SHIFT						0 +#define   NV10TCL_RC_FINAL0_D_INPUT_MASK						0x0000000f +#define    NV10TCL_RC_FINAL0_D_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_FINAL0_D_INPUT_CONSTANT_COLOR0_NV					0x00000001 +#define    NV10TCL_RC_FINAL0_D_INPUT_CONSTANT_COLOR1_NV					0x00000002 +#define    NV10TCL_RC_FINAL0_D_INPUT_FOG						0x00000003 +#define    NV10TCL_RC_FINAL0_D_INPUT_PRIMARY_COLOR_NV					0x00000004 +#define    NV10TCL_RC_FINAL0_D_INPUT_SECONDARY_COLOR_NV					0x00000005 +#define    NV10TCL_RC_FINAL0_D_INPUT_TEXTURE0_ARB					0x00000008 +#define    NV10TCL_RC_FINAL0_D_INPUT_TEXTURE1_ARB					0x00000009 +#define    NV10TCL_RC_FINAL0_D_INPUT_SPARE0_NV						0x0000000c +#define    NV10TCL_RC_FINAL0_D_INPUT_SPARE1_NV						0x0000000d +#define    NV10TCL_RC_FINAL0_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0000000e +#define    NV10TCL_RC_FINAL0_D_INPUT_E_TIMES_F_NV					0x0000000f +#define   NV10TCL_RC_FINAL0_D_COMPONENT_USAGE						(1 <<  4) +#define    NV10TCL_RC_FINAL0_D_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_FINAL0_D_COMPONENT_USAGE_ALPHA					0x00000010 +#define   NV10TCL_RC_FINAL0_D_MAPPING_SHIFT						5 +#define   NV10TCL_RC_FINAL0_D_MAPPING_MASK						0x000000e0 +#define    NV10TCL_RC_FINAL0_D_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_FINAL0_D_MAPPING_UNSIGNED_INVERT_NV				0x00000020 +#define    NV10TCL_RC_FINAL0_D_MAPPING_EXPAND_NORMAL_NV					0x00000040 +#define    NV10TCL_RC_FINAL0_D_MAPPING_EXPAND_NEGATE_NV					0x00000060 +#define    NV10TCL_RC_FINAL0_D_MAPPING_HALF_BIAS_NORMAL_NV				0x00000080 +#define    NV10TCL_RC_FINAL0_D_MAPPING_HALF_BIAS_NEGATE_NV				0x000000a0 +#define    NV10TCL_RC_FINAL0_D_MAPPING_SIGNED_IDENTITY_NV				0x000000c0 +#define    NV10TCL_RC_FINAL0_D_MAPPING_SIGNED_NEGATE_NV					0x000000e0 +#define   NV10TCL_RC_FINAL0_C_INPUT_SHIFT						8 +#define   NV10TCL_RC_FINAL0_C_INPUT_MASK						0x00000f00 +#define    NV10TCL_RC_FINAL0_C_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_FINAL0_C_INPUT_CONSTANT_COLOR0_NV					0x00000100 +#define    NV10TCL_RC_FINAL0_C_INPUT_CONSTANT_COLOR1_NV					0x00000200 +#define    NV10TCL_RC_FINAL0_C_INPUT_FOG						0x00000300 +#define    NV10TCL_RC_FINAL0_C_INPUT_PRIMARY_COLOR_NV					0x00000400 +#define    NV10TCL_RC_FINAL0_C_INPUT_SECONDARY_COLOR_NV					0x00000500 +#define    NV10TCL_RC_FINAL0_C_INPUT_TEXTURE0_ARB					0x00000800 +#define    NV10TCL_RC_FINAL0_C_INPUT_TEXTURE1_ARB					0x00000900 +#define    NV10TCL_RC_FINAL0_C_INPUT_SPARE0_NV						0x00000c00 +#define    NV10TCL_RC_FINAL0_C_INPUT_SPARE1_NV						0x00000d00 +#define    NV10TCL_RC_FINAL0_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x00000e00 +#define    NV10TCL_RC_FINAL0_C_INPUT_E_TIMES_F_NV					0x00000f00 +#define   NV10TCL_RC_FINAL0_C_COMPONENT_USAGE						(1 << 12) +#define    NV10TCL_RC_FINAL0_C_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_FINAL0_C_COMPONENT_USAGE_ALPHA					0x00001000 +#define   NV10TCL_RC_FINAL0_C_MAPPING_SHIFT						13 +#define   NV10TCL_RC_FINAL0_C_MAPPING_MASK						0x0000e000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_UNSIGNED_INVERT_NV				0x00002000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_EXPAND_NORMAL_NV					0x00004000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_EXPAND_NEGATE_NV					0x00006000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_HALF_BIAS_NORMAL_NV				0x00008000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_HALF_BIAS_NEGATE_NV				0x0000a000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_SIGNED_IDENTITY_NV				0x0000c000 +#define    NV10TCL_RC_FINAL0_C_MAPPING_SIGNED_NEGATE_NV					0x0000e000 +#define   NV10TCL_RC_FINAL0_B_INPUT_SHIFT						16 +#define   NV10TCL_RC_FINAL0_B_INPUT_MASK						0x000f0000 +#define    NV10TCL_RC_FINAL0_B_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_FINAL0_B_INPUT_CONSTANT_COLOR0_NV					0x00010000 +#define    NV10TCL_RC_FINAL0_B_INPUT_CONSTANT_COLOR1_NV					0x00020000 +#define    NV10TCL_RC_FINAL0_B_INPUT_FOG						0x00030000 +#define    NV10TCL_RC_FINAL0_B_INPUT_PRIMARY_COLOR_NV					0x00040000 +#define    NV10TCL_RC_FINAL0_B_INPUT_SECONDARY_COLOR_NV					0x00050000 +#define    NV10TCL_RC_FINAL0_B_INPUT_TEXTURE0_ARB					0x00080000 +#define    NV10TCL_RC_FINAL0_B_INPUT_TEXTURE1_ARB					0x00090000 +#define    NV10TCL_RC_FINAL0_B_INPUT_SPARE0_NV						0x000c0000 +#define    NV10TCL_RC_FINAL0_B_INPUT_SPARE1_NV						0x000d0000 +#define    NV10TCL_RC_FINAL0_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x000e0000 +#define    NV10TCL_RC_FINAL0_B_INPUT_E_TIMES_F_NV					0x000f0000 +#define   NV10TCL_RC_FINAL0_B_COMPONENT_USAGE						(1 << 20) +#define    NV10TCL_RC_FINAL0_B_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_FINAL0_B_COMPONENT_USAGE_ALPHA					0x00100000 +#define   NV10TCL_RC_FINAL0_B_MAPPING_SHIFT						21 +#define   NV10TCL_RC_FINAL0_B_MAPPING_MASK						0x00e00000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_UNSIGNED_INVERT_NV				0x00200000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_EXPAND_NORMAL_NV					0x00400000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_EXPAND_NEGATE_NV					0x00600000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_HALF_BIAS_NORMAL_NV				0x00800000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_HALF_BIAS_NEGATE_NV				0x00a00000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_SIGNED_IDENTITY_NV				0x00c00000 +#define    NV10TCL_RC_FINAL0_B_MAPPING_SIGNED_NEGATE_NV					0x00e00000 +#define   NV10TCL_RC_FINAL0_A_INPUT_SHIFT						24 +#define   NV10TCL_RC_FINAL0_A_INPUT_MASK						0x0f000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_CONSTANT_COLOR0_NV					0x01000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_CONSTANT_COLOR1_NV					0x02000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_FOG						0x03000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_PRIMARY_COLOR_NV					0x04000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_SECONDARY_COLOR_NV					0x05000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_TEXTURE0_ARB					0x08000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_TEXTURE1_ARB					0x09000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_SPARE0_NV						0x0c000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_SPARE1_NV						0x0d000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0e000000 +#define    NV10TCL_RC_FINAL0_A_INPUT_E_TIMES_F_NV					0x0f000000 +#define   NV10TCL_RC_FINAL0_A_COMPONENT_USAGE						(1 << 28) +#define    NV10TCL_RC_FINAL0_A_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_FINAL0_A_COMPONENT_USAGE_ALPHA					0x10000000 +#define   NV10TCL_RC_FINAL0_A_MAPPING_SHIFT						29 +#define   NV10TCL_RC_FINAL0_A_MAPPING_MASK						0xe0000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_UNSIGNED_INVERT_NV				0x20000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_EXPAND_NORMAL_NV					0x40000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_EXPAND_NEGATE_NV					0x60000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_HALF_BIAS_NORMAL_NV				0x80000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_HALF_BIAS_NEGATE_NV				0xa0000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_SIGNED_IDENTITY_NV				0xc0000000 +#define    NV10TCL_RC_FINAL0_A_MAPPING_SIGNED_NEGATE_NV					0xe0000000 +#define  NV10TCL_RC_FINAL1								0x0000028c +#define   NV10TCL_RC_FINAL1_COLOR_SUM_CLAMP						(1 <<  7) +#define   NV10TCL_RC_FINAL1_G_INPUT_SHIFT						8 +#define   NV10TCL_RC_FINAL1_G_INPUT_MASK						0x00000f00 +#define    NV10TCL_RC_FINAL1_G_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_FINAL1_G_INPUT_CONSTANT_COLOR0_NV					0x00000100 +#define    NV10TCL_RC_FINAL1_G_INPUT_CONSTANT_COLOR1_NV					0x00000200 +#define    NV10TCL_RC_FINAL1_G_INPUT_FOG						0x00000300 +#define    NV10TCL_RC_FINAL1_G_INPUT_PRIMARY_COLOR_NV					0x00000400 +#define    NV10TCL_RC_FINAL1_G_INPUT_SECONDARY_COLOR_NV					0x00000500 +#define    NV10TCL_RC_FINAL1_G_INPUT_TEXTURE0_ARB					0x00000800 +#define    NV10TCL_RC_FINAL1_G_INPUT_TEXTURE1_ARB					0x00000900 +#define    NV10TCL_RC_FINAL1_G_INPUT_SPARE0_NV						0x00000c00 +#define    NV10TCL_RC_FINAL1_G_INPUT_SPARE1_NV						0x00000d00 +#define    NV10TCL_RC_FINAL1_G_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x00000e00 +#define    NV10TCL_RC_FINAL1_G_INPUT_E_TIMES_F_NV					0x00000f00 +#define   NV10TCL_RC_FINAL1_G_COMPONENT_USAGE						(1 << 12) +#define    NV10TCL_RC_FINAL1_G_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_FINAL1_G_COMPONENT_USAGE_ALPHA					0x00001000 +#define   NV10TCL_RC_FINAL1_G_MAPPING_SHIFT						13 +#define   NV10TCL_RC_FINAL1_G_MAPPING_MASK						0x0000e000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_UNSIGNED_INVERT_NV				0x00002000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_EXPAND_NORMAL_NV					0x00004000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_EXPAND_NEGATE_NV					0x00006000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_HALF_BIAS_NORMAL_NV				0x00008000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_HALF_BIAS_NEGATE_NV				0x0000a000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_SIGNED_IDENTITY_NV				0x0000c000 +#define    NV10TCL_RC_FINAL1_G_MAPPING_SIGNED_NEGATE_NV					0x0000e000 +#define   NV10TCL_RC_FINAL1_F_INPUT_SHIFT						16 +#define   NV10TCL_RC_FINAL1_F_INPUT_MASK						0x000f0000 +#define    NV10TCL_RC_FINAL1_F_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_FINAL1_F_INPUT_CONSTANT_COLOR0_NV					0x00010000 +#define    NV10TCL_RC_FINAL1_F_INPUT_CONSTANT_COLOR1_NV					0x00020000 +#define    NV10TCL_RC_FINAL1_F_INPUT_FOG						0x00030000 +#define    NV10TCL_RC_FINAL1_F_INPUT_PRIMARY_COLOR_NV					0x00040000 +#define    NV10TCL_RC_FINAL1_F_INPUT_SECONDARY_COLOR_NV					0x00050000 +#define    NV10TCL_RC_FINAL1_F_INPUT_TEXTURE0_ARB					0x00080000 +#define    NV10TCL_RC_FINAL1_F_INPUT_TEXTURE1_ARB					0x00090000 +#define    NV10TCL_RC_FINAL1_F_INPUT_SPARE0_NV						0x000c0000 +#define    NV10TCL_RC_FINAL1_F_INPUT_SPARE1_NV						0x000d0000 +#define    NV10TCL_RC_FINAL1_F_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x000e0000 +#define    NV10TCL_RC_FINAL1_F_INPUT_E_TIMES_F_NV					0x000f0000 +#define   NV10TCL_RC_FINAL1_F_COMPONENT_USAGE						(1 << 20) +#define    NV10TCL_RC_FINAL1_F_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_FINAL1_F_COMPONENT_USAGE_ALPHA					0x00100000 +#define   NV10TCL_RC_FINAL1_F_MAPPING_SHIFT						21 +#define   NV10TCL_RC_FINAL1_F_MAPPING_MASK						0x00e00000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_UNSIGNED_INVERT_NV				0x00200000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_EXPAND_NORMAL_NV					0x00400000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_EXPAND_NEGATE_NV					0x00600000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_HALF_BIAS_NORMAL_NV				0x00800000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_HALF_BIAS_NEGATE_NV				0x00a00000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_SIGNED_IDENTITY_NV				0x00c00000 +#define    NV10TCL_RC_FINAL1_F_MAPPING_SIGNED_NEGATE_NV					0x00e00000 +#define   NV10TCL_RC_FINAL1_E_INPUT_SHIFT						24 +#define   NV10TCL_RC_FINAL1_E_INPUT_MASK						0x0f000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_ZERO						0x00000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_CONSTANT_COLOR0_NV					0x01000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_CONSTANT_COLOR1_NV					0x02000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_FOG						0x03000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_PRIMARY_COLOR_NV					0x04000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_SECONDARY_COLOR_NV					0x05000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_TEXTURE0_ARB					0x08000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_TEXTURE1_ARB					0x09000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_SPARE0_NV						0x0c000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_SPARE1_NV						0x0d000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV			0x0e000000 +#define    NV10TCL_RC_FINAL1_E_INPUT_E_TIMES_F_NV					0x0f000000 +#define   NV10TCL_RC_FINAL1_E_COMPONENT_USAGE						(1 << 28) +#define    NV10TCL_RC_FINAL1_E_COMPONENT_USAGE_RGB					0x00000000 +#define    NV10TCL_RC_FINAL1_E_COMPONENT_USAGE_ALPHA					0x10000000 +#define   NV10TCL_RC_FINAL1_E_MAPPING_SHIFT						29 +#define   NV10TCL_RC_FINAL1_E_MAPPING_MASK						0xe0000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_UNSIGNED_IDENTITY_NV				0x00000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_UNSIGNED_INVERT_NV				0x20000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_EXPAND_NORMAL_NV					0x40000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_EXPAND_NEGATE_NV					0x60000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_HALF_BIAS_NORMAL_NV				0x80000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_HALF_BIAS_NEGATE_NV				0xa0000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_SIGNED_IDENTITY_NV				0xc0000000 +#define    NV10TCL_RC_FINAL1_E_MAPPING_SIGNED_NEGATE_NV					0xe0000000 +#define  NV10TCL_LIGHT_MODEL								0x00000294 +#define   NV10TCL_LIGHT_MODEL_COLOR_CONTROL						(1 <<  1) +#define   NV10TCL_LIGHT_MODEL_LOCAL_VIEWER						(1 << 16) +#define  NV10TCL_COLOR_MATERIAL_ENABLE							0x00000298 +#define   NV10TCL_COLOR_MATERIAL_ENABLE_SPECULAR					(1 <<  0) +#define   NV10TCL_COLOR_MATERIAL_ENABLE_DIFFUSE						(1 <<  1) +#define   NV10TCL_COLOR_MATERIAL_ENABLE_AMBIENT						(1 <<  2) +#define   NV10TCL_COLOR_MATERIAL_ENABLE_EMISSION					(1 <<  3) +#define  NV10TCL_FOG_MODE								0x0000029c +#define   NV10TCL_FOG_MODE_EXP								0x00000800 +#define   NV10TCL_FOG_MODE_EXP_2							0x00000802 +#define   NV10TCL_FOG_MODE_EXP2								0x00000803 +#define   NV10TCL_FOG_MODE_LINEAR							0x00000804 +#define   NV10TCL_FOG_MODE_LINEAR_2							0x00002601 +#define  NV10TCL_FOG_COORD_DIST								0x000002a0 +#define  NV10TCL_FOG_ENABLE								0x000002a4 +#define  NV10TCL_FOG_COLOR								0x000002a8 +#define   NV10TCL_FOG_COLOR_R_SHIFT							0 +#define   NV10TCL_FOG_COLOR_R_MASK							0x000000ff +#define   NV10TCL_FOG_COLOR_G_SHIFT							8 +#define   NV10TCL_FOG_COLOR_G_MASK							0x0000ff00 +#define   NV10TCL_FOG_COLOR_B_SHIFT							16 +#define   NV10TCL_FOG_COLOR_B_MASK							0x00ff0000 +#define   NV10TCL_FOG_COLOR_A_SHIFT							24 +#define   NV10TCL_FOG_COLOR_A_MASK							0xff000000 +#define  NV10TCL_VIEWPORT_CLIP_MODE							0x000002b4 +#define  NV10TCL_VIEWPORT_CLIP_HORIZ(x)							(0x000002c0+((x)*4)) +#define  NV10TCL_VIEWPORT_CLIP_HORIZ__SIZE						0x00000008 +#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_L_SHIFT					0 +#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_L_MASK					0x000007ff +#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_LEFT_ENABLE					(1 << 11) +#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_R_SHIFT					16 +#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_R_MASK					0x07ff0000 +#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_RIGHT_ENABLE					(1 << 27) +#define  NV10TCL_VIEWPORT_CLIP_VERT(x)							(0x000002e0+((x)*4)) +#define  NV10TCL_VIEWPORT_CLIP_VERT__SIZE						0x00000008 +#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_T_SHIFT					0 +#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_T_MASK					0x000007ff +#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_TOP_ENABLE					(1 << 11) +#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_B_SHIFT					16 +#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_B_MASK					0x07ff0000 +#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_BOTTOM_ENABLE					(1 << 27) +#define  NV10TCL_ALPHA_FUNC_ENABLE							0x00000300 +#define  NV10TCL_BLEND_FUNC_ENABLE							0x00000304 +#define  NV10TCL_CULL_FACE_ENABLE							0x00000308 +#define  NV10TCL_DEPTH_TEST_ENABLE							0x0000030c +#define  NV10TCL_DITHER_ENABLE								0x00000310 +#define  NV10TCL_LIGHTING_ENABLE							0x00000314 +#define  NV10TCL_POINT_PARAMETERS_ENABLE						0x00000318 +#define  NV10TCL_POINT_SMOOTH_ENABLE							0x0000031c +#define  NV10TCL_LINE_SMOOTH_ENABLE							0x00000320 +#define  NV10TCL_POLYGON_SMOOTH_ENABLE							0x00000324 +#define  NV10TCL_VERTEX_WEIGHT_ENABLE							0x00000328 +#define  NV10TCL_STENCIL_ENABLE								0x0000032c +#define  NV10TCL_POLYGON_OFFSET_POINT_ENABLE						0x00000330 +#define  NV10TCL_POLYGON_OFFSET_LINE_ENABLE						0x00000334 +#define  NV10TCL_POLYGON_OFFSET_FILL_ENABLE						0x00000338 +#define  NV10TCL_ALPHA_FUNC_FUNC							0x0000033c +#define   NV10TCL_ALPHA_FUNC_FUNC_NEVER							0x00000200 +#define   NV10TCL_ALPHA_FUNC_FUNC_LESS							0x00000201 +#define   NV10TCL_ALPHA_FUNC_FUNC_EQUAL							0x00000202 +#define   NV10TCL_ALPHA_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV10TCL_ALPHA_FUNC_FUNC_GREATER						0x00000204 +#define   NV10TCL_ALPHA_FUNC_FUNC_GREATER						0x00000204 +#define   NV10TCL_ALPHA_FUNC_FUNC_NOTEQUAL						0x00000205 +#define   NV10TCL_ALPHA_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV10TCL_ALPHA_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV10TCL_ALPHA_FUNC_REF								0x00000340 +#define  NV10TCL_BLEND_FUNC_SRC								0x00000344 +#define   NV10TCL_BLEND_FUNC_SRC_ZERO							0x00000000 +#define   NV10TCL_BLEND_FUNC_SRC_ONE							0x00000001 +#define   NV10TCL_BLEND_FUNC_SRC_SRC_COLOR						0x00000300 +#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_COLOR					0x00000301 +#define   NV10TCL_BLEND_FUNC_SRC_SRC_ALPHA						0x00000302 +#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_ALPHA					0x00000303 +#define   NV10TCL_BLEND_FUNC_SRC_DST_ALPHA						0x00000304 +#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_ALPHA					0x00000305 +#define   NV10TCL_BLEND_FUNC_SRC_DST_COLOR						0x00000306 +#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_COLOR					0x00000307 +#define   NV10TCL_BLEND_FUNC_SRC_SRC_ALPHA_SATURATE					0x00000308 +#define   NV10TCL_BLEND_FUNC_SRC_CONSTANT_COLOR						0x00008001 +#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV10TCL_BLEND_FUNC_SRC_CONSTANT_ALPHA						0x00008003 +#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV10TCL_BLEND_FUNC_DST								0x00000348 +#define   NV10TCL_BLEND_FUNC_DST_ZERO							0x00000000 +#define   NV10TCL_BLEND_FUNC_DST_ONE							0x00000001 +#define   NV10TCL_BLEND_FUNC_DST_SRC_COLOR						0x00000300 +#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_COLOR					0x00000301 +#define   NV10TCL_BLEND_FUNC_DST_SRC_ALPHA						0x00000302 +#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_ALPHA					0x00000303 +#define   NV10TCL_BLEND_FUNC_DST_DST_ALPHA						0x00000304 +#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_DST_ALPHA					0x00000305 +#define   NV10TCL_BLEND_FUNC_DST_DST_COLOR						0x00000306 +#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_DST_COLOR					0x00000307 +#define   NV10TCL_BLEND_FUNC_DST_SRC_ALPHA_SATURATE					0x00000308 +#define   NV10TCL_BLEND_FUNC_DST_CONSTANT_COLOR						0x00008001 +#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV10TCL_BLEND_FUNC_DST_CONSTANT_ALPHA						0x00008003 +#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV10TCL_BLEND_COLOR								0x0000034c +#define   NV10TCL_BLEND_COLOR_B_SHIFT							0 +#define   NV10TCL_BLEND_COLOR_B_MASK							0x000000ff +#define   NV10TCL_BLEND_COLOR_G_SHIFT							8 +#define   NV10TCL_BLEND_COLOR_G_MASK							0x0000ff00 +#define   NV10TCL_BLEND_COLOR_R_SHIFT							16 +#define   NV10TCL_BLEND_COLOR_R_MASK							0x00ff0000 +#define   NV10TCL_BLEND_COLOR_A_SHIFT							24 +#define   NV10TCL_BLEND_COLOR_A_MASK							0xff000000 +#define  NV10TCL_BLEND_EQUATION								0x00000350 +#define   NV10TCL_BLEND_EQUATION_FUNC_ADD						0x00008006 +#define   NV10TCL_BLEND_EQUATION_MIN							0x00008007 +#define   NV10TCL_BLEND_EQUATION_MAX							0x00008008 +#define   NV10TCL_BLEND_EQUATION_FUNC_SUBTRACT						0x0000800a +#define   NV10TCL_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT					0x0000800b +#define  NV10TCL_DEPTH_FUNC								0x00000354 +#define   NV10TCL_DEPTH_FUNC_NEVER							0x00000200 +#define   NV10TCL_DEPTH_FUNC_LESS							0x00000201 +#define   NV10TCL_DEPTH_FUNC_EQUAL							0x00000202 +#define   NV10TCL_DEPTH_FUNC_LEQUAL							0x00000203 +#define   NV10TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV10TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV10TCL_DEPTH_FUNC_NOTEQUAL							0x00000205 +#define   NV10TCL_DEPTH_FUNC_GEQUAL							0x00000206 +#define   NV10TCL_DEPTH_FUNC_ALWAYS							0x00000207 +#define  NV10TCL_COLOR_MASK								0x00000358 +#define   NV10TCL_COLOR_MASK_B								(1 <<  0) +#define   NV10TCL_COLOR_MASK_G								(1 <<  8) +#define   NV10TCL_COLOR_MASK_R								(1 << 16) +#define   NV10TCL_COLOR_MASK_A								(1 << 24) +#define  NV10TCL_DEPTH_WRITE_ENABLE							0x0000035c +#define  NV10TCL_STENCIL_MASK								0x00000360 +#define  NV10TCL_STENCIL_FUNC_FUNC							0x00000364 +#define   NV10TCL_STENCIL_FUNC_FUNC_NEVER						0x00000200 +#define   NV10TCL_STENCIL_FUNC_FUNC_LESS						0x00000201 +#define   NV10TCL_STENCIL_FUNC_FUNC_EQUAL						0x00000202 +#define   NV10TCL_STENCIL_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV10TCL_STENCIL_FUNC_FUNC_GREATER						0x00000204 +#define   NV10TCL_STENCIL_FUNC_FUNC_GREATER						0x00000204 +#define   NV10TCL_STENCIL_FUNC_FUNC_NOTEQUAL						0x00000205 +#define   NV10TCL_STENCIL_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV10TCL_STENCIL_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV10TCL_STENCIL_FUNC_REF							0x00000368 +#define  NV10TCL_STENCIL_FUNC_MASK							0x0000036c +#define  NV10TCL_STENCIL_OP_FAIL							0x00000370 +#define   NV10TCL_STENCIL_OP_FAIL_ZERO							0x00000000 +#define   NV10TCL_STENCIL_OP_FAIL_INVERT						0x0000150a +#define   NV10TCL_STENCIL_OP_FAIL_KEEP							0x00001e00 +#define   NV10TCL_STENCIL_OP_FAIL_REPLACE						0x00001e01 +#define   NV10TCL_STENCIL_OP_FAIL_INCR							0x00001e02 +#define   NV10TCL_STENCIL_OP_FAIL_DECR							0x00001e03 +#define   NV10TCL_STENCIL_OP_FAIL_INCR_WRAP						0x00008507 +#define   NV10TCL_STENCIL_OP_FAIL_DECR_WRAP						0x00008508 +#define  NV10TCL_STENCIL_OP_ZFAIL							0x00000374 +#define   NV10TCL_STENCIL_OP_ZFAIL_ZERO							0x00000000 +#define   NV10TCL_STENCIL_OP_ZFAIL_INVERT						0x0000150a +#define   NV10TCL_STENCIL_OP_ZFAIL_KEEP							0x00001e00 +#define   NV10TCL_STENCIL_OP_ZFAIL_REPLACE						0x00001e01 +#define   NV10TCL_STENCIL_OP_ZFAIL_INCR							0x00001e02 +#define   NV10TCL_STENCIL_OP_ZFAIL_DECR							0x00001e03 +#define   NV10TCL_STENCIL_OP_ZFAIL_INCR_WRAP						0x00008507 +#define   NV10TCL_STENCIL_OP_ZFAIL_DECR_WRAP						0x00008508 +#define  NV10TCL_STENCIL_OP_ZPASS							0x00000378 +#define   NV10TCL_STENCIL_OP_ZPASS_ZERO							0x00000000 +#define   NV10TCL_STENCIL_OP_ZPASS_INVERT						0x0000150a +#define   NV10TCL_STENCIL_OP_ZPASS_KEEP							0x00001e00 +#define   NV10TCL_STENCIL_OP_ZPASS_REPLACE						0x00001e01 +#define   NV10TCL_STENCIL_OP_ZPASS_INCR							0x00001e02 +#define   NV10TCL_STENCIL_OP_ZPASS_DECR							0x00001e03 +#define   NV10TCL_STENCIL_OP_ZPASS_INCR_WRAP						0x00008507 +#define   NV10TCL_STENCIL_OP_ZPASS_DECR_WRAP						0x00008508 +#define  NV10TCL_SHADE_MODEL								0x0000037c +#define   NV10TCL_SHADE_MODEL_FLAT							0x00001d00 +#define   NV10TCL_SHADE_MODEL_SMOOTH							0x00001d01 +#define  NV10TCL_LINE_WIDTH								0x00000380 +#define  NV10TCL_POLYGON_OFFSET_FACTOR							0x00000384 +#define  NV10TCL_POLYGON_OFFSET_UNITS							0x00000388 +#define  NV10TCL_POLYGON_MODE_FRONT							0x0000038c +#define   NV10TCL_POLYGON_MODE_FRONT_POINT						0x00001b00 +#define   NV10TCL_POLYGON_MODE_FRONT_LINE						0x00001b01 +#define   NV10TCL_POLYGON_MODE_FRONT_FILL						0x00001b02 +#define  NV10TCL_POLYGON_MODE_BACK							0x00000390 +#define   NV10TCL_POLYGON_MODE_BACK_POINT						0x00001b00 +#define   NV10TCL_POLYGON_MODE_BACK_LINE						0x00001b01 +#define   NV10TCL_POLYGON_MODE_BACK_FILL						0x00001b02 +#define  NV10TCL_DEPTH_RANGE_NEAR							0x00000394 +#define  NV10TCL_DEPTH_RANGE_FAR							0x00000398 +#define  NV10TCL_CULL_FACE								0x0000039c +#define   NV10TCL_CULL_FACE_FRONT							0x00000404 +#define   NV10TCL_CULL_FACE_BACK							0x00000405 +#define   NV10TCL_CULL_FACE_FRONT_AND_BACK						0x00000408 +#define  NV10TCL_FRONT_FACE								0x000003a0 +#define   NV10TCL_FRONT_FACE_CW								0x00000900 +#define   NV10TCL_FRONT_FACE_CCW							0x00000901 +#define  NV10TCL_NORMALIZE_ENABLE							0x000003a4 +#define  NV10TCL_COLOR_MATERIAL_R							0x000003a8 +#define  NV10TCL_COLOR_MATERIAL_G							0x000003ac +#define  NV10TCL_COLOR_MATERIAL_B							0x000003b0 +#define  NV10TCL_COLOR_MATERIAL_A							0x000003b4 +#define  NV10TCL_COLOR_CONTROL								0x000003b8 +#define  NV10TCL_ENABLED_LIGHTS								0x000003bc +#define   NV10TCL_ENABLED_LIGHTS_LIGHT0							(1 <<  0) +#define   NV10TCL_ENABLED_LIGHTS_LIGHT1							(1 <<  2) +#define   NV10TCL_ENABLED_LIGHTS_LIGHT2							(1 <<  4) +#define   NV10TCL_ENABLED_LIGHTS_LIGHT3							(1 <<  6) +#define   NV10TCL_ENABLED_LIGHTS_LIGHT4							(1 <<  8) +#define   NV10TCL_ENABLED_LIGHTS_LIGHT5							(1 << 10) +#define   NV10TCL_ENABLED_LIGHTS_LIGHT6							(1 << 12) +#define   NV10TCL_ENABLED_LIGHTS_LIGHT7							(1 << 14) +#define  NV10TCL_CLIP_PLANE_ENABLE(x)							(0x000003c0+((x)*4)) +#define  NV10TCL_CLIP_PLANE_ENABLE__SIZE						0x00000008 +#define   NV10TCL_CLIP_PLANE_ENABLE_FALSE						0x00000000 +#define   NV10TCL_CLIP_PLANE_ENABLE_EYE_LINEAR						0x00002400 +#define   NV10TCL_CLIP_PLANE_ENABLE_OBJECT_LINEAR					0x00002401 +#define  NV10TCL_TX_MATRIX_ENABLE(x)							(0x000003e0+((x)*4)) +#define  NV10TCL_TX_MATRIX_ENABLE__SIZE							0x00000002 +#define  NV10TCL_VIEW_MATRIX_ENABLE							0x000003e8 +#define   NV10TCL_VIEW_MATRIX_ENABLE_MODELVIEW1						(1 <<  0) +#define   NV10TCL_VIEW_MATRIX_ENABLE_MODELVIEW0						(1 <<  1) +#define   NV10TCL_VIEW_MATRIX_ENABLE_PROJECTION						(1 <<  2) +#define  NV10TCL_POINT_SIZE								0x000003ec +#define  NV10TCL_MODELVIEW0_MATRIX(x)							(0x00000400+((x)*4)) +#define  NV10TCL_MODELVIEW0_MATRIX__SIZE						0x00000010 +#define  NV10TCL_MODELVIEW1_MATRIX(x)							(0x00000440+((x)*4)) +#define  NV10TCL_MODELVIEW1_MATRIX__SIZE						0x00000010 +#define  NV10TCL_INVERSE_MODELVIEW0_MATRIX(x)						(0x00000480+((x)*4)) +#define  NV10TCL_INVERSE_MODELVIEW0_MATRIX__SIZE					0x00000010 +#define  NV10TCL_INVERSE_MODELVIEW1_MATRIX(x)						(0x000004c0+((x)*4)) +#define  NV10TCL_INVERSE_MODELVIEW1_MATRIX__SIZE					0x00000010 +#define  NV10TCL_PROJECTION_MATRIX(x)							(0x00000500+((x)*4)) +#define  NV10TCL_PROJECTION_MATRIX__SIZE						0x00000010 +#define  NV10TCL_TX0_MATRIX(x)								(0x00000540+((x)*4)) +#define  NV10TCL_TX0_MATRIX__SIZE							0x00000010 +#define  NV10TCL_TX1_MATRIX(x)								(0x00000580+((x)*4)) +#define  NV10TCL_TX1_MATRIX__SIZE							0x00000010 +#define  NV10TCL_CLIP_PLANE_A(x)							(0x00000600+((x)*16)) +#define  NV10TCL_CLIP_PLANE_A__SIZE							0x00000008 +#define  NV10TCL_CLIP_PLANE_B(x)							(0x00000604+((x)*16)) +#define  NV10TCL_CLIP_PLANE_B__SIZE							0x00000008 +#define  NV10TCL_CLIP_PLANE_C(x)							(0x00000608+((x)*16)) +#define  NV10TCL_CLIP_PLANE_C__SIZE							0x00000008 +#define  NV10TCL_CLIP_PLANE_D(x)							(0x0000060c+((x)*16)) +#define  NV10TCL_CLIP_PLANE_D__SIZE							0x00000008 +#define  NV10TCL_FOG_EQUATION_CONSTANT							0x00000680 +#define  NV10TCL_FOG_EQUATION_LINEAR							0x00000684 +#define  NV10TCL_FOG_EQUATION_QUADRATIC							0x00000688 +#define  NV10TCL_FRONT_MATERIAL_SHININESS(x)						(0x000006a0+((x)*4)) +#define  NV10TCL_FRONT_MATERIAL_SHININESS__SIZE						0x00000006 +#define  NV10TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R			0x000006c4 +#define  NV10TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G			0x000006c8 +#define  NV10TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B			0x000006cc +#define  NV10TCL_VIEWPORT_SCALE_X							0x000006e8 +#define  NV10TCL_VIEWPORT_SCALE_Y							0x000006ec +#define  NV10TCL_VIEWPORT_SCALE_Z							0x000006f0 +#define  NV10TCL_VIEWPORT_SCALE_W							0x000006f4 +#define  NV10TCL_POINT_PARAMETER(x)							(0x000006f8+((x)*4)) +#define  NV10TCL_POINT_PARAMETER__SIZE							0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(x)					(0x00000800+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(x)					(0x00000804+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(x)					(0x00000808+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(x)					(0x0000080c+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(x)					(0x00000810+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(x)					(0x00000814+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(x)					(0x00000818+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(x)					(0x0000081c+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G__SIZE				0x00000008 +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(x)					(0x00000820+((x)*128)) +#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B__SIZE				0x00000008 +#define  NV10TCL_LIGHT_HALF_VECTOR_X(x)							(0x00000828+((x)*128)) +#define  NV10TCL_LIGHT_HALF_VECTOR_X__SIZE						0x00000008 +#define  NV10TCL_LIGHT_HALF_VECTOR_Y(x)							(0x0000082c+((x)*128)) +#define  NV10TCL_LIGHT_HALF_VECTOR_Y__SIZE						0x00000008 +#define  NV10TCL_LIGHT_HALF_VECTOR_Z(x)							(0x00000830+((x)*128)) +#define  NV10TCL_LIGHT_HALF_VECTOR_Z__SIZE						0x00000008 +#define  NV10TCL_LIGHT_DIRECTION_X(x)							(0x00000834+((x)*128)) +#define  NV10TCL_LIGHT_DIRECTION_X__SIZE						0x00000008 +#define  NV10TCL_LIGHT_DIRECTION_Y(x)							(0x00000838+((x)*128)) +#define  NV10TCL_LIGHT_DIRECTION_Y__SIZE						0x00000008 +#define  NV10TCL_LIGHT_DIRECTION_Z(x)							(0x0000083c+((x)*128)) +#define  NV10TCL_LIGHT_DIRECTION_Z__SIZE						0x00000008 +#define  NV10TCL_LIGHT_SPOT_CUTOFF_A(x)							(0x00000840+((x)*128)) +#define  NV10TCL_LIGHT_SPOT_CUTOFF_A__SIZE						0x00000008 +#define  NV10TCL_LIGHT_SPOT_CUTOFF_B(x)							(0x00000844+((x)*128)) +#define  NV10TCL_LIGHT_SPOT_CUTOFF_B__SIZE						0x00000008 +#define  NV10TCL_LIGHT_SPOT_CUTOFF_C(x)							(0x00000848+((x)*128)) +#define  NV10TCL_LIGHT_SPOT_CUTOFF_C__SIZE						0x00000008 +#define  NV10TCL_LIGHT_SPOT_DIR_X(x)							(0x0000084c+((x)*128)) +#define  NV10TCL_LIGHT_SPOT_DIR_X__SIZE							0x00000008 +#define  NV10TCL_LIGHT_SPOT_DIR_Y(x)							(0x00000850+((x)*128)) +#define  NV10TCL_LIGHT_SPOT_DIR_Y__SIZE							0x00000008 +#define  NV10TCL_LIGHT_SPOT_DIR_Z(x)							(0x00000854+((x)*128)) +#define  NV10TCL_LIGHT_SPOT_DIR_Z__SIZE							0x00000008 +#define  NV10TCL_LIGHT_SPOT_CUTOFF_D(x)							(0x00000858+((x)*128)) +#define  NV10TCL_LIGHT_SPOT_CUTOFF_D__SIZE						0x00000008 +#define  NV10TCL_LIGHT_POSITION_X(x)							(0x0000085c+((x)*128)) +#define  NV10TCL_LIGHT_POSITION_X__SIZE							0x00000008 +#define  NV10TCL_LIGHT_POSITION_Y(x)							(0x00000860+((x)*128)) +#define  NV10TCL_LIGHT_POSITION_Y__SIZE							0x00000008 +#define  NV10TCL_LIGHT_POSITION_Z(x)							(0x00000864+((x)*128)) +#define  NV10TCL_LIGHT_POSITION_Z__SIZE							0x00000008 +#define  NV10TCL_LIGHT_ATTENUATION_CONSTANT(x)						(0x00000868+((x)*128)) +#define  NV10TCL_LIGHT_ATTENUATION_CONSTANT__SIZE					0x00000008 +#define  NV10TCL_LIGHT_ATTENUATION_LINEAR(x)						(0x0000086c+((x)*128)) +#define  NV10TCL_LIGHT_ATTENUATION_LINEAR__SIZE						0x00000008 +#define  NV10TCL_LIGHT_ATTENUATION_QUADRATIC(x)						(0x00000870+((x)*128)) +#define  NV10TCL_LIGHT_ATTENUATION_QUADRATIC__SIZE					0x00000008 +#define  NV10TCL_VERTEX_POS_3F_X							0x00000c00 +#define  NV10TCL_VERTEX_POS_3F_Y							0x00000c04 +#define  NV10TCL_VERTEX_POS_3F_Z							0x00000c08 +#define  NV10TCL_VERTEX_POS_4F_X							0x00000c18 +#define  NV10TCL_VERTEX_POS_4F_Y							0x00000c1c +#define  NV10TCL_VERTEX_POS_4F_Z							0x00000c20 +#define  NV10TCL_VERTEX_POS_4F_W							0x00000c24 +#define  NV10TCL_VERTEX_NOR_3F_X							0x00000c30 +#define  NV10TCL_VERTEX_NOR_3F_Y							0x00000c34 +#define  NV10TCL_VERTEX_NOR_3F_Z							0x00000c38 +#define  NV10TCL_VERTEX_NOR_3I_XY							0x00000c40 +#define   NV10TCL_VERTEX_NOR_3I_XY_X_SHIFT						0 +#define   NV10TCL_VERTEX_NOR_3I_XY_X_MASK						0x0000ffff +#define   NV10TCL_VERTEX_NOR_3I_XY_Y_SHIFT						16 +#define   NV10TCL_VERTEX_NOR_3I_XY_Y_MASK						0xffff0000 +#define  NV10TCL_VERTEX_NOR_3I_Z							0x00000c44 +#define   NV10TCL_VERTEX_NOR_3I_Z_Z_SHIFT						0 +#define   NV10TCL_VERTEX_NOR_3I_Z_Z_MASK						0x0000ffff +#define  NV10TCL_VERTEX_COL_4F_R							0x00000c50 +#define  NV10TCL_VERTEX_COL_4F_G							0x00000c54 +#define  NV10TCL_VERTEX_COL_4F_B							0x00000c58 +#define  NV10TCL_VERTEX_COL_4F_A							0x00000c5c +#define  NV10TCL_VERTEX_COL_3F_R							0x00000c60 +#define  NV10TCL_VERTEX_COL_3F_G							0x00000c64 +#define  NV10TCL_VERTEX_COL_3F_B							0x00000c68 +#define  NV10TCL_VERTEX_COL_4I								0x00000c6c +#define   NV10TCL_VERTEX_COL_4I_R_SHIFT							0 +#define   NV10TCL_VERTEX_COL_4I_R_MASK							0x000000ff +#define   NV10TCL_VERTEX_COL_4I_G_SHIFT							8 +#define   NV10TCL_VERTEX_COL_4I_G_MASK							0x0000ff00 +#define   NV10TCL_VERTEX_COL_4I_B_SHIFT							16 +#define   NV10TCL_VERTEX_COL_4I_B_MASK							0x00ff0000 +#define   NV10TCL_VERTEX_COL_4I_A_SHIFT							24 +#define   NV10TCL_VERTEX_COL_4I_A_MASK							0xff000000 +#define  NV10TCL_VERTEX_COL2_3F_R							0x00000c80 +#define  NV10TCL_VERTEX_COL2_3F_G							0x00000c84 +#define  NV10TCL_VERTEX_COL2_3F_B							0x00000c88 +#define  NV10TCL_VERTEX_COL2_3I								0x00000c8c +#define   NV10TCL_VERTEX_COL2_3I_R_SHIFT						0 +#define   NV10TCL_VERTEX_COL2_3I_R_MASK							0x000000ff +#define   NV10TCL_VERTEX_COL2_3I_G_SHIFT						8 +#define   NV10TCL_VERTEX_COL2_3I_G_MASK							0x0000ff00 +#define   NV10TCL_VERTEX_COL2_3I_B_SHIFT						16 +#define   NV10TCL_VERTEX_COL2_3I_B_MASK							0x00ff0000 +#define  NV10TCL_VERTEX_TX0_2F_S							0x00000c90 +#define  NV10TCL_VERTEX_TX0_2F_T							0x00000c94 +#define  NV10TCL_VERTEX_TX0_2I								0x00000c98 +#define   NV10TCL_VERTEX_TX0_2I_S_SHIFT							0 +#define   NV10TCL_VERTEX_TX0_2I_S_MASK							0x0000ffff +#define   NV10TCL_VERTEX_TX0_2I_T_SHIFT							16 +#define   NV10TCL_VERTEX_TX0_2I_T_MASK							0xffff0000 +#define  NV10TCL_VERTEX_TX0_4F_S							0x00000ca0 +#define  NV10TCL_VERTEX_TX0_4F_T							0x00000ca4 +#define  NV10TCL_VERTEX_TX0_4F_R							0x00000ca8 +#define  NV10TCL_VERTEX_TX0_4F_Q							0x00000cac +#define  NV10TCL_VERTEX_TX0_4I_ST							0x00000cb0 +#define   NV10TCL_VERTEX_TX0_4I_ST_S_SHIFT						0 +#define   NV10TCL_VERTEX_TX0_4I_ST_S_MASK						0x0000ffff +#define   NV10TCL_VERTEX_TX0_4I_ST_T_SHIFT						16 +#define   NV10TCL_VERTEX_TX0_4I_ST_T_MASK						0xffff0000 +#define  NV10TCL_VERTEX_TX0_4I_RQ							0x00000cb4 +#define   NV10TCL_VERTEX_TX0_4I_RQ_R_SHIFT						0 +#define   NV10TCL_VERTEX_TX0_4I_RQ_R_MASK						0x0000ffff +#define   NV10TCL_VERTEX_TX0_4I_RQ_Q_SHIFT						16 +#define   NV10TCL_VERTEX_TX0_4I_RQ_Q_MASK						0xffff0000 +#define  NV10TCL_VERTEX_TX1_2F_S							0x00000cb8 +#define  NV10TCL_VERTEX_TX1_2F_T							0x00000cbc +#define  NV10TCL_VERTEX_TX1_2I								0x00000cc0 +#define   NV10TCL_VERTEX_TX1_2I_S_SHIFT							0 +#define   NV10TCL_VERTEX_TX1_2I_S_MASK							0x0000ffff +#define   NV10TCL_VERTEX_TX1_2I_T_SHIFT							16 +#define   NV10TCL_VERTEX_TX1_2I_T_MASK							0xffff0000 +#define  NV10TCL_VERTEX_TX1_4F_S							0x00000cc8 +#define  NV10TCL_VERTEX_TX1_4F_T							0x00000ccc +#define  NV10TCL_VERTEX_TX1_4F_R							0x00000cd0 +#define  NV10TCL_VERTEX_TX1_4F_Q							0x00000cd4 +#define  NV10TCL_VERTEX_TX1_4I_ST							0x00000cd8 +#define   NV10TCL_VERTEX_TX1_4I_ST_S_SHIFT						0 +#define   NV10TCL_VERTEX_TX1_4I_ST_S_MASK						0x0000ffff +#define   NV10TCL_VERTEX_TX1_4I_ST_T_SHIFT						16 +#define   NV10TCL_VERTEX_TX1_4I_ST_T_MASK						0xffff0000 +#define  NV10TCL_VERTEX_TX1_4I_RQ							0x00000cdc +#define   NV10TCL_VERTEX_TX1_4I_RQ_R_SHIFT						0 +#define   NV10TCL_VERTEX_TX1_4I_RQ_R_MASK						0x0000ffff +#define   NV10TCL_VERTEX_TX1_4I_RQ_Q_SHIFT						16 +#define   NV10TCL_VERTEX_TX1_4I_RQ_Q_MASK						0xffff0000 +#define  NV10TCL_VERTEX_FOG_1F								0x00000ce0 +#define  NV10TCL_VERTEX_WGH_1F								0x00000ce4 +#define  NV10TCL_EDGEFLAG_ENABLE							0x00000cec +#define  NV10TCL_VERTEX_ARRAY_VALIDATE							0x00000cf0 +#define  NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(x)						(0x00000d00+((x)*8)) +#define  NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET__SIZE					0x00000008 +#define  NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(x)						(0x00000d04+((x)*8)) +#define  NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT__SIZE					0x00000008 +#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_FIELDS_SHIFT				4 +#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_FIELDS_MASK				0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_STRIDE_SHIFT				8 +#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_STRIDE_MASK				0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_POS						0x00000d00 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_POS						0x00000d04 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_COL						0x00000d08 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_COL						0x00000d0c +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_COL2						0x00000d10 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_COL2						0x00000d14 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_TX0						0x00000d18 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_TX0						0x00000d1c +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_TX1						0x00000d20 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_TX1						0x00000d24 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_NOR						0x00000d28 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_NOR						0x00000d2c +#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_WGH						0x00000d30 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_WGH						0x00000d34 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_ARRAY_OFFSET_FOG						0x00000d38 +#define  NV10TCL_VERTEX_ARRAY_FORMAT_FOG						0x00000d3c +#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_TYPE_SHIFT					0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_TYPE_MASK					0x0000000f +#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_FIELDS_SHIFT					4 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_FIELDS_MASK					0x000000f0 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_STRIDE_SHIFT					8 +#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_STRIDE_MASK					0x0000ff00 +#define  NV10TCL_VERTEX_BEGIN_END							0x00000dfc +#define   NV10TCL_VERTEX_BEGIN_END_STOP							0x00000000 +#define   NV10TCL_VERTEX_BEGIN_END_POINTS						0x00000001 +#define   NV10TCL_VERTEX_BEGIN_END_LINES						0x00000002 +#define   NV10TCL_VERTEX_BEGIN_END_LINE_LOOP						0x00000003 +#define   NV10TCL_VERTEX_BEGIN_END_LINE_STRIP						0x00000004 +#define   NV10TCL_VERTEX_BEGIN_END_TRIANGLES						0x00000005 +#define   NV10TCL_VERTEX_BEGIN_END_TRIANGLE_STRIP					0x00000006 +#define   NV10TCL_VERTEX_BEGIN_END_TRIANGLE_FAN						0x00000007 +#define   NV10TCL_VERTEX_BEGIN_END_QUADS						0x00000008 +#define   NV10TCL_VERTEX_BEGIN_END_QUAD_STRIP						0x00000009 +#define   NV10TCL_VERTEX_BEGIN_END_POLYGON						0x0000000a +#define  NV10TCL_VB_ELEMENT_U16								0x00000e00 +#define   NV10TCL_VB_ELEMENT_U16_I0_SHIFT						0 +#define   NV10TCL_VB_ELEMENT_U16_I0_MASK						0x0000ffff +#define   NV10TCL_VB_ELEMENT_U16_I1_SHIFT						16 +#define   NV10TCL_VB_ELEMENT_U16_I1_MASK						0xffff0000 +#define  NV10TCL_VB_ELEMENT_U32								0x00001100 +#define  NV10TCL_VERTEX_BUFFER_BEGIN_END						0x000013fc +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_STOP						0x00000000 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_POINTS					0x00000001 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_LINES						0x00000002 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_LINE_LOOP					0x00000003 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_LINE_STRIP					0x00000004 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_TRIANGLES					0x00000005 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_TRIANGLE_STRIP				0x00000006 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_TRIANGLE_FAN					0x00000007 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_QUADS						0x00000008 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_QUAD_STRIP					0x00000009 +#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_POLYGON					0x0000000a +#define  NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS						0x00001400 +#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_FIRST_SHIFT					0 +#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_FIRST_MASK					0x0000ffff +#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_LAST_SHIFT					24 +#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_LAST_MASK					0xff000000 +#define  NV10TCL_VERTEX_ARRAY_DATA							0x00001800 + + +#define NV04_CONTEXT_COLOR_KEY								0x00000057 + + + +#define NV03_CONTEXT_SURFACES_2D							0x00000058 + +#define  NV03_CONTEXT_SURFACES_2D_SYNCHRONIZE						0x00000100 +#define  NV03_CONTEXT_SURFACES_2D_DMA_NOTIFY						0x00000180 +#define  NV03_CONTEXT_SURFACES_2D_DMA_SOURCE						0x00000184 +#define  NV03_CONTEXT_SURFACES_2D_DMA_DESTIN						0x00000188 +#define  NV03_CONTEXT_SURFACES_2D_COLOR_FORMAT						0x00000300 +#define  NV03_CONTEXT_SURFACES_2D_PITCH							0x00000304 +#define   NV03_CONTEXT_SURFACES_2D_PITCH_SOURCE_SHIFT					0 +#define   NV03_CONTEXT_SURFACES_2D_PITCH_SOURCE_MASK					0x0000ffff +#define   NV03_CONTEXT_SURFACES_2D_PITCH_DESTIN_SHIFT					16 +#define   NV03_CONTEXT_SURFACES_2D_PITCH_DESTIN_MASK					0xffff0000 +#define  NV03_CONTEXT_SURFACES_2D_OFFSET_SOURCE						0x00000308 +#define  NV03_CONTEXT_SURFACES_2D_OFFSET_DESTIN						0x0000030c + + +#define NV03_CONTEXT_SURFACES_3D							0x0000005a + +#define  NV03_CONTEXT_SURFACES_3D_SYNCHRONIZE						0x00000100 +#define  NV03_CONTEXT_SURFACES_3D_DMA_NOTIFY						0x00000180 +#define  NV03_CONTEXT_SURFACES_3D_DMA_SURFACE						0x00000184 +#define  NV03_CONTEXT_SURFACES_3D_PITCH							0x00000300 +#define  NV03_CONTEXT_SURFACES_3D_OFFSET_COLOR						0x00000304 +#define  NV03_CONTEXT_SURFACES_3D_OFFSET_ZETA						0x00000308 + + +#define NV04_RENDER_SOLID_LINE								0x0000005c + +#define  NV04_RENDER_SOLID_LINE_SURFACE							0x00000198 + + +#define NV04_RENDER_SOLID_TRIANGLE							0x0000005d + + + +#define NV04_RENDER_SOLID_RECTANGLE							0x0000005e + +#define  NV04_RENDER_SOLID_RECTANGLE_SURFACE						0x00000198 + + +#define NV04_IMAGE_BLIT									0x0000005f + +#define  NV04_IMAGE_BLIT_NOP								0x00000100 +#define  NV04_IMAGE_BLIT_NOTIFY								0x00000104 +#define  NV04_IMAGE_BLIT_DMA_NOTIFY							0x00000180 +#define  NV04_IMAGE_BLIT_COLOR_KEY							0x00000184 +#define  NV04_IMAGE_BLIT_CLIP_RECTANGLE							0x00000188 +#define  NV04_IMAGE_BLIT_PATTERN							0x0000018c +#define  NV04_IMAGE_BLIT_ROP								0x00000190 +#define  NV04_IMAGE_BLIT_BETA4								0x00000198 +#define  NV04_IMAGE_BLIT_SURFACE							0x0000019c +#define  NV04_IMAGE_BLIT_OPERATION							0x000002fc +#define   NV04_IMAGE_BLIT_OPERATION_SRCCOPY_AND						0x00000000 +#define   NV04_IMAGE_BLIT_OPERATION_ROP_AND						0x00000001 +#define   NV04_IMAGE_BLIT_OPERATION_BLEND_AND						0x00000002 +#define   NV04_IMAGE_BLIT_OPERATION_SRCCOPY						0x00000003 +#define   NV04_IMAGE_BLIT_OPERATION_SRCCOPY_PREMULT					0x00000004 +#define   NV04_IMAGE_BLIT_OPERATION_BLEND_PREMULT					0x00000005 + + +#define NV04_INDEXED_IMAGE_FROM_CPU							0x00000060 + +#define  NV04_INDEXED_IMAGE_FROM_CPU_NOP						0x00000100 +#define  NV04_INDEXED_IMAGE_FROM_CPU_NOTIFY						0x00000104 +#define  NV04_INDEXED_IMAGE_FROM_CPU_PATCH						0x0000010c +#define  NV04_INDEXED_IMAGE_FROM_CPU_DMA_NOTIFY						0x00000180 +#define  NV04_INDEXED_IMAGE_FROM_CPU_DMA_LUT						0x00000184 +#define  NV04_INDEXED_IMAGE_FROM_CPU_COLOR_FORMAT					0x000003e8 +#define  NV04_INDEXED_IMAGE_FROM_CPU_INDEX_FORMAT					0x000003ec +#define  NV04_INDEXED_IMAGE_FROM_CPU_LUT_OFFSET						0x000003f0 +#define  NV04_INDEXED_IMAGE_FROM_CPU_POINT						0x000003f4 +#define  NV04_INDEXED_IMAGE_FROM_CPU_SIZE_OUT						0x000003f8 +#define  NV04_INDEXED_IMAGE_FROM_CPU_SIZE_IN						0x000003fc +#define  NV04_INDEXED_IMAGE_FROM_CPU_COLOR						0x00000400 + + +#define NV04_IMAGE_FROM_CPU								0x00000061 + +#define  NV04_IMAGE_FROM_CPU_BETA4							0x00000198 +#define  NV04_IMAGE_FROM_CPU_SURFACE							0x0000019c + + +#define NV10_CONTEXT_SURFACES_2D							0x00000062 + + + +#define NV05_SCALED_IMAGE_FROM_MEMORY							0x00000063 + +#define  NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION					0x000002fc +#define   NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER				0x00000000 +#define   NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE			0x00000001 +#define   NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_SUBTR_TRUNCATE			0x00000002 + + +#define NV01_IMAGE_SRCCOPY_AND								0x00000064 + +#define  NV01_IMAGE_SRCCOPY_AND_NOTIFY							0x00000104 +#define  NV01_IMAGE_SRCCOPY_AND_DMA_NOTIFY						0x00000180 +#define  NV01_IMAGE_SRCCOPY_AND_IMAGE_OUTPUT						0x00000200 +#define  NV01_IMAGE_SRCCOPY_AND_IMAGE_INPUT						0x00000204 + + +#define NV05_INDEXED_IMAGE_FROM_CPU							0x00000064 + +#define  NV05_INDEXED_IMAGE_FROM_CPU_COLOR_KEY						0x00000188 +#define  NV05_INDEXED_IMAGE_FROM_CPU_CLIP_RECTANGLE					0x0000018c +#define  NV05_INDEXED_IMAGE_FROM_CPU_PATTERN						0x00000190 +#define  NV05_INDEXED_IMAGE_FROM_CPU_ROP						0x00000194 +#define  NV05_INDEXED_IMAGE_FROM_CPU_BETA1						0x00000198 +#define  NV05_INDEXED_IMAGE_FROM_CPU_BETA4						0x0000019c +#define  NV05_INDEXED_IMAGE_FROM_CPU_SURFACE						0x000001a0 +#define  NV05_INDEXED_IMAGE_FROM_CPU_COLOR_CONVERSION					0x000003e0 +#define  NV05_INDEXED_IMAGE_FROM_CPU_OPERATION						0x000003e4 +#define  NV05_INDEXED_IMAGE_FROM_CPU_INDICES						0x00000400 + + +#define NV05_IMAGE_FROM_CPU								0x00000065 + +#define  NV05_IMAGE_FROM_CPU_BETA4							0x00000198 +#define  NV05_IMAGE_FROM_CPU_SURFACE							0x0000019c + + +#define NV05_STRETCHED_IMAGE_FROM_CPU							0x00000066 + +#define  NV05_STRETCHED_IMAGE_FROM_CPU_BETA4						0x00000194 +#define  NV05_STRETCHED_IMAGE_FROM_CPU_SURFACE						0x00000198 +#define  NV05_STRETCHED_IMAGE_FROM_CPU_COLOR_CONVERSION					0x000002f8 + + +#define NV04_IMAGE_BLEND_PREMULT							0x00000067 + +#define  NV04_IMAGE_BLEND_PREMULT_NOP							0x00000100 +#define  NV04_IMAGE_BLEND_PREMULT_NOTIFY						0x00000104 +#define  NV04_IMAGE_BLEND_PREMULT_DMA_NOTIFY						0x00000180 +#define  NV04_IMAGE_BLEND_PREMULT_IMAGE_OUTPUT						0x00000200 +#define  NV04_IMAGE_BLEND_PREMULT_BETA_INPUT						0x00000204 +#define  NV04_IMAGE_BLEND_PREMULT_IMAGE_INPUT						0x00000208 + + +#define NV03_CHANNEL_PIO								0x0000006a + + + +#define NV03_CHANNEL_DMA								0x0000006b + + + +#define NV04_BETA_SOLID									0x00000072 + +#define  NV04_BETA_SOLID_NOP								0x00000100 +#define  NV04_BETA_SOLID_NOTIFY								0x00000104 +#define  NV04_BETA_SOLID_DMA_NOTIFY							0x00000180 +#define  NV04_BETA_SOLID_BETA_OUTPUT							0x00000200 +#define  NV04_BETA_SOLID_BETA_FACTOR							0x00000300 + + +#define NV04_STRETCHED_IMAGE_FROM_CPU							0x00000076 + + + +#define NV04_SCALED_IMAGE_FROM_MEMORY							0x00000077 + +#define  NV04_SCALED_IMAGE_FROM_MEMORY_NOP						0x00000100 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_NOTIFY						0x00000104 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY					0x00000180 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE					0x00000184 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_PATTERN						0x00000188 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_ROP						0x0000018c +#define  NV04_SCALED_IMAGE_FROM_MEMORY_BETA1						0x00000190 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_BETA4						0x00000194 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE						0x00000198 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION					0x000002fc +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER				0x00000000 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE			0x00000001 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_SUBTR_TRUNCATE			0x00000002 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT					0x00000300 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5				0x00000001 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5				0x00000002 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8				0x00000003 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8				0x00000004 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8				0x00000005 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8				0x00000006 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5				0x00000007 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8					0x00000008 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8				0x00000009 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION					0x00000304 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_AND				0x00000000 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_ROP_AND				0x00000001 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_AND				0x00000002 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY				0x00000003 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_PREMULT			0x00000004 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_PREMULT				0x00000005 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT					0x00000308 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_SHIFT				0 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_MASK				0x0000ffff +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT				16 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_MASK				0xffff0000 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE					0x0000030c +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_SHIFT				0 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_MASK				0x0000ffff +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT				16 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_MASK				0xffff0000 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT					0x00000310 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_X_SHIFT				0 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_X_MASK				0x0000ffff +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT				16 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_MASK				0xffff0000 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE						0x00000314 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_W_SHIFT				0 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_W_MASK					0x0000ffff +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT				16 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_MASK					0xffff0000 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_DU_DX						0x00000318 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_DV_DY						0x0000031c +#define  NV04_SCALED_IMAGE_FROM_MEMORY_SIZE						0x00000400 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_W_SHIFT					0 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_W_MASK					0x0000ffff +#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT					16 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_H_MASK					0xffff0000 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT						0x00000404 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_PITCH_SHIFT				0 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_PITCH_MASK				0x0000ffff +#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_SHIFT				16 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_MASK				0x00ff0000 +#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER				0x00010000 +#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CORNER				0x00020000 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_SHIFT				24 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_MASK				0xff000000 +#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE			0x00000000 +#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR				0x01000000 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_ADDRESS						0x00000408 +#define  NV04_SCALED_IMAGE_FROM_MEMORY_POINT						0x0000040c +#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_X_SHIFT					0 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_X_MASK					0x0000ffff +#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_Y_SHIFT					16 +#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_Y_MASK					0xffff0000 + + +#define NV10_TEXTURE_FROM_CPU								0x0000007b + +#define  NV10_TEXTURE_FROM_CPU_NOP							0x00000100 +#define  NV10_TEXTURE_FROM_CPU_NOTIFY							0x00000104 +#define  NV10_TEXTURE_FROM_CPU_WAIT_FOR_IDLE						0x00000108 +#define  NV10_TEXTURE_FROM_CPU_PM_TRIGGER						0x00000140 +#define  NV10_TEXTURE_FROM_CPU_DMA_NOTIFY						0x00000180 +#define  NV10_TEXTURE_FROM_CPU_SURFACE							0x00000184 +#define  NV10_TEXTURE_FROM_CPU_COLOR_FORMAT						0x00000300 +#define  NV10_TEXTURE_FROM_CPU_POINT							0x00000304 +#define   NV10_TEXTURE_FROM_CPU_POINT_X_SHIFT						0 +#define   NV10_TEXTURE_FROM_CPU_POINT_X_MASK						0x0000ffff +#define   NV10_TEXTURE_FROM_CPU_POINT_Y_SHIFT						16 +#define   NV10_TEXTURE_FROM_CPU_POINT_Y_MASK						0xffff0000 +#define  NV10_TEXTURE_FROM_CPU_SIZE							0x00000308 +#define   NV10_TEXTURE_FROM_CPU_SIZE_W_SHIFT						0 +#define   NV10_TEXTURE_FROM_CPU_SIZE_W_MASK						0x0000ffff +#define   NV10_TEXTURE_FROM_CPU_SIZE_H_SHIFT						16 +#define   NV10_TEXTURE_FROM_CPU_SIZE_H_MASK						0xffff0000 +#define  NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL						0x0000030c +#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_X_SHIFT					0 +#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_X_MASK					0x0000ffff +#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_W_SHIFT					16 +#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_W_MASK					0xffff0000 +#define  NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL						0x00000310 +#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_Y_SHIFT					0 +#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_Y_MASK					0x0000ffff +#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_H_SHIFT					16 +#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_H_MASK					0xffff0000 +#define  NV10_TEXTURE_FROM_CPU_COLOR(x)							(0x00000400+((x)*4)) +#define  NV10_TEXTURE_FROM_CPU_COLOR__SIZE						0x00000700 + + +#define NV10_VIDEO_DISPLAY								0x0000007c + + + +#define NV10_DVD_SUBPICTURE								0x00000088 + + + +#define NV10_SCALED_IMAGE_FROM_MEMORY							0x00000089 + +#define  NV10_SCALED_IMAGE_FROM_MEMORY_WAIT_FOR_IDLE					0x00000108 + + +#define NV10_IMAGE_FROM_CPU								0x0000008a + +#define  NV10_IMAGE_FROM_CPU_COLOR_CONVERSION						0x000002f8 + + +#define NV10_CONTEXT_SURFACES_3D							0x00000093 + + + +#define NV10_DX5_TEXTURE_TRIANGLE							0x00000094 + + + +#define NV10_DX6_MULTI_TEXTURE_TRIANGLE							0x00000095 + + + +#define NV11TCL										0x00000096 + +#define  NV11TCL_COLOR_LOGIC_OP_ENABLE							0x00000d40 +#define  NV11TCL_COLOR_LOGIC_OP_OP							0x00000d44 +#define   NV11TCL_COLOR_LOGIC_OP_OP_CLEAR						0x00001500 +#define   NV11TCL_COLOR_LOGIC_OP_OP_AND							0x00001501 +#define   NV11TCL_COLOR_LOGIC_OP_OP_AND_REVERSE						0x00001502 +#define   NV11TCL_COLOR_LOGIC_OP_OP_COPY						0x00001503 +#define   NV11TCL_COLOR_LOGIC_OP_OP_AND_INVERTED					0x00001504 +#define   NV11TCL_COLOR_LOGIC_OP_OP_NOOP						0x00001505 +#define   NV11TCL_COLOR_LOGIC_OP_OP_XOR							0x00001506 +#define   NV11TCL_COLOR_LOGIC_OP_OP_OR							0x00001507 +#define   NV11TCL_COLOR_LOGIC_OP_OP_NOR							0x00001508 +#define   NV11TCL_COLOR_LOGIC_OP_OP_EQUIV						0x00001509 +#define   NV11TCL_COLOR_LOGIC_OP_OP_INVERT						0x0000150a +#define   NV11TCL_COLOR_LOGIC_OP_OP_OR_REVERSE						0x0000150b +#define   NV11TCL_COLOR_LOGIC_OP_OP_COPY_INVERTED					0x0000150c +#define   NV11TCL_COLOR_LOGIC_OP_OP_OR_INVERTED						0x0000150d +#define   NV11TCL_COLOR_LOGIC_OP_OP_NAND						0x0000150e +#define   NV11TCL_COLOR_LOGIC_OP_OP_SET							0x0000150f + + +#define NV20TCL										0x00000097 + +#define  NV20TCL_NOP									0x00000100 +#define  NV20TCL_NOTIFY									0x00000104 +#define  NV20TCL_DMA_NOTIFY								0x00000180 +#define  NV20TCL_DMA_IN_MEMORY0								0x00000184 +#define  NV20TCL_DMA_IN_MEMORY1								0x00000188 +#define  NV20TCL_DMA_IN_MEMORY2								0x00000194 +#define  NV20TCL_DMA_IN_MEMORY3								0x00000198 +#define  NV20TCL_DMA_IN_MEMORY6								0x000001a4 +#define  NV20TCL_DMA_IN_MEMORY7								0x000001a8 +#define  NV20TCL_VIEWPORT_HORIZ								0x00000200 +#define  NV20TCL_VIEWPORT_VERT								0x00000204 +#define  NV20TCL_BUFFER_FORMAT								0x00000208 +#define  NV20TCL_BUFFER_PITCH								0x0000020c +#define  NV20TCL_COLOR_OFFSET								0x00000210 +#define  NV20TCL_ZETA_OFFSET								0x00000214 +#define  NV20TCL_RC_IN_ALPHA(x)								(0x00000260+((x)*4)) +#define  NV20TCL_RC_IN_ALPHA__SIZE							0x00000008 +#define  NV20TCL_RC_FINAL0								0x00000288 +#define  NV20TCL_RC_FINAL1								0x0000028c +#define  NV20TCL_LIGHT_CONTROL								0x00000294 +#define  NV20TCL_FOG_MODE								0x0000029c +#define  NV20TCL_FOG_COORD_DIST								0x000002a0 +#define  NV20TCL_FOG_ENABLE								0x000002a4 +#define  NV20TCL_FOG_COLOR								0x000002a8 +#define  NV20TCL_VIEWPORT_CLIP_MODE							0x000002b4 +#define  NV20TCL_VIEWPORT_CLIP_HORIZ(x)							(0x000002c0+((x)*4)) +#define  NV20TCL_VIEWPORT_CLIP_HORIZ__SIZE						0x00000008 +#define  NV20TCL_VIEWPORT_CLIP_VERT(x)							(0x000002e0+((x)*4)) +#define  NV20TCL_VIEWPORT_CLIP_VERT__SIZE						0x00000008 +#define  NV20TCL_ALPHA_FUNC_ENABLE							0x00000300 +#define  NV20TCL_BLEND_FUNC_ENABLE							0x00000304 +#define  NV20TCL_CULL_FACE_ENABLE							0x00000308 +#define  NV20TCL_DEPTH_TEST_ENABLE							0x0000030c +#define  NV20TCL_DITHER_ENABLE								0x00000310 +#define  NV20TCL_LIGHTING_ENABLE							0x00000314 +#define  NV20TCL_POINT_PARAMETERS_ENABLE						0x00000318 +#define  NV20TCL_LINE_SMOOTH_ENABLE							0x00000320 +#define  NV20TCL_POLYGON_SMOOTH_ENABLE							0x00000324 +#define  NV20TCL_STENCIL_ENABLE								0x0000032c +#define  NV20TCL_POLYGON_OFFSET_POINT_ENABLE						0x00000330 +#define  NV20TCL_POLYGON_OFFSET_LINE_ENABLE						0x00000334 +#define  NV20TCL_POLYGON_OFFSET_FILL_ENABLE						0x00000338 +#define  NV20TCL_ALPHA_FUNC_FUNC							0x0000033c +#define   NV20TCL_ALPHA_FUNC_FUNC_NEVER							0x00000200 +#define   NV20TCL_ALPHA_FUNC_FUNC_LESS							0x00000201 +#define   NV20TCL_ALPHA_FUNC_FUNC_EQUAL							0x00000202 +#define   NV20TCL_ALPHA_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV20TCL_ALPHA_FUNC_FUNC_GREATER						0x00000204 +#define   NV20TCL_ALPHA_FUNC_FUNC_GREATER						0x00000204 +#define   NV20TCL_ALPHA_FUNC_FUNC_NOTEQUAL						0x00000205 +#define   NV20TCL_ALPHA_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV20TCL_ALPHA_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV20TCL_ALPHA_FUNC_REF								0x00000340 +#define  NV20TCL_BLEND_FUNC_SRC								0x00000344 +#define   NV20TCL_BLEND_FUNC_SRC_ZERO							0x00000000 +#define   NV20TCL_BLEND_FUNC_SRC_ONE							0x00000001 +#define   NV20TCL_BLEND_FUNC_SRC_SRC_COLOR						0x00000300 +#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_COLOR					0x00000301 +#define   NV20TCL_BLEND_FUNC_SRC_SRC_ALPHA						0x00000302 +#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_ALPHA					0x00000303 +#define   NV20TCL_BLEND_FUNC_SRC_DST_ALPHA						0x00000304 +#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_ALPHA					0x00000305 +#define   NV20TCL_BLEND_FUNC_SRC_DST_COLOR						0x00000306 +#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_COLOR					0x00000307 +#define   NV20TCL_BLEND_FUNC_SRC_SRC_ALPHA_SATURATE					0x00000308 +#define   NV20TCL_BLEND_FUNC_SRC_CONSTANT_COLOR						0x00008001 +#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV20TCL_BLEND_FUNC_SRC_CONSTANT_ALPHA						0x00008003 +#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV20TCL_BLEND_FUNC_DST								0x00000348 +#define   NV20TCL_BLEND_FUNC_DST_ZERO							0x00000000 +#define   NV20TCL_BLEND_FUNC_DST_ONE							0x00000001 +#define   NV20TCL_BLEND_FUNC_DST_SRC_COLOR						0x00000300 +#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_COLOR					0x00000301 +#define   NV20TCL_BLEND_FUNC_DST_SRC_ALPHA						0x00000302 +#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_ALPHA					0x00000303 +#define   NV20TCL_BLEND_FUNC_DST_DST_ALPHA						0x00000304 +#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_DST_ALPHA					0x00000305 +#define   NV20TCL_BLEND_FUNC_DST_DST_COLOR						0x00000306 +#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_DST_COLOR					0x00000307 +#define   NV20TCL_BLEND_FUNC_DST_SRC_ALPHA_SATURATE					0x00000308 +#define   NV20TCL_BLEND_FUNC_DST_CONSTANT_COLOR						0x00008001 +#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV20TCL_BLEND_FUNC_DST_CONSTANT_ALPHA						0x00008003 +#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV20TCL_BLEND_COLOR								0x0000034c +#define  NV20TCL_BLEND_EQUATION								0x00000350 +#define   NV20TCL_BLEND_EQUATION_FUNC_ADD						0x00008006 +#define   NV20TCL_BLEND_EQUATION_MIN							0x00008007 +#define   NV20TCL_BLEND_EQUATION_MAX							0x00008008 +#define   NV20TCL_BLEND_EQUATION_FUNC_SUBTRACT						0x0000800a +#define   NV20TCL_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT					0x0000800b +#define  NV20TCL_DEPTH_FUNC								0x00000354 +#define   NV20TCL_DEPTH_FUNC_NEVER							0x00000200 +#define   NV20TCL_DEPTH_FUNC_LESS							0x00000201 +#define   NV20TCL_DEPTH_FUNC_EQUAL							0x00000202 +#define   NV20TCL_DEPTH_FUNC_LEQUAL							0x00000203 +#define   NV20TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV20TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV20TCL_DEPTH_FUNC_NOTEQUAL							0x00000205 +#define   NV20TCL_DEPTH_FUNC_GEQUAL							0x00000206 +#define   NV20TCL_DEPTH_FUNC_ALWAYS							0x00000207 +#define  NV20TCL_COLOR_MASK								0x00000358 +#define  NV20TCL_DEPTH_WRITE_ENABLE							0x0000035c +#define  NV20TCL_STENCIL_MASK								0x00000360 +#define  NV20TCL_STENCIL_FUNC_FUNC							0x00000364 +#define   NV20TCL_STENCIL_FUNC_FUNC_NEVER						0x00000200 +#define   NV20TCL_STENCIL_FUNC_FUNC_LESS						0x00000201 +#define   NV20TCL_STENCIL_FUNC_FUNC_EQUAL						0x00000202 +#define   NV20TCL_STENCIL_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV20TCL_STENCIL_FUNC_FUNC_GREATER						0x00000204 +#define   NV20TCL_STENCIL_FUNC_FUNC_GREATER						0x00000204 +#define   NV20TCL_STENCIL_FUNC_FUNC_NOTEQUAL						0x00000205 +#define   NV20TCL_STENCIL_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV20TCL_STENCIL_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV20TCL_STENCIL_FUNC_REF							0x00000368 +#define  NV20TCL_STENCIL_FUNC_MASK							0x0000036c +#define  NV20TCL_STENCIL_OP_FAIL							0x00000370 +#define   NV20TCL_STENCIL_OP_FAIL_ZERO							0x00000000 +#define   NV20TCL_STENCIL_OP_FAIL_INVERT						0x0000150a +#define   NV20TCL_STENCIL_OP_FAIL_KEEP							0x00001e00 +#define   NV20TCL_STENCIL_OP_FAIL_REPLACE						0x00001e01 +#define   NV20TCL_STENCIL_OP_FAIL_INCR							0x00001e02 +#define   NV20TCL_STENCIL_OP_FAIL_DECR							0x00001e03 +#define   NV20TCL_STENCIL_OP_FAIL_INCR_WRAP						0x00008507 +#define   NV20TCL_STENCIL_OP_FAIL_DECR_WRAP						0x00008508 +#define  NV20TCL_STENCIL_OP_ZFAIL							0x00000374 +#define   NV20TCL_STENCIL_OP_ZFAIL_ZERO							0x00000000 +#define   NV20TCL_STENCIL_OP_ZFAIL_INVERT						0x0000150a +#define   NV20TCL_STENCIL_OP_ZFAIL_KEEP							0x00001e00 +#define   NV20TCL_STENCIL_OP_ZFAIL_REPLACE						0x00001e01 +#define   NV20TCL_STENCIL_OP_ZFAIL_INCR							0x00001e02 +#define   NV20TCL_STENCIL_OP_ZFAIL_DECR							0x00001e03 +#define   NV20TCL_STENCIL_OP_ZFAIL_INCR_WRAP						0x00008507 +#define   NV20TCL_STENCIL_OP_ZFAIL_DECR_WRAP						0x00008508 +#define  NV20TCL_STENCIL_OP_ZPASS							0x00000378 +#define   NV20TCL_STENCIL_OP_ZPASS_ZERO							0x00000000 +#define   NV20TCL_STENCIL_OP_ZPASS_INVERT						0x0000150a +#define   NV20TCL_STENCIL_OP_ZPASS_KEEP							0x00001e00 +#define   NV20TCL_STENCIL_OP_ZPASS_REPLACE						0x00001e01 +#define   NV20TCL_STENCIL_OP_ZPASS_INCR							0x00001e02 +#define   NV20TCL_STENCIL_OP_ZPASS_DECR							0x00001e03 +#define   NV20TCL_STENCIL_OP_ZPASS_INCR_WRAP						0x00008507 +#define   NV20TCL_STENCIL_OP_ZPASS_DECR_WRAP						0x00008508 +#define  NV20TCL_SHADE_MODEL								0x0000037c +#define   NV20TCL_SHADE_MODEL_FLAT							0x00001d00 +#define   NV20TCL_SHADE_MODEL_SMOOTH							0x00001d01 +#define  NV20TCL_LINE_WIDTH								0x00000380 +#define  NV20TCL_POLYGON_OFFSET_FACTOR							0x00000384 +#define  NV20TCL_POLYGON_OFFSET_UNITS							0x00000388 +#define  NV20TCL_POLYGON_MODE_FRONT							0x0000038c +#define   NV20TCL_POLYGON_MODE_FRONT_POINT						0x00001b00 +#define   NV20TCL_POLYGON_MODE_FRONT_LINE						0x00001b01 +#define   NV20TCL_POLYGON_MODE_FRONT_FILL						0x00001b02 +#define  NV20TCL_POLYGON_MODE_BACK							0x00000390 +#define   NV20TCL_POLYGON_MODE_BACK_POINT						0x00001b00 +#define   NV20TCL_POLYGON_MODE_BACK_LINE						0x00001b01 +#define   NV20TCL_POLYGON_MODE_BACK_FILL						0x00001b02 +#define  NV20TCL_DEPTH_RANGE_NEAR							0x00000394 +#define  NV20TCL_DEPTH_RANGE_FAR							0x00000398 +#define  NV20TCL_CULL_FACE								0x0000039c +#define   NV20TCL_CULL_FACE_FRONT							0x00000404 +#define   NV20TCL_CULL_FACE_BACK							0x00000405 +#define   NV20TCL_CULL_FACE_FRONT_AND_BACK						0x00000408 +#define  NV20TCL_FRONT_FACE								0x000003a0 +#define   NV20TCL_FRONT_FACE_CW								0x00000900 +#define   NV20TCL_FRONT_FACE_CCW							0x00000901 +#define  NV20TCL_NORMALIZE_ENABLE							0x000003a4 +#define  NV20TCL_SEPARATE_SPECULAR_ENABLE						0x000003b8 +#define  NV20TCL_ENABLED_LIGHTS								0x000003bc +#define  NV20TCL_CLIP_PLANE_ENABLE(x)							(0x000003c0+((x)*4)) +#define  NV20TCL_CLIP_PLANE_ENABLE__SIZE						0x00000010 +#define  NV20TCL_TX_MATRIX_ENABLE(x)							(0x00000420+((x)*4)) +#define  NV20TCL_TX_MATRIX_ENABLE__SIZE							0x00000004 +#define  NV20TCL_POINT_SIZE								0x0000043c +#define  NV20TCL_MODELVIEW_MATRIX(x)							(0x00000480+((x)*4)) +#define  NV20TCL_MODELVIEW_MATRIX__SIZE							0x00000010 +#define  NV20TCL_PROJECTION_MATRIX(x)							(0x00000680+((x)*4)) +#define  NV20TCL_PROJECTION_MATRIX__SIZE						0x00000010 +#define  NV20TCL_TX0_MATRIX(x)								(0x000006c0+((x)*4)) +#define  NV20TCL_TX0_MATRIX__SIZE							0x00000010 +#define  NV20TCL_TX1_MATRIX(x)								(0x00000700+((x)*4)) +#define  NV20TCL_TX1_MATRIX__SIZE							0x00000010 +#define  NV20TCL_TX2_MATRIX(x)								(0x00000740+((x)*4)) +#define  NV20TCL_TX2_MATRIX__SIZE							0x00000010 +#define  NV20TCL_TX3_MATRIX(x)								(0x00000780+((x)*4)) +#define  NV20TCL_TX3_MATRIX__SIZE							0x00000010 +#define  NV20TCL_FOG_EQUATION_CONSTANT							0x000009c0 +#define  NV20TCL_FOG_EQUATION_LINEAR							0x000009c4 +#define  NV20TCL_FOG_EQUATION_QUADRATIC							0x000009c8 +#define  NV20TCL_VIEWPORT_SCALE0_X							0x00000a20 +#define  NV20TCL_VIEWPORT_SCALE0_Y							0x00000a24 +#define  NV20TCL_VIEWPORT_SCALE0_Z							0x00000a28 +#define  NV20TCL_VIEWPORT_SCALE0_W							0x00000a2c +#define  NV20TCL_POINT_PARAMETER(x)							(0x00000a30+((x)*4)) +#define  NV20TCL_POINT_PARAMETER__SIZE							0x00000007 +#define  NV20TCL_RC_CONSTANT_COLOR0(x)							(0x00000a60+((x)*4)) +#define  NV20TCL_RC_CONSTANT_COLOR0__SIZE						0x00000008 +#define  NV20TCL_RC_CONSTANT_COLOR1(x)							(0x00000a80+((x)*4)) +#define  NV20TCL_RC_CONSTANT_COLOR1__SIZE						0x00000008 +#define  NV20TCL_RC_OUT_ALPHA(x)							(0x00000aa0+((x)*4)) +#define  NV20TCL_RC_OUT_ALPHA__SIZE							0x00000008 +#define  NV20TCL_RC_IN_RGB(x)								(0x00000ac0+((x)*4)) +#define  NV20TCL_RC_IN_RGB__SIZE							0x00000008 +#define  NV20TCL_VIEWPORT_SCALE1_X							0x00000af0 +#define  NV20TCL_VIEWPORT_SCALE1_Y							0x00000af4 +#define  NV20TCL_VIEWPORT_SCALE1_Z							0x00000af8 +#define  NV20TCL_VIEWPORT_SCALE1_W							0x00000afc +#define  NV20TCL_VP_UPLOAD_INST(x)							(0x00000b00+((x)*4)) +#define  NV20TCL_VP_UPLOAD_INST__SIZE							0x00000004 +#define  NV20TCL_VP_UPLOAD_CONST(x)							(0x00000b80+((x)*4)) +#define  NV20TCL_VP_UPLOAD_CONST__SIZE							0x00000004 +#define  NV20TCL_POLYGON_STIPPLE_ENABLE							0x0000147c +#define  NV20TCL_POLYGON_STIPPLE_PATTERN(x)						(0x00001480+((x)*4)) +#define  NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE						0x00000020 +#define  NV20TCL_VERTEX_POS_3F_X							0x00001500 +#define  NV20TCL_VERTEX_POS_3F_Y							0x00001504 +#define  NV20TCL_VERTEX_POS_3F_Z							0x00001508 +#define  NV20TCL_VERTEX_POS_4F_X							0x00001518 +#define  NV20TCL_VERTEX_POS_4F_Y							0x0000151c +#define  NV20TCL_VERTEX_POS_4F_Z							0x00001520 +#define  NV20TCL_VERTEX_POS_3I_XY							0x00001528 +#define   NV20TCL_VERTEX_POS_3I_XY_X_SHIFT						0 +#define   NV20TCL_VERTEX_POS_3I_XY_X_MASK						0x0000ffff +#define   NV20TCL_VERTEX_POS_3I_XY_Y_SHIFT						16 +#define   NV20TCL_VERTEX_POS_3I_XY_Y_MASK						0xffff0000 +#define  NV20TCL_VERTEX_POS_3I_Z							0x0000152c +#define   NV20TCL_VERTEX_POS_3I_Z_Z_SHIFT						0 +#define   NV20TCL_VERTEX_POS_3I_Z_Z_MASK						0x0000ffff +#define  NV20TCL_VERTEX_NOR_3F_X							0x00001530 +#define  NV20TCL_VERTEX_NOR_3F_Y							0x00001534 +#define  NV20TCL_VERTEX_NOR_3F_Z							0x00001538 +#define  NV20TCL_VERTEX_NOR_3I_XY							0x00001540 +#define   NV20TCL_VERTEX_NOR_3I_XY_X_SHIFT						0 +#define   NV20TCL_VERTEX_NOR_3I_XY_X_MASK						0x0000ffff +#define   NV20TCL_VERTEX_NOR_3I_XY_Y_SHIFT						16 +#define   NV20TCL_VERTEX_NOR_3I_XY_Y_MASK						0xffff0000 +#define  NV20TCL_VERTEX_NOR_3I_Z							0x00001544 +#define   NV20TCL_VERTEX_NOR_3I_Z_Z_SHIFT						0 +#define   NV20TCL_VERTEX_NOR_3I_Z_Z_MASK						0x0000ffff +#define  NV20TCL_VERTEX_COL_4F_X							0x00001550 +#define  NV20TCL_VERTEX_COL_4F_Y							0x00001554 +#define  NV20TCL_VERTEX_COL_4F_Z							0x00001558 +#define  NV20TCL_VERTEX_COL_4F_W							0x0000155c +#define  NV20TCL_VERTEX_COL_3F_X							0x00001560 +#define  NV20TCL_VERTEX_COL_3F_Y							0x00001564 +#define  NV20TCL_VERTEX_COL_3F_Z							0x00001568 +#define  NV20TCL_VERTEX_COL_4I								0x0000156c +#define   NV20TCL_VERTEX_COL_4I_R_SHIFT							0 +#define   NV20TCL_VERTEX_COL_4I_R_MASK							0x000000ff +#define   NV20TCL_VERTEX_COL_4I_G_SHIFT							8 +#define   NV20TCL_VERTEX_COL_4I_G_MASK							0x0000ff00 +#define   NV20TCL_VERTEX_COL_4I_B_SHIFT							16 +#define   NV20TCL_VERTEX_COL_4I_B_MASK							0x00ff0000 +#define   NV20TCL_VERTEX_COL_4I_A_SHIFT							24 +#define   NV20TCL_VERTEX_COL_4I_A_MASK							0xff000000 +#define  NV20TCL_VERTEX_COL2_3F_X							0x00001580 +#define  NV20TCL_VERTEX_COL2_3F_Y							0x00001584 +#define  NV20TCL_VERTEX_COL2_3F_Z							0x00001588 +#define  NV20TCL_VERTEX_COL2_4I								0x0000158c +#define   NV20TCL_VERTEX_COL2_4I_R_SHIFT						0 +#define   NV20TCL_VERTEX_COL2_4I_R_MASK							0x000000ff +#define   NV20TCL_VERTEX_COL2_4I_G_SHIFT						8 +#define   NV20TCL_VERTEX_COL2_4I_G_MASK							0x0000ff00 +#define   NV20TCL_VERTEX_COL2_4I_B_SHIFT						16 +#define   NV20TCL_VERTEX_COL2_4I_B_MASK							0x00ff0000 +#define   NV20TCL_VERTEX_COL2_4I_A_SHIFT						24 +#define   NV20TCL_VERTEX_COL2_4I_A_MASK							0xff000000 +#define  NV20TCL_VERTEX_TX0_2F_S							0x00001590 +#define  NV20TCL_VERTEX_TX0_2F_T							0x00001594 +#define  NV20TCL_VERTEX_TX0_2I								0x00001598 +#define   NV20TCL_VERTEX_TX0_2I_S_SHIFT							0 +#define   NV20TCL_VERTEX_TX0_2I_S_MASK							0x0000ffff +#define   NV20TCL_VERTEX_TX0_2I_T_SHIFT							16 +#define   NV20TCL_VERTEX_TX0_2I_T_MASK							0xffff0000 +#define  NV20TCL_VERTEX_TX0_4F_S							0x000015a0 +#define  NV20TCL_VERTEX_TX0_4F_T							0x000015a4 +#define  NV20TCL_VERTEX_TX0_4F_R							0x000015a8 +#define  NV20TCL_VERTEX_TX0_4F_Q							0x000015ac +#define  NV20TCL_VERTEX_TX0_4I_ST							0x000015b0 +#define   NV20TCL_VERTEX_TX0_4I_ST_S_SHIFT						0 +#define   NV20TCL_VERTEX_TX0_4I_ST_S_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX0_4I_ST_T_SHIFT						16 +#define   NV20TCL_VERTEX_TX0_4I_ST_T_MASK						0xffff0000 +#define  NV20TCL_VERTEX_TX0_4I_RQ							0x000015b4 +#define   NV20TCL_VERTEX_TX0_4I_RQ_R_SHIFT						0 +#define   NV20TCL_VERTEX_TX0_4I_RQ_R_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX0_4I_RQ_Q_SHIFT						16 +#define   NV20TCL_VERTEX_TX0_4I_RQ_Q_MASK						0xffff0000 +#define  NV20TCL_VERTEX_TX1_2F_S							0x000015b8 +#define  NV20TCL_VERTEX_TX1_2F_T							0x000015bc +#define  NV20TCL_VERTEX_TX1_2I								0x000015c0 +#define   NV20TCL_VERTEX_TX1_2I_S_SHIFT							0 +#define   NV20TCL_VERTEX_TX1_2I_S_MASK							0x0000ffff +#define   NV20TCL_VERTEX_TX1_2I_T_SHIFT							16 +#define   NV20TCL_VERTEX_TX1_2I_T_MASK							0xffff0000 +#define  NV20TCL_VERTEX_TX1_4F_S							0x000015c8 +#define  NV20TCL_VERTEX_TX1_4F_T							0x000015cc +#define  NV20TCL_VERTEX_TX1_4F_R							0x000015d0 +#define  NV20TCL_VERTEX_TX1_4F_Q							0x000015d4 +#define  NV20TCL_VERTEX_TX1_4I_ST							0x000015d8 +#define   NV20TCL_VERTEX_TX1_4I_ST_S_SHIFT						0 +#define   NV20TCL_VERTEX_TX1_4I_ST_S_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX1_4I_ST_T_SHIFT						16 +#define   NV20TCL_VERTEX_TX1_4I_ST_T_MASK						0xffff0000 +#define  NV20TCL_VERTEX_TX1_4I_RQ							0x000015dc +#define   NV20TCL_VERTEX_TX1_4I_RQ_R_SHIFT						0 +#define   NV20TCL_VERTEX_TX1_4I_RQ_R_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX1_4I_RQ_Q_SHIFT						16 +#define   NV20TCL_VERTEX_TX1_4I_RQ_Q_MASK						0xffff0000 +#define  NV20TCL_VERTEX_TX2_2F_S							0x000015e0 +#define  NV20TCL_VERTEX_TX2_2F_T							0x000015e4 +#define  NV20TCL_VERTEX_TX2_2I								0x000015e8 +#define   NV20TCL_VERTEX_TX2_2I_S_SHIFT							0 +#define   NV20TCL_VERTEX_TX2_2I_S_MASK							0x0000ffff +#define   NV20TCL_VERTEX_TX2_2I_T_SHIFT							16 +#define   NV20TCL_VERTEX_TX2_2I_T_MASK							0xffff0000 +#define  NV20TCL_VERTEX_TX2_4F_S							0x000015f0 +#define  NV20TCL_VERTEX_TX2_4F_T							0x000015f4 +#define  NV20TCL_VERTEX_TX2_4F_R							0x000015f8 +#define  NV20TCL_VERTEX_TX2_4F_Q							0x000015fc +#define  NV20TCL_VERTEX_TX2_4I_ST							0x00001600 +#define   NV20TCL_VERTEX_TX2_4I_ST_S_SHIFT						0 +#define   NV20TCL_VERTEX_TX2_4I_ST_S_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX2_4I_ST_T_SHIFT						16 +#define   NV20TCL_VERTEX_TX2_4I_ST_T_MASK						0xffff0000 +#define  NV20TCL_VERTEX_TX2_4I_RQ							0x00001604 +#define   NV20TCL_VERTEX_TX2_4I_RQ_R_SHIFT						0 +#define   NV20TCL_VERTEX_TX2_4I_RQ_R_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX2_4I_RQ_Q_SHIFT						16 +#define   NV20TCL_VERTEX_TX2_4I_RQ_Q_MASK						0xffff0000 +#define  NV20TCL_VERTEX_TX3_2F_S							0x00001608 +#define  NV20TCL_VERTEX_TX3_2F_T							0x0000160c +#define  NV20TCL_VERTEX_TX3_2I								0x00001610 +#define   NV20TCL_VERTEX_TX3_2I_S_SHIFT							0 +#define   NV20TCL_VERTEX_TX3_2I_S_MASK							0x0000ffff +#define   NV20TCL_VERTEX_TX3_2I_T_SHIFT							16 +#define   NV20TCL_VERTEX_TX3_2I_T_MASK							0xffff0000 +#define  NV20TCL_VERTEX_TX3_4F_S							0x00001620 +#define  NV20TCL_VERTEX_TX3_4F_T							0x00001624 +#define  NV20TCL_VERTEX_TX3_4F_R							0x00001628 +#define  NV20TCL_VERTEX_TX3_4F_Q							0x0000162c +#define  NV20TCL_VERTEX_TX3_4I_ST							0x00001630 +#define   NV20TCL_VERTEX_TX3_4I_ST_S_SHIFT						0 +#define   NV20TCL_VERTEX_TX3_4I_ST_S_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX3_4I_ST_T_SHIFT						16 +#define   NV20TCL_VERTEX_TX3_4I_ST_T_MASK						0xffff0000 +#define  NV20TCL_VERTEX_TX3_4I_RQ							0x00001634 +#define   NV20TCL_VERTEX_TX3_4I_RQ_R_SHIFT						0 +#define   NV20TCL_VERTEX_TX3_4I_RQ_R_MASK						0x0000ffff +#define   NV20TCL_VERTEX_TX3_4I_RQ_Q_SHIFT						16 +#define   NV20TCL_VERTEX_TX3_4I_RQ_Q_MASK						0xffff0000 +#define  NV20TCL_EDGEFLAG_ENABLE							0x000016bc +#define  NV20TCL_VERTEX_ATTR_OFFSET(x)							(0x00001720+((x)*4)) +#define  NV20TCL_VERTEX_ATTR_OFFSET__SIZE						0x00000010 +#define  NV20TCL_VERTEX_ARRAY_FORMAT(x)							(0x00001760+((x)*4)) +#define  NV20TCL_VERTEX_ARRAY_FORMAT__SIZE						0x00000010 +#define   NV20TCL_VERTEX_ARRAY_FORMAT_TYPE_SHIFT					0 +#define   NV20TCL_VERTEX_ARRAY_FORMAT_TYPE_MASK						0x0000000f +#define   NV20TCL_VERTEX_ARRAY_FORMAT_FIELDS_SHIFT					4 +#define   NV20TCL_VERTEX_ARRAY_FORMAT_FIELDS_MASK					0x000000f0 +#define   NV20TCL_VERTEX_ARRAY_FORMAT_STRIDE_SHIFT					8 +#define   NV20TCL_VERTEX_ARRAY_FORMAT_STRIDE_MASK					0x0000ff00 +#define  NV20TCL_COLOR_LOGIC_OP_ENABLE							0x000017bc +#define  NV20TCL_COLOR_LOGIC_OP_OP							0x000017c0 +#define  NV20TCL_LIGHT_MODEL_TWO_SIDE_ENABLE						0x000017c4 +#define  NV20TCL_TX_SHADER_CULL_MODE							0x000017f8 +#define  NV20TCL_VERTEX_BEGIN_END							0x000017fc +#define  NV20TCL_VERTEX_BUFFER_DRAW_ARRAYS						0x00001810 +#define  NV20TCL_VERTEX_ARRAY_DATA							0x00001818 +#define  NV20TCL_TX_OFFSET(x)								(0x00001b00+((x)*64)) +#define  NV20TCL_TX_OFFSET__SIZE							0x00000004 +#define  NV20TCL_TX_FORMAT(x)								(0x00001b04+((x)*64)) +#define  NV20TCL_TX_FORMAT__SIZE							0x00000004 +#define  NV20TCL_TX_WRAP(x)								(0x00001b08+((x)*64)) +#define  NV20TCL_TX_WRAP__SIZE								0x00000004 +#define  NV20TCL_TX_ENABLE(x)								(0x00001b0c+((x)*64)) +#define  NV20TCL_TX_ENABLE__SIZE							0x00000004 +#define  NV20TCL_TX_FILTER(x)								(0x00001b14+((x)*64)) +#define  NV20TCL_TX_FILTER__SIZE							0x00000004 +#define  NV20TCL_TX_BORDER_COLOR(x)							(0x00001b24+((x)*64)) +#define  NV20TCL_TX_BORDER_COLOR__SIZE							0x00000004 +#define  NV20TCL_SCISSOR_HORIZ								0x00001c30 +#define  NV20TCL_SCISSOR_VERT								0x00001c50 +#define  NV20TCL_MULTISAMPLE_CONTROL							0x00001d7c +#define  NV20TCL_CLEAR_VALUE								0x00001d90 +#define  NV20TCL_CLEAR_BUFFERS								0x00001d94 +#define  NV20TCL_RC_COLOR0								0x00001e20 +#define  NV20TCL_RC_COLOR1								0x00001e24 +#define  NV20TCL_RC_OUT_RGB(x)								(0x00001e40+((x)*4)) +#define  NV20TCL_RC_OUT_RGB__SIZE							0x00000008 +#define  NV20TCL_RC_ENABLE								0x00001e60 +#define  NV20TCL_TX_SHADER_OP								0x00001e70 +#define  NV20TCL_VP_UPLOAD_CONST_ID							0x00001ea4 + + +#define NV17TCL										0x00000099 + +#define  NV17TCL_DMA_IN_MEMORY4								0x000001ac +#define  NV17TCL_DMA_IN_MEMORY5								0x000001b0 +#define  NV17TCL_COLOR_MASK_ENABLE							0x000002bc +#define  NV17TCL_LMA_DEPTH_BUFFER_PITCH							0x00000d5c +#define  NV17TCL_LMA_DEPTH_BUFFER_OFFSET						0x00000d60 +#define  NV17TCL_LMA_DEPTH_FILL_VALUE							0x00000d68 +#define  NV17TCL_LMA_DEPTH_BUFFER_CLEAR							0x00000d6c +#define  NV17TCL_LMA_DEPTH_ENABLE							0x00001658 + + +#define NV20_SWIZZLED_SURFACE								0x0000009e + + + +#define NV12_IMAGE_BLIT									0x0000009f + + + +#define NV30_CONTEXT_SURFACES_2D							0x00000362 + + + +#define NV30_STRETCHED_IMAGE_FROM_CPU							0x00000366 + + + +#define NV30_TEXTURE_FROM_CPU								0x0000037b + + + +#define NV30_SCALED_IMAGE_FROM_MEMORY							0x00000389 + + + +#define NV30_IMAGE_FROM_CPU								0x0000038a + + + +#define NV30TCL										0x00000397 + + + +#define NV30_SWIZZLED_SURFACE								0x0000039e + + + +#define NV35TCL										0x00000497 + + + +#define NV25TCL										0x00000597 + +#define  NV25TCL_DMA_IN_MEMORY4								0x0000019c +#define  NV25TCL_DMA_IN_MEMORY5								0x000001a0 +#define  NV25TCL_DMA_IN_MEMORY8								0x000001ac +#define  NV25TCL_DMA_IN_MEMORY9								0x000001b0 + + +#define NV34TCL										0x00000697 + +#define  NV34TCL_NOP									0x00000100 +#define  NV34TCL_NOTIFY									0x00000104 +#define  NV34TCL_DMA_NOTIFY								0x00000180 +#define  NV34TCL_DMA_TEXTURE0								0x00000184 +#define  NV34TCL_DMA_TEXTURE1								0x00000188 +#define  NV34TCL_DMA_COLOR1								0x0000018c +#define  NV34TCL_DMA_COLOR0								0x00000194 +#define  NV34TCL_DMA_ZETA								0x00000198 +#define  NV34TCL_DMA_VTXBUF0								0x0000019c +#define  NV34TCL_DMA_VTXBUF1								0x000001a0 +#define  NV34TCL_DMA_FENCE								0x000001a4 +#define  NV34TCL_DMA_QUERY								0x000001a8 +#define  NV34TCL_DMA_IN_MEMORY7								0x000001ac +#define  NV34TCL_DMA_IN_MEMORY8								0x000001b0 +#define  NV34TCL_RT_HORIZ								0x00000200 +#define   NV34TCL_RT_HORIZ_X_SHIFT							0 +#define   NV34TCL_RT_HORIZ_X_MASK							0x0000ffff +#define   NV34TCL_RT_HORIZ_W_SHIFT							16 +#define   NV34TCL_RT_HORIZ_W_MASK							0xffff0000 +#define  NV34TCL_RT_VERT								0x00000204 +#define   NV34TCL_RT_VERT_Y_SHIFT							0 +#define   NV34TCL_RT_VERT_Y_MASK							0x0000ffff +#define   NV34TCL_RT_VERT_H_SHIFT							16 +#define   NV34TCL_RT_VERT_H_MASK							0xffff0000 +#define  NV34TCL_RT_FORMAT								0x00000208 +#define   NV34TCL_RT_FORMAT_TYPE_SHIFT							8 +#define   NV34TCL_RT_FORMAT_TYPE_MASK							0x00000f00 +#define    NV34TCL_RT_FORMAT_TYPE_LINEAR						0x00000100 +#define    NV34TCL_RT_FORMAT_TYPE_SWIZZLED						0x00000200 +#define   NV34TCL_RT_FORMAT_ZETA_SHIFT							5 +#define   NV34TCL_RT_FORMAT_ZETA_MASK							0x000000e0 +#define    NV34TCL_RT_FORMAT_ZETA_Z16							0x00000020 +#define    NV34TCL_RT_FORMAT_ZETA_Z24S8							0x00000040 +#define   NV34TCL_RT_FORMAT_COLOR_SHIFT							0 +#define   NV34TCL_RT_FORMAT_COLOR_MASK							0x0000001f +#define    NV34TCL_RT_FORMAT_COLOR_R5G6B5						0x00000003 +#define    NV34TCL_RT_FORMAT_COLOR_X8R8G8B8						0x00000005 +#define    NV34TCL_RT_FORMAT_COLOR_A8R8G8B8						0x00000008 +#define    NV34TCL_RT_FORMAT_COLOR_B8							0x00000009 +#define    NV34TCL_RT_FORMAT_COLOR_X8B8G8R8						0x0000000f +#define    NV34TCL_RT_FORMAT_COLOR_A8B8G8R8						0x00000010 +#define  NV34TCL_COLOR0_PITCH								0x0000020c +#define   NV34TCL_COLOR0_PITCH_COLOR0_SHIFT						0 +#define   NV34TCL_COLOR0_PITCH_COLOR0_MASK						0x0000ffff +#define   NV34TCL_COLOR0_PITCH_ZETA_SHIFT						16 +#define   NV34TCL_COLOR0_PITCH_ZETA_MASK						0xffff0000 +#define  NV34TCL_COLOR0_OFFSET								0x00000210 +#define  NV34TCL_ZETA_OFFSET								0x00000214 +#define  NV34TCL_COLOR1_OFFSET								0x00000218 +#define  NV34TCL_COLOR1_PITCH								0x0000021c +#define  NV34TCL_RT_ENABLE								0x00000220 +#define   NV34TCL_RT_ENABLE_MRT								(1 <<  4) +#define   NV34TCL_RT_ENABLE_COLOR1							(1 <<  1) +#define   NV34TCL_RT_ENABLE_COLOR0							(1 <<  0) +#define  NV34TCL_LMA_DEPTH_PITCH							0x0000022c +#define  NV34TCL_LMA_DEPTH_OFFSET							0x00000230 +#define  NV34TCL_TX_UNITS_ENABLE							0x0000023c +#define   NV34TCL_TX_UNITS_ENABLE_TX0							(1 <<  0) +#define   NV34TCL_TX_UNITS_ENABLE_TX1							(1 <<  1) +#define   NV34TCL_TX_UNITS_ENABLE_TX2							(1 <<  2) +#define   NV34TCL_TX_UNITS_ENABLE_TX3							(1 <<  3) +#define  NV34TCL_TX_MATRIX_ENABLE(x)							(0x00000240+((x)*4)) +#define  NV34TCL_TX_MATRIX_ENABLE__SIZE							0x00000004 +#define  NV34TCL_UNK0250(x)								(0x00000250+((x)*4)) +#define  NV34TCL_UNK0250__SIZE								0x00000004 +#define  NV34TCL_VIEWPORT_TX_ORIGIN							0x000002b8 +#define   NV34TCL_VIEWPORT_TX_ORIGIN_X_SHIFT						0 +#define   NV34TCL_VIEWPORT_TX_ORIGIN_X_MASK						0x0000ffff +#define   NV34TCL_VIEWPORT_TX_ORIGIN_Y_SHIFT						16 +#define   NV34TCL_VIEWPORT_TX_ORIGIN_Y_MASK						0xffff0000 +#define  NV34TCL_VIEWPORT_CLIP_HORIZ(x)							(0x000002c0+((x)*8)) +#define  NV34TCL_VIEWPORT_CLIP_HORIZ__SIZE						0x00000008 +#define   NV34TCL_VIEWPORT_CLIP_HORIZ_L_SHIFT						0 +#define   NV34TCL_VIEWPORT_CLIP_HORIZ_L_MASK						0x0000ffff +#define   NV34TCL_VIEWPORT_CLIP_HORIZ_R_SHIFT						16 +#define   NV34TCL_VIEWPORT_CLIP_HORIZ_R_MASK						0xffff0000 +#define  NV34TCL_VIEWPORT_CLIP_VERT(x)							(0x000002c4+((x)*8)) +#define  NV34TCL_VIEWPORT_CLIP_VERT__SIZE						0x00000008 +#define   NV34TCL_VIEWPORT_CLIP_VERT_T_SHIFT						0 +#define   NV34TCL_VIEWPORT_CLIP_VERT_T_MASK						0x0000ffff +#define   NV34TCL_VIEWPORT_CLIP_VERT_D_SHIFT						16 +#define   NV34TCL_VIEWPORT_CLIP_VERT_D_MASK						0xffff0000 +#define  NV34TCL_DITHER_ENABLE								0x00000300 +#define  NV34TCL_ALPHA_FUNC_ENABLE							0x00000304 +#define  NV34TCL_ALPHA_FUNC_FUNC							0x00000308 +#define   NV34TCL_ALPHA_FUNC_FUNC_NEVER							0x00000200 +#define   NV34TCL_ALPHA_FUNC_FUNC_LESS							0x00000201 +#define   NV34TCL_ALPHA_FUNC_FUNC_EQUAL							0x00000202 +#define   NV34TCL_ALPHA_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV34TCL_ALPHA_FUNC_FUNC_GREATER						0x00000204 +#define   NV34TCL_ALPHA_FUNC_FUNC_GREATER						0x00000204 +#define   NV34TCL_ALPHA_FUNC_FUNC_NOTEQUAL						0x00000205 +#define   NV34TCL_ALPHA_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV34TCL_ALPHA_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV34TCL_ALPHA_FUNC_REF								0x0000030c +#define  NV34TCL_BLEND_FUNC_ENABLE							0x00000310 +#define  NV34TCL_BLEND_FUNC_SRC								0x00000314 +#define   NV34TCL_BLEND_FUNC_SRC_RGB_SHIFT						0 +#define   NV34TCL_BLEND_FUNC_SRC_RGB_MASK						0x0000ffff +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ZERO						0x00000000 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE						0x00000001 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_SRC_COLOR						0x00000300 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR				0x00000301 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA						0x00000302 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA				0x00000303 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_DST_ALPHA						0x00000304 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA				0x00000305 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_DST_COLOR						0x00000306 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR				0x00000307 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE				0x00000308 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR					0x00008001 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA					0x00008003 +#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define   NV34TCL_BLEND_FUNC_SRC_ALPHA_SHIFT						16 +#define   NV34TCL_BLEND_FUNC_SRC_ALPHA_MASK						0xffff0000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ZERO						0x00000000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE						0x00010000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_SRC_COLOR					0x03000000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_COLOR				0x03010000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA					0x03020000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_ALPHA				0x03030000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_DST_ALPHA					0x03040000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_ALPHA				0x03050000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_DST_COLOR					0x03060000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_COLOR				0x03070000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA_SATURATE				0x03080000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_COLOR					0x80010000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_COLOR			0x80020000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_ALPHA					0x80030000 +#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_ALPHA			0x80040000 +#define  NV34TCL_BLEND_FUNC_DST								0x00000318 +#define   NV34TCL_BLEND_FUNC_DST_RGB_SHIFT						0 +#define   NV34TCL_BLEND_FUNC_DST_RGB_MASK						0x0000ffff +#define    NV34TCL_BLEND_FUNC_DST_RGB_ZERO						0x00000000 +#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE						0x00000001 +#define    NV34TCL_BLEND_FUNC_DST_RGB_SRC_COLOR						0x00000300 +#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_COLOR				0x00000301 +#define    NV34TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA						0x00000302 +#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_ALPHA				0x00000303 +#define    NV34TCL_BLEND_FUNC_DST_RGB_DST_ALPHA						0x00000304 +#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_ALPHA				0x00000305 +#define    NV34TCL_BLEND_FUNC_DST_RGB_DST_COLOR						0x00000306 +#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_COLOR				0x00000307 +#define    NV34TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA_SATURATE				0x00000308 +#define    NV34TCL_BLEND_FUNC_DST_RGB_CONSTANT_COLOR					0x00008001 +#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define    NV34TCL_BLEND_FUNC_DST_RGB_CONSTANT_ALPHA					0x00008003 +#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define   NV34TCL_BLEND_FUNC_DST_ALPHA_SHIFT						16 +#define   NV34TCL_BLEND_FUNC_DST_ALPHA_MASK						0xffff0000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ZERO						0x00000000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE						0x00010000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_SRC_COLOR					0x03000000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_COLOR				0x03010000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA					0x03020000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_ALPHA				0x03030000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_DST_ALPHA					0x03040000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_ALPHA				0x03050000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_DST_COLOR					0x03060000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_COLOR				0x03070000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA_SATURATE				0x03080000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_COLOR					0x80010000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_COLOR			0x80020000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_ALPHA					0x80030000 +#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_ALPHA			0x80040000 +#define  NV34TCL_BLEND_COLOR								0x0000031c +#define   NV34TCL_BLEND_COLOR_B_SHIFT							0 +#define   NV34TCL_BLEND_COLOR_B_MASK							0x000000ff +#define   NV34TCL_BLEND_COLOR_G_SHIFT							8 +#define   NV34TCL_BLEND_COLOR_G_MASK							0x0000ff00 +#define   NV34TCL_BLEND_COLOR_R_SHIFT							16 +#define   NV34TCL_BLEND_COLOR_R_MASK							0x00ff0000 +#define   NV34TCL_BLEND_COLOR_A_SHIFT							24 +#define   NV34TCL_BLEND_COLOR_A_MASK							0xff000000 +#define  NV34TCL_BLEND_EQUATION								0x00000320 +#define   NV34TCL_BLEND_EQUATION_FUNC_ADD						0x00008006 +#define   NV34TCL_BLEND_EQUATION_MIN							0x00008007 +#define   NV34TCL_BLEND_EQUATION_MAX							0x00008008 +#define   NV34TCL_BLEND_EQUATION_FUNC_SUBTRACT						0x0000800a +#define   NV34TCL_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT					0x0000800b +#define  NV34TCL_COLOR_MASK								0x00000324 +#define   NV34TCL_COLOR_MASK_B_SHIFT							0 +#define   NV34TCL_COLOR_MASK_B_MASK							0x000000ff +#define   NV34TCL_COLOR_MASK_G_SHIFT							8 +#define   NV34TCL_COLOR_MASK_G_MASK							0x0000ff00 +#define   NV34TCL_COLOR_MASK_R_SHIFT							16 +#define   NV34TCL_COLOR_MASK_R_MASK							0x00ff0000 +#define   NV34TCL_COLOR_MASK_A_SHIFT							24 +#define   NV34TCL_COLOR_MASK_A_MASK							0xff000000 +#define  NV34TCL_STENCIL_BACK_ENABLE							0x00000328 +#define  NV34TCL_STENCIL_BACK_MASK							0x0000032c +#define  NV34TCL_STENCIL_BACK_FUNC_FUNC							0x00000330 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_NEVER						0x00000200 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_LESS						0x00000201 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_EQUAL						0x00000202 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_GREATER					0x00000204 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_GREATER					0x00000204 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_NOTEQUAL					0x00000205 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV34TCL_STENCIL_BACK_FUNC_REF							0x00000334 +#define  NV34TCL_STENCIL_BACK_FUNC_MASK							0x00000338 +#define  NV34TCL_STENCIL_BACK_OP_FAIL							0x0000033c +#define   NV34TCL_STENCIL_BACK_OP_FAIL_ZERO						0x00000000 +#define   NV34TCL_STENCIL_BACK_OP_FAIL_INVERT						0x0000150a +#define   NV34TCL_STENCIL_BACK_OP_FAIL_KEEP						0x00001e00 +#define   NV34TCL_STENCIL_BACK_OP_FAIL_REPLACE						0x00001e01 +#define   NV34TCL_STENCIL_BACK_OP_FAIL_INCR						0x00001e02 +#define   NV34TCL_STENCIL_BACK_OP_FAIL_DECR						0x00001e03 +#define   NV34TCL_STENCIL_BACK_OP_FAIL_INCR_WRAP					0x00008507 +#define   NV34TCL_STENCIL_BACK_OP_FAIL_DECR_WRAP					0x00008508 +#define  NV34TCL_STENCIL_BACK_OP_ZFAIL							0x00000340 +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_ZERO						0x00000000 +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_INVERT						0x0000150a +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_KEEP						0x00001e00 +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_REPLACE						0x00001e01 +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_INCR						0x00001e02 +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_DECR						0x00001e03 +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_INCR_WRAP					0x00008507 +#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_DECR_WRAP					0x00008508 +#define  NV34TCL_STENCIL_BACK_OP_ZPASS							0x00000344 +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_ZERO						0x00000000 +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_INVERT						0x0000150a +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_KEEP						0x00001e00 +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_REPLACE						0x00001e01 +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_INCR						0x00001e02 +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_DECR						0x00001e03 +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_INCR_WRAP					0x00008507 +#define   NV34TCL_STENCIL_BACK_OP_ZPASS_DECR_WRAP					0x00008508 +#define  NV34TCL_STENCIL_FRONT_ENABLE							0x00000348 +#define  NV34TCL_STENCIL_FRONT_MASK							0x0000034c +#define  NV34TCL_STENCIL_FRONT_FUNC_FUNC						0x00000350 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_NEVER						0x00000200 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_LESS						0x00000201 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_EQUAL						0x00000202 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_LEQUAL					0x00000203 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_GREATER					0x00000204 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_GREATER					0x00000204 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_NOTEQUAL					0x00000205 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_GEQUAL					0x00000206 +#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_ALWAYS					0x00000207 +#define  NV34TCL_STENCIL_FRONT_FUNC_REF							0x00000354 +#define  NV34TCL_STENCIL_FRONT_FUNC_MASK						0x00000358 +#define  NV34TCL_STENCIL_FRONT_OP_FAIL							0x0000035c +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_ZERO						0x00000000 +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_INVERT						0x0000150a +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_KEEP						0x00001e00 +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_REPLACE						0x00001e01 +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_INCR						0x00001e02 +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_DECR						0x00001e03 +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_INCR_WRAP					0x00008507 +#define   NV34TCL_STENCIL_FRONT_OP_FAIL_DECR_WRAP					0x00008508 +#define  NV34TCL_STENCIL_FRONT_OP_ZFAIL							0x00000360 +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_ZERO						0x00000000 +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_INVERT						0x0000150a +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_KEEP						0x00001e00 +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_REPLACE					0x00001e01 +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_INCR						0x00001e02 +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_DECR						0x00001e03 +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_INCR_WRAP					0x00008507 +#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_DECR_WRAP					0x00008508 +#define  NV34TCL_STENCIL_FRONT_OP_ZPASS							0x00000364 +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_ZERO						0x00000000 +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_INVERT						0x0000150a +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_KEEP						0x00001e00 +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_REPLACE					0x00001e01 +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_INCR						0x00001e02 +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_DECR						0x00001e03 +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_INCR_WRAP					0x00008507 +#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_DECR_WRAP					0x00008508 +#define  NV34TCL_SHADE_MODEL								0x00000368 +#define   NV34TCL_SHADE_MODEL_FLAT							0x00001d00 +#define   NV34TCL_SHADE_MODEL_SMOOTH							0x00001d01 +#define  NV34TCL_FOG_ENABLE								0x0000036c +#define  NV34TCL_FOG_COLOR								0x00000370 +#define  NV34TCL_COLOR_LOGIC_OP_ENABLE							0x00000374 +#define  NV34TCL_COLOR_LOGIC_OP_OP							0x00000378 +#define   NV34TCL_COLOR_LOGIC_OP_OP_CLEAR						0x00001500 +#define   NV34TCL_COLOR_LOGIC_OP_OP_AND							0x00001501 +#define   NV34TCL_COLOR_LOGIC_OP_OP_AND_REVERSE						0x00001502 +#define   NV34TCL_COLOR_LOGIC_OP_OP_COPY						0x00001503 +#define   NV34TCL_COLOR_LOGIC_OP_OP_AND_INVERTED					0x00001504 +#define   NV34TCL_COLOR_LOGIC_OP_OP_NOOP						0x00001505 +#define   NV34TCL_COLOR_LOGIC_OP_OP_XOR							0x00001506 +#define   NV34TCL_COLOR_LOGIC_OP_OP_OR							0x00001507 +#define   NV34TCL_COLOR_LOGIC_OP_OP_NOR							0x00001508 +#define   NV34TCL_COLOR_LOGIC_OP_OP_EQUIV						0x00001509 +#define   NV34TCL_COLOR_LOGIC_OP_OP_INVERT						0x0000150a +#define   NV34TCL_COLOR_LOGIC_OP_OP_OR_REVERSE						0x0000150b +#define   NV34TCL_COLOR_LOGIC_OP_OP_COPY_INVERTED					0x0000150c +#define   NV34TCL_COLOR_LOGIC_OP_OP_OR_INVERTED						0x0000150d +#define   NV34TCL_COLOR_LOGIC_OP_OP_NAND						0x0000150e +#define   NV34TCL_COLOR_LOGIC_OP_OP_SET							0x0000150f +#define  NV34TCL_NORMALIZE_ENABLE							0x0000037c +#define  NV34TCL_COLOR_MATERIAL								0x00000390 +#define   NV34TCL_COLOR_MATERIAL_FRONT_EMISSION_ENABLE					(1 <<  0) +#define   NV34TCL_COLOR_MATERIAL_FRONT_AMBIENT_ENABLE					(1 <<  2) +#define   NV34TCL_COLOR_MATERIAL_FRONT_DIFFUSE_ENABLE					(1 <<  4) +#define   NV34TCL_COLOR_MATERIAL_FRONT_SPECULAR_ENABLE					(1 <<  6) +#define   NV34TCL_COLOR_MATERIAL_BACK_EMISSION_ENABLE					(1 <<  8) +#define   NV34TCL_COLOR_MATERIAL_BACK_AMBIENT_ENABLE					(1 << 10) +#define   NV34TCL_COLOR_MATERIAL_BACK_DIFFUSE_ENABLE					(1 << 12) +#define   NV34TCL_COLOR_MATERIAL_BACK_SPECULAR_ENABLE					(1 << 14) +#define  NV34TCL_DEPTH_RANGE_NEAR							0x00000394 +#define  NV34TCL_DEPTH_RANGE_FAR							0x00000398 +#define  NV34TCL_COLOR_MATERIAL_FRONT_R							0x000003a0 +#define  NV34TCL_COLOR_MATERIAL_FRONT_G							0x000003a4 +#define  NV34TCL_COLOR_MATERIAL_FRONT_B							0x000003a8 +#define  NV34TCL_COLOR_MATERIAL_FRONT_A							0x000003b4 +#define  NV34TCL_LINE_WIDTH								0x000003b8 +#define  NV34TCL_LINE_SMOOTH_ENABLE							0x000003bc +#define  NV34TCL_CLIP_PLANE_ENABLE(x)							(0x00000400+((x)*4)) +#define  NV34TCL_CLIP_PLANE_ENABLE__SIZE						0x00000020 +#define   NV34TCL_CLIP_PLANE_ENABLE_FALSE						0x00000000 +#define   NV34TCL_CLIP_PLANE_ENABLE_EYE_LINEAR						0x00002400 +#define   NV34TCL_CLIP_PLANE_ENABLE_OBJECT_LINEAR					0x00002401 +#define  NV34TCL_MODELVIEW_MATRIX(x)							(0x00000480+((x)*4)) +#define  NV34TCL_MODELVIEW_MATRIX__SIZE							0x00000010 +#define  NV34TCL_INVERSE_MODELVIEW_MATRIX(x)						(0x00000580+((x)*4)) +#define  NV34TCL_INVERSE_MODELVIEW_MATRIX__SIZE						0x0000000c +#define  NV34TCL_PROJECTION_MATRIX(x)							(0x00000680+((x)*4)) +#define  NV34TCL_PROJECTION_MATRIX__SIZE						0x00000010 +#define  NV34TCL_TX0_MATRIX(x)								(0x000006c0+((x)*4)) +#define  NV34TCL_TX0_MATRIX__SIZE							0x00000010 +#define  NV34TCL_TX1_MATRIX(x)								(0x00000700+((x)*4)) +#define  NV34TCL_TX1_MATRIX__SIZE							0x00000010 +#define  NV34TCL_TX2_MATRIX(x)								(0x00000740+((x)*4)) +#define  NV34TCL_TX2_MATRIX__SIZE							0x00000010 +#define  NV34TCL_TX3_MATRIX(x)								(0x00000780+((x)*4)) +#define  NV34TCL_TX3_MATRIX__SIZE							0x00000010 +#define  NV34TCL_SCISSOR_HORIZ								0x000008c0 +#define   NV34TCL_SCISSOR_HORIZ_X_SHIFT							0 +#define   NV34TCL_SCISSOR_HORIZ_X_MASK							0x0000ffff +#define   NV34TCL_SCISSOR_HORIZ_W_SHIFT							16 +#define   NV34TCL_SCISSOR_HORIZ_W_MASK							0xffff0000 +#define  NV34TCL_SCISSOR_VERT								0x000008c4 +#define   NV34TCL_SCISSOR_VERT_Y_SHIFT							0 +#define   NV34TCL_SCISSOR_VERT_Y_MASK							0x0000ffff +#define   NV34TCL_SCISSOR_VERT_H_SHIFT							16 +#define   NV34TCL_SCISSOR_VERT_H_MASK							0xffff0000 +#define  NV34TCL_FOG_COORD_DIST								0x000008c8 +#define  NV34TCL_FOG_MODE								0x000008cc +#define   NV34TCL_FOG_MODE_EXP								0x00000800 +#define   NV34TCL_FOG_MODE_EXP_2							0x00000802 +#define   NV34TCL_FOG_MODE_EXP2								0x00000803 +#define   NV34TCL_FOG_MODE_LINEAR							0x00000804 +#define   NV34TCL_FOG_MODE_LINEAR_2							0x00002601 +#define  NV34TCL_FOG_EQUATION_CONSTANT							0x000008d0 +#define  NV34TCL_FOG_EQUATION_LINEAR							0x000008d4 +#define  NV34TCL_FOG_EQUATION_QUADRATIC							0x000008d8 +#define  NV34TCL_FP_ACTIVE_PROGRAM							0x000008e4 +#define   NV34TCL_FP_ACTIVE_PROGRAM_DMA0						(1 <<  0) +#define   NV34TCL_FP_ACTIVE_PROGRAM_DMA1						(1 <<  1) +#define   NV34TCL_FP_ACTIVE_PROGRAM_OFFSET_SHIFT					2 +#define   NV34TCL_FP_ACTIVE_PROGRAM_OFFSET_MASK						0xfffffffc +#define  NV34TCL_RC_COLOR0								0x000008ec +#define   NV34TCL_RC_COLOR0_B_SHIFT							0 +#define   NV34TCL_RC_COLOR0_B_MASK							0x000000ff +#define   NV34TCL_RC_COLOR0_G_SHIFT							8 +#define   NV34TCL_RC_COLOR0_G_MASK							0x0000ff00 +#define   NV34TCL_RC_COLOR0_R_SHIFT							16 +#define   NV34TCL_RC_COLOR0_R_MASK							0x00ff0000 +#define   NV34TCL_RC_COLOR0_A_SHIFT							24 +#define   NV34TCL_RC_COLOR0_A_MASK							0xff000000 +#define  NV34TCL_RC_COLOR1								0x000008f0 +#define   NV34TCL_RC_COLOR1_B_SHIFT							0 +#define   NV34TCL_RC_COLOR1_B_MASK							0x000000ff +#define   NV34TCL_RC_COLOR1_G_SHIFT							8 +#define   NV34TCL_RC_COLOR1_G_MASK							0x0000ff00 +#define   NV34TCL_RC_COLOR1_R_SHIFT							16 +#define   NV34TCL_RC_COLOR1_R_MASK							0x00ff0000 +#define   NV34TCL_RC_COLOR1_A_SHIFT							24 +#define   NV34TCL_RC_COLOR1_A_MASK							0xff000000 +#define  NV34TCL_RC_FINAL0								0x000008f4 +#define  NV34TCL_RC_FINAL1								0x000008f8 +#define  NV34TCL_RC_ENABLE								0x000008fc +#define  NV34TCL_RC_IN_ALPHA(x)								(0x00000900+((x)*32)) +#define  NV34TCL_RC_IN_ALPHA__SIZE							0x00000008 +#define  NV34TCL_RC_IN_RGB(x)								(0x00000904+((x)*32)) +#define  NV34TCL_RC_IN_RGB__SIZE							0x00000008 +#define  NV34TCL_RC_CONSTANT_COLOR0(x)							(0x00000908+((x)*32)) +#define  NV34TCL_RC_CONSTANT_COLOR0__SIZE						0x00000008 +#define   NV34TCL_RC_CONSTANT_COLOR0_B_SHIFT						0 +#define   NV34TCL_RC_CONSTANT_COLOR0_B_MASK						0x000000ff +#define   NV34TCL_RC_CONSTANT_COLOR0_G_SHIFT						8 +#define   NV34TCL_RC_CONSTANT_COLOR0_G_MASK						0x0000ff00 +#define   NV34TCL_RC_CONSTANT_COLOR0_R_SHIFT						16 +#define   NV34TCL_RC_CONSTANT_COLOR0_R_MASK						0x00ff0000 +#define   NV34TCL_RC_CONSTANT_COLOR0_A_SHIFT						24 +#define   NV34TCL_RC_CONSTANT_COLOR0_A_MASK						0xff000000 +#define  NV34TCL_RC_CONSTANT_COLOR1(x)							(0x0000090c+((x)*32)) +#define  NV34TCL_RC_CONSTANT_COLOR1__SIZE						0x00000008 +#define   NV34TCL_RC_CONSTANT_COLOR1_B_SHIFT						0 +#define   NV34TCL_RC_CONSTANT_COLOR1_B_MASK						0x000000ff +#define   NV34TCL_RC_CONSTANT_COLOR1_G_SHIFT						8 +#define   NV34TCL_RC_CONSTANT_COLOR1_G_MASK						0x0000ff00 +#define   NV34TCL_RC_CONSTANT_COLOR1_R_SHIFT						16 +#define   NV34TCL_RC_CONSTANT_COLOR1_R_MASK						0x00ff0000 +#define   NV34TCL_RC_CONSTANT_COLOR1_A_SHIFT						24 +#define   NV34TCL_RC_CONSTANT_COLOR1_A_MASK						0xff000000 +#define  NV34TCL_RC_OUT_ALPHA(x)							(0x00000910+((x)*32)) +#define  NV34TCL_RC_OUT_ALPHA__SIZE							0x00000008 +#define  NV34TCL_RC_OUT_RGB(x)								(0x00000914+((x)*32)) +#define  NV34TCL_RC_OUT_RGB__SIZE							0x00000008 +#define  NV34TCL_VIEWPORT_HORIZ								0x00000a00 +#define   NV34TCL_VIEWPORT_HORIZ_X_SHIFT						0 +#define   NV34TCL_VIEWPORT_HORIZ_X_MASK							0x0000ffff +#define   NV34TCL_VIEWPORT_HORIZ_W_SHIFT						16 +#define   NV34TCL_VIEWPORT_HORIZ_W_MASK							0xffff0000 +#define  NV34TCL_VIEWPORT_VERT								0x00000a04 +#define   NV34TCL_VIEWPORT_VERT_Y_SHIFT							0 +#define   NV34TCL_VIEWPORT_VERT_Y_MASK							0x0000ffff +#define   NV34TCL_VIEWPORT_VERT_H_SHIFT							16 +#define   NV34TCL_VIEWPORT_VERT_H_MASK							0xffff0000 +#define  NV34TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R			0x00000a10 +#define  NV34TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G			0x00000a14 +#define  NV34TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B			0x00000a18 +#define  NV34TCL_VIEWPORT_TRANSLATE_X							0x00000a20 +#define  NV34TCL_VIEWPORT_TRANSLATE_Y							0x00000a24 +#define  NV34TCL_VIEWPORT_TRANSLATE_Z							0x00000a28 +#define  NV34TCL_VIEWPORT_TRANSLATE_W							0x00000a2c +#define  NV34TCL_VIEWPORT_SCALE_X							0x00000a30 +#define  NV34TCL_VIEWPORT_SCALE_Y							0x00000a34 +#define  NV34TCL_VIEWPORT_SCALE_Z							0x00000a38 +#define  NV34TCL_VIEWPORT_SCALE_W							0x00000a3c +#define  NV34TCL_POLYGON_OFFSET_POINT_ENABLE						0x00000a60 +#define  NV34TCL_POLYGON_OFFSET_LINE_ENABLE						0x00000a64 +#define  NV34TCL_POLYGON_OFFSET_FILL_ENABLE						0x00000a68 +#define  NV34TCL_DEPTH_FUNC								0x00000a6c +#define   NV34TCL_DEPTH_FUNC_NEVER							0x00000200 +#define   NV34TCL_DEPTH_FUNC_LESS							0x00000201 +#define   NV34TCL_DEPTH_FUNC_EQUAL							0x00000202 +#define   NV34TCL_DEPTH_FUNC_LEQUAL							0x00000203 +#define   NV34TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV34TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV34TCL_DEPTH_FUNC_NOTEQUAL							0x00000205 +#define   NV34TCL_DEPTH_FUNC_GEQUAL							0x00000206 +#define   NV34TCL_DEPTH_FUNC_ALWAYS							0x00000207 +#define  NV34TCL_DEPTH_WRITE_ENABLE							0x00000a70 +#define  NV34TCL_DEPTH_TEST_ENABLE							0x00000a74 +#define  NV34TCL_POLYGON_OFFSET_FACTOR							0x00000a78 +#define  NV34TCL_POLYGON_OFFSET_UNITS							0x00000a7c +#define  NV34TCL_VTX_ATTR_3I_XY(x)							(0x00000a80+((x)*8)) +#define  NV34TCL_VTX_ATTR_3I_XY__SIZE							0x00000010 +#define   NV34TCL_VTX_ATTR_3I_XY_X_SHIFT						0 +#define   NV34TCL_VTX_ATTR_3I_XY_X_MASK							0x0000ffff +#define   NV34TCL_VTX_ATTR_3I_XY_Y_SHIFT						16 +#define   NV34TCL_VTX_ATTR_3I_XY_Y_MASK							0xffff0000 +#define  NV34TCL_VTX_ATTR_3I_Z(x)							(0x00000a84+((x)*8)) +#define  NV34TCL_VTX_ATTR_3I_Z__SIZE							0x00000010 +#define   NV34TCL_VTX_ATTR_3I_Z_Z_SHIFT							0 +#define   NV34TCL_VTX_ATTR_3I_Z_Z_MASK							0x0000ffff +#define  NV34TCL_VP_UPLOAD_INST(x)							(0x00000b80+((x)*4)) +#define  NV34TCL_VP_UPLOAD_INST__SIZE							0x00000004 +#define  NV34TCL_CLIP_PLANE_A(x)							(0x00000e00+((x)*16)) +#define  NV34TCL_CLIP_PLANE_A__SIZE							0x00000020 +#define  NV34TCL_CLIP_PLANE_B(x)							(0x00000e04+((x)*16)) +#define  NV34TCL_CLIP_PLANE_B__SIZE							0x00000020 +#define  NV34TCL_CLIP_PLANE_C(x)							(0x00000e08+((x)*16)) +#define  NV34TCL_CLIP_PLANE_C__SIZE							0x00000020 +#define  NV34TCL_CLIP_PLANE_D(x)							(0x00000e0c+((x)*16)) +#define  NV34TCL_CLIP_PLANE_D__SIZE							0x00000020 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(x)					(0x00001000+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(x)					(0x00001004+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(x)					(0x00001008+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(x)					(0x0000100c+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(x)					(0x00001010+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(x)					(0x00001014+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(x)					(0x00001018+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(x)					(0x0000101c+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G__SIZE				0x00000008 +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(x)					(0x00001020+((x)*64)) +#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B__SIZE				0x00000008 +#define  NV34TCL_LIGHT_HALF_VECTOR_X(x)							(0x00001028+((x)*64)) +#define  NV34TCL_LIGHT_HALF_VECTOR_X__SIZE						0x00000008 +#define  NV34TCL_LIGHT_HALF_VECTOR_Y(x)							(0x0000102c+((x)*64)) +#define  NV34TCL_LIGHT_HALF_VECTOR_Y__SIZE						0x00000008 +#define  NV34TCL_LIGHT_HALF_VECTOR_Z(x)							(0x00001030+((x)*64)) +#define  NV34TCL_LIGHT_HALF_VECTOR_Z__SIZE						0x00000008 +#define  NV34TCL_LIGHT_DIRECTION_X(x)							(0x00001034+((x)*64)) +#define  NV34TCL_LIGHT_DIRECTION_X__SIZE						0x00000008 +#define  NV34TCL_LIGHT_DIRECTION_Y(x)							(0x00001038+((x)*64)) +#define  NV34TCL_LIGHT_DIRECTION_Y__SIZE						0x00000008 +#define  NV34TCL_LIGHT_DIRECTION_Z(x)							(0x0000103c+((x)*64)) +#define  NV34TCL_LIGHT_DIRECTION_Z__SIZE						0x00000008 +#define  NV34TCL_LIGHT_SPOT_CUTOFF_A(x)							(0x00001200+((x)*64)) +#define  NV34TCL_LIGHT_SPOT_CUTOFF_A__SIZE						0x00000008 +#define  NV34TCL_LIGHT_SPOT_CUTOFF_B(x)							(0x00001204+((x)*64)) +#define  NV34TCL_LIGHT_SPOT_CUTOFF_B__SIZE						0x00000008 +#define  NV34TCL_LIGHT_SPOT_CUTOFF_C(x)							(0x00001208+((x)*64)) +#define  NV34TCL_LIGHT_SPOT_CUTOFF_C__SIZE						0x00000008 +#define  NV34TCL_LIGHT_SPOT_DIR_X(x)							(0x0000120c+((x)*64)) +#define  NV34TCL_LIGHT_SPOT_DIR_X__SIZE							0x00000008 +#define  NV34TCL_LIGHT_SPOT_DIR_Y(x)							(0x00001210+((x)*64)) +#define  NV34TCL_LIGHT_SPOT_DIR_Y__SIZE							0x00000008 +#define  NV34TCL_LIGHT_SPOT_DIR_Z(x)							(0x00001214+((x)*64)) +#define  NV34TCL_LIGHT_SPOT_DIR_Z__SIZE							0x00000008 +#define  NV34TCL_LIGHT_SPOT_CUTOFF_D(x)							(0x00001218+((x)*64)) +#define  NV34TCL_LIGHT_SPOT_CUTOFF_D__SIZE						0x00000008 +#define  NV34TCL_LIGHT_POSITION_X(x)							(0x0000121c+((x)*64)) +#define  NV34TCL_LIGHT_POSITION_X__SIZE							0x00000008 +#define  NV34TCL_LIGHT_POSITION_Y(x)							(0x00001220+((x)*64)) +#define  NV34TCL_LIGHT_POSITION_Y__SIZE							0x00000008 +#define  NV34TCL_LIGHT_POSITION_Z(x)							(0x00001224+((x)*64)) +#define  NV34TCL_LIGHT_POSITION_Z__SIZE							0x00000008 +#define  NV34TCL_LIGHT_ATTENUATION_CONSTANT(x)						(0x00001228+((x)*64)) +#define  NV34TCL_LIGHT_ATTENUATION_CONSTANT__SIZE					0x00000008 +#define  NV34TCL_LIGHT_ATTENUATION_LINEAR(x)						(0x0000122c+((x)*64)) +#define  NV34TCL_LIGHT_ATTENUATION_LINEAR__SIZE						0x00000008 +#define  NV34TCL_LIGHT_ATTENUATION_QUADRATIC(x)						(0x00001230+((x)*64)) +#define  NV34TCL_LIGHT_ATTENUATION_QUADRATIC__SIZE					0x00000008 +#define  NV34TCL_FRONT_MATERIAL_SHININESS(x)						(0x00001400+((x)*4)) +#define  NV34TCL_FRONT_MATERIAL_SHININESS__SIZE						0x00000006 +#define  NV34TCL_ENABLED_LIGHTS								0x00001420 +#define  NV34TCL_FP_REG_CONTROL								0x00001450 +#define   NV34TCL_FP_REG_CONTROL_UNK1_SHIFT						16 +#define   NV34TCL_FP_REG_CONTROL_UNK1_MASK						0xffff0000 +#define   NV34TCL_FP_REG_CONTROL_UNK0_SHIFT						0 +#define   NV34TCL_FP_REG_CONTROL_UNK0_MASK						0x0000ffff +#define  NV34TCL_VP_CLIP_PLANES_ENABLE							0x00001478 +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0						(1 <<  1) +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1						(1 <<  5) +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2						(1 <<  9) +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3						(1 << 13) +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4						(1 << 17) +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5						(1 << 21) +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE6						(1 << 25) +#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE7						(1 << 29) +#define  NV34TCL_POLYGON_STIPPLE_ENABLE							0x0000147c +#define  NV34TCL_POLYGON_STIPPLE_PATTERN(x)						(0x00001480+((x)*4)) +#define  NV34TCL_POLYGON_STIPPLE_PATTERN__SIZE						0x00000020 +#define  NV34TCL_VTX_ATTR_3F_X(x)							(0x00001500+((x)*16)) +#define  NV34TCL_VTX_ATTR_3F_X__SIZE							0x00000010 +#define  NV34TCL_VTX_ATTR_3F_Y(x)							(0x00001504+((x)*16)) +#define  NV34TCL_VTX_ATTR_3F_Y__SIZE							0x00000010 +#define  NV34TCL_VTX_ATTR_3F_Z(x)							(0x00001508+((x)*16)) +#define  NV34TCL_VTX_ATTR_3F_Z__SIZE							0x00000010 +#define  NV34TCL_VP_CLIP_PLANE_A(x)							(0x00001600+((x)*16)) +#define  NV34TCL_VP_CLIP_PLANE_A__SIZE							0x00000006 +#define  NV34TCL_VP_CLIP_PLANE_B(x)							(0x00001604+((x)*16)) +#define  NV34TCL_VP_CLIP_PLANE_B__SIZE							0x00000006 +#define  NV34TCL_VP_CLIP_PLANE_C(x)							(0x00001608+((x)*16)) +#define  NV34TCL_VP_CLIP_PLANE_C__SIZE							0x00000006 +#define  NV34TCL_VP_CLIP_PLANE_D(x)							(0x0000160c+((x)*16)) +#define  NV34TCL_VP_CLIP_PLANE_D__SIZE							0x00000006 +#define  NV34TCL_VTXBUF_ADDRESS(x)							(0x00001680+((x)*4)) +#define  NV34TCL_VTXBUF_ADDRESS__SIZE							0x00000010 +#define   NV34TCL_VTXBUF_ADDRESS_DMA1							(1 << 31) +#define   NV34TCL_VTXBUF_ADDRESS_OFFSET_SHIFT						0 +#define   NV34TCL_VTXBUF_ADDRESS_OFFSET_MASK						0x0fffffff +#define  NV34TCL_VTXFMT(x)								(0x00001740+((x)*4)) +#define  NV34TCL_VTXFMT__SIZE								0x00000010 +#define   NV34TCL_VTXFMT_TYPE_SHIFT							0 +#define   NV34TCL_VTXFMT_TYPE_MASK							0x0000000f +#define    NV34TCL_VTXFMT_TYPE_FLOAT							0x00000002 +#define    NV34TCL_VTXFMT_TYPE_UBYTE							0x00000004 +#define    NV34TCL_VTXFMT_TYPE_USHORT							0x00000005 +#define   NV34TCL_VTXFMT_SIZE_SHIFT							4 +#define   NV34TCL_VTXFMT_SIZE_MASK							0x000000f0 +#define   NV34TCL_VTXFMT_STRIDE_SHIFT							8 +#define   NV34TCL_VTXFMT_STRIDE_MASK							0x0000ff00 +#define  NV34TCL_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R			0x000017a0 +#define  NV34TCL_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G			0x000017a4 +#define  NV34TCL_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B			0x000017a8 +#define  NV34TCL_COLOR_MATERIAL_BACK_R							0x000017b0 +#define  NV34TCL_COLOR_MATERIAL_BACK_G							0x000017b4 +#define  NV34TCL_COLOR_MATERIAL_BACK_B							0x000017b8 +#define  NV34TCL_COLOR_MATERIAL_BACK_A							0x000017c0 +#define  NV34TCL_QUERY_RESET								0x000017c8 +#define  NV34TCL_QUERY_UNK17CC								0x000017cc +#define  NV34TCL_QUERY_GET								0x00001800 +#define   NV34TCL_QUERY_GET_UNK24_SHIFT							24 +#define   NV34TCL_QUERY_GET_UNK24_MASK							0xff000000 +#define   NV34TCL_QUERY_GET_OFFSET_SHIFT						0 +#define   NV34TCL_QUERY_GET_OFFSET_MASK							0x00ffffff +#define  NV34TCL_VERTEX_BEGIN_END							0x00001808 +#define   NV34TCL_VERTEX_BEGIN_END_STOP							0x00000000 +#define   NV34TCL_VERTEX_BEGIN_END_POINTS						0x00000001 +#define   NV34TCL_VERTEX_BEGIN_END_LINES						0x00000002 +#define   NV34TCL_VERTEX_BEGIN_END_LINE_LOOP						0x00000003 +#define   NV34TCL_VERTEX_BEGIN_END_LINE_STRIP						0x00000004 +#define   NV34TCL_VERTEX_BEGIN_END_TRIANGLES						0x00000005 +#define   NV34TCL_VERTEX_BEGIN_END_TRIANGLE_STRIP					0x00000006 +#define   NV34TCL_VERTEX_BEGIN_END_TRIANGLE_FAN						0x00000007 +#define   NV34TCL_VERTEX_BEGIN_END_QUADS						0x00000008 +#define   NV34TCL_VERTEX_BEGIN_END_QUAD_STRIP						0x00000009 +#define   NV34TCL_VERTEX_BEGIN_END_POLYGON						0x0000000a +#define  NV34TCL_VB_ELEMENT_U16								0x0000180c +#define   NV34TCL_VB_ELEMENT_U16_I0_SHIFT						0 +#define   NV34TCL_VB_ELEMENT_U16_I0_MASK						0x0000ffff +#define   NV34TCL_VB_ELEMENT_U16_I1_SHIFT						16 +#define   NV34TCL_VB_ELEMENT_U16_I1_MASK						0xffff0000 +#define  NV34TCL_VB_ELEMENT_U32								0x00001810 +#define  NV34TCL_VB_VERTEX_BATCH							0x00001814 +#define   NV34TCL_VB_VERTEX_BATCH_OFFSET_SHIFT						0 +#define   NV34TCL_VB_VERTEX_BATCH_OFFSET_MASK						0x00ffffff +#define   NV34TCL_VB_VERTEX_BATCH_COUNT_SHIFT						24 +#define   NV34TCL_VB_VERTEX_BATCH_COUNT_MASK						0xff000000 +#define  NV34TCL_VERTEX_DATA								0x00001818 +#define  NV34TCL_IDXBUF_ADDRESS								0x0000181c +#define  NV34TCL_IDXBUF_FORMAT								0x00001820 +#define   NV34TCL_IDXBUF_FORMAT_TYPE_SHIFT						4 +#define   NV34TCL_IDXBUF_FORMAT_TYPE_MASK						0x000000f0 +#define    NV34TCL_IDXBUF_FORMAT_TYPE_U32						0x00000000 +#define    NV34TCL_IDXBUF_FORMAT_TYPE_U16						0x00000010 +#define   NV34TCL_IDXBUF_FORMAT_DMA1							(1 <<  0) +#define  NV34TCL_VB_INDEX_BATCH								0x00001824 +#define   NV34TCL_VB_INDEX_BATCH_COUNT_SHIFT						24 +#define   NV34TCL_VB_INDEX_BATCH_COUNT_MASK						0xff000000 +#define   NV34TCL_VB_INDEX_BATCH_START_SHIFT						0 +#define   NV34TCL_VB_INDEX_BATCH_START_MASK						0x00ffffff +#define  NV34TCL_POLYGON_MODE_FRONT							0x00001828 +#define   NV34TCL_POLYGON_MODE_FRONT_POINT						0x00001b00 +#define   NV34TCL_POLYGON_MODE_FRONT_LINE						0x00001b01 +#define   NV34TCL_POLYGON_MODE_FRONT_FILL						0x00001b02 +#define  NV34TCL_POLYGON_MODE_BACK							0x0000182c +#define   NV34TCL_POLYGON_MODE_BACK_POINT						0x00001b00 +#define   NV34TCL_POLYGON_MODE_BACK_LINE						0x00001b01 +#define   NV34TCL_POLYGON_MODE_BACK_FILL						0x00001b02 +#define  NV34TCL_CULL_FACE								0x00001830 +#define   NV34TCL_CULL_FACE_FRONT							0x00000404 +#define   NV34TCL_CULL_FACE_BACK							0x00000405 +#define   NV34TCL_CULL_FACE_FRONT_AND_BACK						0x00000408 +#define  NV34TCL_FRONT_FACE								0x00001834 +#define   NV34TCL_FRONT_FACE_CW								0x00000900 +#define   NV34TCL_FRONT_FACE_CCW							0x00000901 +#define  NV34TCL_POLYGON_SMOOTH_ENABLE							0x00001838 +#define  NV34TCL_CULL_FACE_ENABLE							0x0000183c +#define  NV34TCL_TX_PALETTE_OFFSET(x)							(0x00001840+((x)*4)) +#define  NV34TCL_TX_PALETTE_OFFSET__SIZE						0x00000004 +#define  NV34TCL_VTX_ATTR_2F_X(x)							(0x00001880+((x)*8)) +#define  NV34TCL_VTX_ATTR_2F_X__SIZE							0x00000010 +#define  NV34TCL_VTX_ATTR_2F_Y(x)							(0x00001884+((x)*8)) +#define  NV34TCL_VTX_ATTR_2F_Y__SIZE							0x00000010 +#define  NV34TCL_VTX_ATTR_2I(x)								(0x00001900+((x)*4)) +#define  NV34TCL_VTX_ATTR_2I__SIZE							0x00000010 +#define   NV34TCL_VTX_ATTR_2I_X_SHIFT							0 +#define   NV34TCL_VTX_ATTR_2I_X_MASK							0x0000ffff +#define   NV34TCL_VTX_ATTR_2I_Y_SHIFT							16 +#define   NV34TCL_VTX_ATTR_2I_Y_MASK							0xffff0000 +#define  NV34TCL_VTX_ATTR_4UB(x)							(0x00001940+((x)*4)) +#define  NV34TCL_VTX_ATTR_4UB__SIZE							0x00000010 +#define   NV34TCL_VTX_ATTR_4UB_X_SHIFT							0 +#define   NV34TCL_VTX_ATTR_4UB_X_MASK							0x000000ff +#define   NV34TCL_VTX_ATTR_4UB_Y_SHIFT							8 +#define   NV34TCL_VTX_ATTR_4UB_Y_MASK							0x0000ff00 +#define   NV34TCL_VTX_ATTR_4UB_Z_SHIFT							16 +#define   NV34TCL_VTX_ATTR_4UB_Z_MASK							0x00ff0000 +#define   NV34TCL_VTX_ATTR_4UB_W_SHIFT							24 +#define   NV34TCL_VTX_ATTR_4UB_W_MASK							0xff000000 +#define  NV34TCL_VTX_ATTR_4I_XY(x)							(0x00001980+((x)*8)) +#define  NV34TCL_VTX_ATTR_4I_XY__SIZE							0x00000010 +#define   NV34TCL_VTX_ATTR_4I_XY_X_SHIFT						0 +#define   NV34TCL_VTX_ATTR_4I_XY_X_MASK							0x0000ffff +#define   NV34TCL_VTX_ATTR_4I_XY_Y_SHIFT						16 +#define   NV34TCL_VTX_ATTR_4I_XY_Y_MASK							0xffff0000 +#define  NV34TCL_VTX_ATTR_4I_ZW(x)							(0x00001984+((x)*8)) +#define  NV34TCL_VTX_ATTR_4I_ZW__SIZE							0x00000010 +#define   NV34TCL_VTX_ATTR_4I_ZW_Z_SHIFT						0 +#define   NV34TCL_VTX_ATTR_4I_ZW_Z_MASK							0x0000ffff +#define   NV34TCL_VTX_ATTR_4I_ZW_W_SHIFT						16 +#define   NV34TCL_VTX_ATTR_4I_ZW_W_MASK							0xffff0000 +#define  NV34TCL_TX_OFFSET(x)								(0x00001a00+((x)*32)) +#define  NV34TCL_TX_OFFSET__SIZE							0x00000004 +#define  NV34TCL_TX_FORMAT(x)								(0x00001a04+((x)*32)) +#define  NV34TCL_TX_FORMAT__SIZE							0x00000004 +#define   NV34TCL_TX_FORMAT_DMA0							(1 <<  0) +#define   NV34TCL_TX_FORMAT_DMA1							(1 <<  1) +#define   NV34TCL_TX_FORMAT_CUBIC							(1 <<  2) +#define   NV34TCL_TX_FORMAT_NO_BORDER							(1 <<  3) +#define   NV34TCL_TX_FORMAT_DIMS_SHIFT							4 +#define   NV34TCL_TX_FORMAT_DIMS_MASK							0x000000f0 +#define    NV34TCL_TX_FORMAT_DIMS_1D							0x00000010 +#define    NV34TCL_TX_FORMAT_DIMS_2D							0x00000020 +#define    NV34TCL_TX_FORMAT_DIMS_3D							0x00000030 +#define   NV34TCL_TX_FORMAT_FORMAT_SHIFT						8 +#define   NV34TCL_TX_FORMAT_FORMAT_MASK							0x0000ff00 +#define    NV34TCL_TX_FORMAT_FORMAT_L8							0x00000000 +#define    NV34TCL_TX_FORMAT_FORMAT_A8							0x00000100 +#define    NV34TCL_TX_FORMAT_FORMAT_A1R5G5B5						0x00000200 +#define    NV34TCL_TX_FORMAT_FORMAT_A8_RECT						0x00000300 +#define    NV34TCL_TX_FORMAT_FORMAT_A4R4G4B4						0x00000400 +#define    NV34TCL_TX_FORMAT_FORMAT_R5G6B5						0x00000500 +#define    NV34TCL_TX_FORMAT_FORMAT_A8R8G8B8						0x00000600 +#define    NV34TCL_TX_FORMAT_FORMAT_X8R8G8B8						0x00000700 +#define    NV34TCL_TX_FORMAT_FORMAT_INDEX8						0x00000b00 +#define    NV34TCL_TX_FORMAT_FORMAT_DXT1						0x00000c00 +#define    NV34TCL_TX_FORMAT_FORMAT_DXT3						0x00000e00 +#define    NV34TCL_TX_FORMAT_FORMAT_DXT5						0x00000f00 +#define    NV34TCL_TX_FORMAT_FORMAT_A1R5G5B5_RECT					0x00001000 +#define    NV34TCL_TX_FORMAT_FORMAT_R5G6B5_RECT						0x00001100 +#define    NV34TCL_TX_FORMAT_FORMAT_A8R8G8B8_RECT					0x00001200 +#define    NV34TCL_TX_FORMAT_FORMAT_L8_RECT						0x00001300 +#define    NV34TCL_TX_FORMAT_FORMAT_A8L8						0x00001a00 +#define    NV34TCL_TX_FORMAT_FORMAT_A8_RECT2						0x00001b00 +#define    NV34TCL_TX_FORMAT_FORMAT_A4R4G4B4_RECT					0x00001d00 +#define    NV34TCL_TX_FORMAT_FORMAT_R8G8B8_RECT						0x00001e00 +#define    NV34TCL_TX_FORMAT_FORMAT_L8A8_RECT						0x00002000 +#define    NV34TCL_TX_FORMAT_FORMAT_A16							0x00003200 +#define    NV34TCL_TX_FORMAT_FORMAT_HILO16						0x00003300 +#define    NV34TCL_TX_FORMAT_FORMAT_A16_RECT						0x00003500 +#define    NV34TCL_TX_FORMAT_FORMAT_HILO16_RECT						0x00003600 +#define    NV34TCL_TX_FORMAT_FORMAT_HILO8						0x00004400 +#define    NV34TCL_TX_FORMAT_FORMAT_SIGNED_HILO8					0x00004500 +#define    NV34TCL_TX_FORMAT_FORMAT_HILO8_RECT						0x00004600 +#define    NV34TCL_TX_FORMAT_FORMAT_SIGNED_HILO8_RECT					0x00004700 +#define    NV34TCL_TX_FORMAT_FORMAT_FLOAT_RGBA16_NV					0x00004a00 +#define    NV34TCL_TX_FORMAT_FORMAT_FLOAT_RGBA32_NV					0x00004b00 +#define    NV34TCL_TX_FORMAT_FORMAT_FLOAT_R32_NV					0x00004c00 +#define   NV34TCL_TX_FORMAT_MIPMAP							(1 << 19) +#define   NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT						20 +#define   NV34TCL_TX_FORMAT_BASE_SIZE_U_MASK						0x00f00000 +#define   NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT						24 +#define   NV34TCL_TX_FORMAT_BASE_SIZE_V_MASK						0x0f000000 +#define   NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT						28 +#define   NV34TCL_TX_FORMAT_BASE_SIZE_W_MASK						0xf0000000 +#define  NV34TCL_TX_WRAP(x)								(0x00001a08+((x)*32)) +#define  NV34TCL_TX_WRAP__SIZE								0x00000004 +#define   NV34TCL_TX_WRAP_S_SHIFT							0 +#define   NV34TCL_TX_WRAP_S_MASK							0x000000ff +#define    NV34TCL_TX_WRAP_S_REPEAT							0x00000001 +#define    NV34TCL_TX_WRAP_S_MIRRORED_REPEAT						0x00000002 +#define    NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE						0x00000003 +#define    NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER						0x00000004 +#define    NV34TCL_TX_WRAP_S_CLAMP							0x00000005 +#define   NV34TCL_TX_WRAP_T_SHIFT							8 +#define   NV34TCL_TX_WRAP_T_MASK							0x00000f00 +#define    NV34TCL_TX_WRAP_T_REPEAT							0x00000100 +#define    NV34TCL_TX_WRAP_T_MIRRORED_REPEAT						0x00000200 +#define    NV34TCL_TX_WRAP_T_CLAMP_TO_EDGE						0x00000300 +#define    NV34TCL_TX_WRAP_T_CLAMP_TO_BORDER						0x00000400 +#define    NV34TCL_TX_WRAP_T_CLAMP							0x00000500 +#define   NV34TCL_TX_WRAP_EXPAND_NORMAL_SHIFT						12 +#define   NV34TCL_TX_WRAP_EXPAND_NORMAL_MASK						0x0000f000 +#define   NV34TCL_TX_WRAP_R_SHIFT							16 +#define   NV34TCL_TX_WRAP_R_MASK							0x00ff0000 +#define    NV34TCL_TX_WRAP_R_REPEAT							0x00010000 +#define    NV34TCL_TX_WRAP_R_MIRRORED_REPEAT						0x00020000 +#define    NV34TCL_TX_WRAP_R_CLAMP_TO_EDGE						0x00030000 +#define    NV34TCL_TX_WRAP_R_CLAMP_TO_BORDER						0x00040000 +#define    NV34TCL_TX_WRAP_R_CLAMP							0x00050000 +#define   NV34TCL_TX_WRAP_RCOMP_SHIFT							28 +#define   NV34TCL_TX_WRAP_RCOMP_MASK							0xf0000000 +#define    NV34TCL_TX_WRAP_RCOMP_NEVER							0x00000000 +#define    NV34TCL_TX_WRAP_RCOMP_GREATER						0x10000000 +#define    NV34TCL_TX_WRAP_RCOMP_EQUAL							0x20000000 +#define    NV34TCL_TX_WRAP_RCOMP_GEQUAL							0x30000000 +#define    NV34TCL_TX_WRAP_RCOMP_LESS							0x40000000 +#define    NV34TCL_TX_WRAP_RCOMP_NOTEQUAL						0x50000000 +#define    NV34TCL_TX_WRAP_RCOMP_LEQUAL							0x60000000 +#define    NV34TCL_TX_WRAP_RCOMP_ALWAYS							0x70000000 +#define  NV34TCL_TX_ENABLE(x)								(0x00001a0c+((x)*32)) +#define  NV34TCL_TX_ENABLE__SIZE							0x00000004 +#define   NV34TCL_TX_ENABLE_ANISO_SHIFT							4 +#define   NV34TCL_TX_ENABLE_ANISO_MASK							0x00000030 +#define    NV34TCL_TX_ENABLE_ANISO_NONE							0x00000000 +#define    NV34TCL_TX_ENABLE_ANISO_2X							0x00000010 +#define    NV34TCL_TX_ENABLE_ANISO_4X							0x00000020 +#define    NV34TCL_TX_ENABLE_ANISO_8X							0x00000030 +#define   NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT					14 +#define   NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_MASK						0x0003c000 +#define   NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT					26 +#define   NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_MASK						0x3c000000 +#define   NV34TCL_TX_ENABLE_ENABLE							(1 << 30) +#define  NV34TCL_TX_SWIZZLE(x)								(0x00001a10+((x)*32)) +#define  NV34TCL_TX_SWIZZLE__SIZE							0x00000004 +#define   NV34TCL_TX_SWIZZLE_S0_X_SHIFT							14 +#define   NV34TCL_TX_SWIZZLE_S0_X_MASK							0x0000c000 +#define    NV34TCL_TX_SWIZZLE_S0_X_ZERO							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S0_X_ONE							0x00004000 +#define    NV34TCL_TX_SWIZZLE_S0_X_S1							0x00008000 +#define   NV34TCL_TX_SWIZZLE_S0_Y_SHIFT							12 +#define   NV34TCL_TX_SWIZZLE_S0_Y_MASK							0x00003000 +#define    NV34TCL_TX_SWIZZLE_S0_Y_ZERO							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S0_Y_ONE							0x00001000 +#define    NV34TCL_TX_SWIZZLE_S0_Y_S1							0x00002000 +#define   NV34TCL_TX_SWIZZLE_S0_Z_SHIFT							10 +#define   NV34TCL_TX_SWIZZLE_S0_Z_MASK							0x00000c00 +#define    NV34TCL_TX_SWIZZLE_S0_Z_ZERO							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S0_Z_ONE							0x00000400 +#define    NV34TCL_TX_SWIZZLE_S0_Z_S1							0x00000800 +#define   NV34TCL_TX_SWIZZLE_S0_W_SHIFT							8 +#define   NV34TCL_TX_SWIZZLE_S0_W_MASK							0x00000300 +#define    NV34TCL_TX_SWIZZLE_S0_W_ZERO							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S0_W_ONE							0x00000100 +#define    NV34TCL_TX_SWIZZLE_S0_W_S1							0x00000200 +#define   NV34TCL_TX_SWIZZLE_S1_X_SHIFT							6 +#define   NV34TCL_TX_SWIZZLE_S1_X_MASK							0x000000c0 +#define    NV34TCL_TX_SWIZZLE_S1_X_W							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S1_X_Z							0x00000040 +#define    NV34TCL_TX_SWIZZLE_S1_X_Y							0x00000080 +#define    NV34TCL_TX_SWIZZLE_S1_X_X							0x000000c0 +#define   NV34TCL_TX_SWIZZLE_S1_Y_SHIFT							4 +#define   NV34TCL_TX_SWIZZLE_S1_Y_MASK							0x00000030 +#define    NV34TCL_TX_SWIZZLE_S1_Y_W							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S1_Y_Z							0x00000010 +#define    NV34TCL_TX_SWIZZLE_S1_Y_Y							0x00000020 +#define    NV34TCL_TX_SWIZZLE_S1_Y_X							0x00000030 +#define   NV34TCL_TX_SWIZZLE_S1_Z_SHIFT							2 +#define   NV34TCL_TX_SWIZZLE_S1_Z_MASK							0x0000000c +#define    NV34TCL_TX_SWIZZLE_S1_Z_W							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S1_Z_Z							0x00000004 +#define    NV34TCL_TX_SWIZZLE_S1_Z_Y							0x00000008 +#define    NV34TCL_TX_SWIZZLE_S1_Z_X							0x0000000c +#define   NV34TCL_TX_SWIZZLE_S1_W_SHIFT							0 +#define   NV34TCL_TX_SWIZZLE_S1_W_MASK							0x00000003 +#define    NV34TCL_TX_SWIZZLE_S1_W_W							0x00000000 +#define    NV34TCL_TX_SWIZZLE_S1_W_Z							0x00000001 +#define    NV34TCL_TX_SWIZZLE_S1_W_Y							0x00000002 +#define    NV34TCL_TX_SWIZZLE_S1_W_X							0x00000003 +#define   NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT						16 +#define   NV34TCL_TX_SWIZZLE_RECT_PITCH_MASK						0xffff0000 +#define  NV34TCL_TX_FILTER(x)								(0x00001a14+((x)*32)) +#define  NV34TCL_TX_FILTER__SIZE							0x00000004 +#define   NV34TCL_TX_FILTER_LOD_BIAS_SHIFT						8 +#define   NV34TCL_TX_FILTER_LOD_BIAS_MASK						0x00000f00 +#define   NV34TCL_TX_FILTER_MINIFY_SHIFT						16 +#define   NV34TCL_TX_FILTER_MINIFY_MASK							0x000f0000 +#define    NV34TCL_TX_FILTER_MINIFY_NEAREST						0x00010000 +#define    NV34TCL_TX_FILTER_MINIFY_LINEAR						0x00020000 +#define    NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST				0x00030000 +#define    NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST				0x00040000 +#define    NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR				0x00050000 +#define    NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR				0x00060000 +#define   NV34TCL_TX_FILTER_MAGNIFY_SHIFT						24 +#define   NV34TCL_TX_FILTER_MAGNIFY_MASK						0x0f000000 +#define    NV34TCL_TX_FILTER_MAGNIFY_NEAREST						0x01000000 +#define    NV34TCL_TX_FILTER_MAGNIFY_LINEAR						0x02000000 +#define   NV34TCL_TX_FILTER_SIGNED_BLUE							(1 << 28) +#define   NV34TCL_TX_FILTER_SIGNED_GREEN						(1 << 29) +#define   NV34TCL_TX_FILTER_SIGNED_RED							(1 << 30) +#define   NV34TCL_TX_FILTER_SIGNED_ALPHA						(1 << 31) +#define  NV34TCL_TX_NPOT_SIZE(x)							(0x00001a18+((x)*32)) +#define  NV34TCL_TX_NPOT_SIZE__SIZE							0x00000004 +#define   NV34TCL_TX_NPOT_SIZE_H_SHIFT							0 +#define   NV34TCL_TX_NPOT_SIZE_H_MASK							0x0000ffff +#define   NV34TCL_TX_NPOT_SIZE_W_SHIFT							16 +#define   NV34TCL_TX_NPOT_SIZE_W_MASK							0xffff0000 +#define  NV34TCL_TX_BORDER_COLOR(x)							(0x00001a1c+((x)*32)) +#define  NV34TCL_TX_BORDER_COLOR__SIZE							0x00000004 +#define   NV34TCL_TX_BORDER_COLOR_B_SHIFT						0 +#define   NV34TCL_TX_BORDER_COLOR_B_MASK						0x000000ff +#define   NV34TCL_TX_BORDER_COLOR_G_SHIFT						8 +#define   NV34TCL_TX_BORDER_COLOR_G_MASK						0x0000ff00 +#define   NV34TCL_TX_BORDER_COLOR_R_SHIFT						16 +#define   NV34TCL_TX_BORDER_COLOR_R_MASK						0x00ff0000 +#define   NV34TCL_TX_BORDER_COLOR_A_SHIFT						24 +#define   NV34TCL_TX_BORDER_COLOR_A_MASK						0xff000000 +#define  NV34TCL_VTX_ATTR_4F_X(x)							(0x00001c00+((x)*16)) +#define  NV34TCL_VTX_ATTR_4F_X__SIZE							0x00000010 +#define  NV34TCL_VTX_ATTR_4F_Y(x)							(0x00001c04+((x)*16)) +#define  NV34TCL_VTX_ATTR_4F_Y__SIZE							0x00000010 +#define  NV34TCL_VTX_ATTR_4F_Z(x)							(0x00001c08+((x)*16)) +#define  NV34TCL_VTX_ATTR_4F_Z__SIZE							0x00000010 +#define  NV34TCL_VTX_ATTR_4F_W(x)							(0x00001c0c+((x)*16)) +#define  NV34TCL_VTX_ATTR_4F_W__SIZE							0x00000010 +#define  NV34TCL_FP_CONTROL								0x00001d60 +#define   NV34TCL_FP_CONTROL_USES_KIL							(1 <<  7) +#define   NV34TCL_FP_CONTROL_USED_REGS_MINUS1_DIV2_SHIFT				0 +#define   NV34TCL_FP_CONTROL_USED_REGS_MINUS1_DIV2_MASK					0x0000000f +#define  NV34TCL_MULTISAMPLE_CONTROL							0x00001d7c +#define   NV34TCL_MULTISAMPLE_CONTROL_ENABLE						(1 <<  0) +#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_ALPHA_TO_COVERAGE				(1 <<  4) +#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_ALPHA_TO_ONE				(1 <<  8) +#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_COVERAGE_SHIFT				16 +#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_COVERAGE_MASK				0xffff0000 +#define  NV34TCL_CLEAR_DEPTH_VALUE							0x00001d8c +#define  NV34TCL_CLEAR_COLOR_VALUE							0x00001d90 +#define   NV34TCL_CLEAR_COLOR_VALUE_B_SHIFT						0 +#define   NV34TCL_CLEAR_COLOR_VALUE_B_MASK						0x000000ff +#define   NV34TCL_CLEAR_COLOR_VALUE_G_SHIFT						8 +#define   NV34TCL_CLEAR_COLOR_VALUE_G_MASK						0x0000ff00 +#define   NV34TCL_CLEAR_COLOR_VALUE_R_SHIFT						16 +#define   NV34TCL_CLEAR_COLOR_VALUE_R_MASK						0x00ff0000 +#define   NV34TCL_CLEAR_COLOR_VALUE_A_SHIFT						24 +#define   NV34TCL_CLEAR_COLOR_VALUE_A_MASK						0xff000000 +#define  NV34TCL_CLEAR_BUFFERS								0x00001d94 +#define   NV34TCL_CLEAR_BUFFERS_COLOR_A							(1 <<  7) +#define   NV34TCL_CLEAR_BUFFERS_COLOR_B							(1 <<  6) +#define   NV34TCL_CLEAR_BUFFERS_COLOR_G							(1 <<  5) +#define   NV34TCL_CLEAR_BUFFERS_COLOR_R							(1 <<  4) +#define   NV34TCL_CLEAR_BUFFERS_STENCIL							(1 <<  1) +#define   NV34TCL_CLEAR_BUFFERS_DEPTH							(1 <<  0) +#define  NV34TCL_DO_VERTICES								0x00001dac +#define  NV34TCL_LINE_STIPPLE_ENABLE							0x00001db4 +#define  NV34TCL_LINE_STIPPLE_PATTERN							0x00001db8 +#define   NV34TCL_LINE_STIPPLE_PATTERN_FACTOR_SHIFT					0 +#define   NV34TCL_LINE_STIPPLE_PATTERN_FACTOR_MASK					0x0000ffff +#define   NV34TCL_LINE_STIPPLE_PATTERN_PATTERN_SHIFT					16 +#define   NV34TCL_LINE_STIPPLE_PATTERN_PATTERN_MASK					0xffff0000 +#define  NV34TCL_BACK_MATERIAL_SHININESS(x)						(0x00001e20+((x)*4)) +#define  NV34TCL_BACK_MATERIAL_SHININESS__SIZE						0x00000006 +#define  NV34TCL_VTX_ATTR_1F(x)								(0x00001e40+((x)*4)) +#define  NV34TCL_VTX_ATTR_1F__SIZE							0x00000010 +#define  NV34TCL_VP_UPLOAD_FROM_ID							0x00001e9c +#define  NV34TCL_VP_START_FROM_ID							0x00001ea0 +#define  NV34TCL_POINT_PARAMETERS(x)							(0x00001ec0+((x)*4)) +#define  NV34TCL_POINT_PARAMETERS__SIZE							0x00000008 +#define  NV34TCL_POINT_SIZE								0x00001ee0 +#define  NV34TCL_POINT_PARAMETERS_ENABLE						0x00001ee4 +#define  NV34TCL_POINT_SPRITE								0x00001ee8 +#define   NV34TCL_POINT_SPRITE_ENABLE							(1 <<  0) +#define   NV34TCL_POINT_SPRITE_R_MODE_SHIFT						1 +#define   NV34TCL_POINT_SPRITE_R_MODE_MASK						0x00000006 +#define    NV34TCL_POINT_SPRITE_R_MODE_GL_ZERO						0x00000000 +#define    NV34TCL_POINT_SPRITE_R_MODE_GL_R						0x00000002 +#define    NV34TCL_POINT_SPRITE_R_MODE_GL_S						0x00000004 +#define   NV34TCL_POINT_SPRITE_COORD_REPLACE						(1 << 11) +#define  NV34TCL_VP_UPLOAD_CONST_ID							0x00001efc +#define  NV34TCL_VP_UPLOAD_CONST_X(x)							(0x00001f00+((x)*16)) +#define  NV34TCL_VP_UPLOAD_CONST_X__SIZE						0x00000004 +#define  NV34TCL_VP_UPLOAD_CONST_Y(x)							(0x00001f04+((x)*16)) +#define  NV34TCL_VP_UPLOAD_CONST_Y__SIZE						0x00000004 +#define  NV34TCL_VP_UPLOAD_CONST_Z(x)							(0x00001f08+((x)*16)) +#define  NV34TCL_VP_UPLOAD_CONST_Z__SIZE						0x00000004 +#define  NV34TCL_VP_UPLOAD_CONST_W(x)							(0x00001f0c+((x)*16)) +#define  NV34TCL_VP_UPLOAD_CONST_W__SIZE						0x00000004 +#define  NV34TCL_UNK1f80(x)								(0x00001f80+((x)*4)) +#define  NV34TCL_UNK1f80__SIZE								0x00000010 + + +#define NV40_CONTEXT_SURFACES_2D							0x00003062 + + + +#define NV40_STRETCHED_IMAGE_FROM_CPU							0x00003066 + + + +#define NV40_TEXTURE_FROM_CPU								0x0000307b + + + +#define NV40_SCALED_IMAGE_FROM_MEMORY							0x00003089 + + + +#define NV40_IMAGE_FROM_CPU								0x0000308a + + + +#define NV40_SWIZZLED_SURFACE								0x0000309e + + + +#define NV40TCL										0x00004097 + +#define  NV40TCL_REF_CNT								0x00000050 +#define  NV40TCL_NOP									0x00000100 +#define  NV40TCL_NOTIFY									0x00000104 +#define  NV40TCL_DMA_NOTIFY								0x00000180 +#define  NV40TCL_DMA_TEXTURE0								0x00000184 +#define  NV40TCL_DMA_TEXTURE1								0x00000188 +#define  NV40TCL_DMA_COLOR1								0x0000018c +#define  NV40TCL_DMA_COLOR0								0x00000194 +#define  NV40TCL_DMA_ZETA								0x00000198 +#define  NV40TCL_DMA_VTXBUF0								0x0000019c +#define  NV40TCL_DMA_VTXBUF1								0x000001a0 +#define  NV40TCL_DMA_FENCE								0x000001a4 +#define  NV40TCL_DMA_QUERY								0x000001a8 +#define  NV40TCL_DMA_UNK01AC								0x000001ac +#define  NV40TCL_DMA_UNK01B0								0x000001b0 +#define  NV40TCL_DMA_COLOR2								0x000001b4 +#define  NV40TCL_DMA_COLOR3								0x000001b8 +#define  NV40TCL_RT_HORIZ								0x00000200 +#define   NV40TCL_RT_HORIZ_W_SHIFT							16 +#define   NV40TCL_RT_HORIZ_W_MASK							0xffff0000 +#define   NV40TCL_RT_HORIZ_X_SHIFT							0 +#define   NV40TCL_RT_HORIZ_X_MASK							0x0000ffff +#define  NV40TCL_RT_VERT								0x00000204 +#define   NV40TCL_RT_VERT_H_SHIFT							16 +#define   NV40TCL_RT_VERT_H_MASK							0xffff0000 +#define   NV40TCL_RT_VERT_Y_SHIFT							0 +#define   NV40TCL_RT_VERT_Y_MASK							0x0000ffff +#define  NV40TCL_RT_FORMAT								0x00000208 +#define   NV40TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT						24 +#define   NV40TCL_RT_FORMAT_LOG2_HEIGHT_MASK						0xff000000 +#define   NV40TCL_RT_FORMAT_LOG2_WIDTH_SHIFT						16 +#define   NV40TCL_RT_FORMAT_LOG2_WIDTH_MASK						0x00ff0000 +#define   NV40TCL_RT_FORMAT_TYPE_SHIFT							8 +#define   NV40TCL_RT_FORMAT_TYPE_MASK							0x00000f00 +#define    NV40TCL_RT_FORMAT_TYPE_LINEAR						0x00000100 +#define    NV40TCL_RT_FORMAT_TYPE_SWIZZLED						0x00000200 +#define   NV40TCL_RT_FORMAT_ZETA_SHIFT							5 +#define   NV40TCL_RT_FORMAT_ZETA_MASK							0x000000e0 +#define    NV40TCL_RT_FORMAT_ZETA_Z16							0x00000020 +#define    NV40TCL_RT_FORMAT_ZETA_Z24S8							0x00000040 +#define   NV40TCL_RT_FORMAT_COLOR_SHIFT							0 +#define   NV40TCL_RT_FORMAT_COLOR_MASK							0x0000001f +#define    NV40TCL_RT_FORMAT_COLOR_R5G6B5						0x00000003 +#define    NV40TCL_RT_FORMAT_COLOR_X8R8G8B8						0x00000005 +#define    NV40TCL_RT_FORMAT_COLOR_A8R8G8B8						0x00000008 +#define    NV40TCL_RT_FORMAT_COLOR_B8							0x00000009 +#define    NV40TCL_RT_FORMAT_COLOR_X8B8G8R8						0x0000000f +#define    NV40TCL_RT_FORMAT_COLOR_A8B8G8R8						0x00000010 +#define  NV40TCL_COLOR0_PITCH								0x0000020c +#define  NV40TCL_COLOR0_OFFSET								0x00000210 +#define  NV40TCL_ZETA_OFFSET								0x00000214 +#define  NV40TCL_COLOR1_OFFSET								0x00000218 +#define  NV40TCL_COLOR1_PITCH								0x0000021c +#define  NV40TCL_RT_ENABLE								0x00000220 +#define   NV40TCL_RT_ENABLE_MRT								(1 <<  4) +#define   NV40TCL_RT_ENABLE_COLOR3							(1 <<  3) +#define   NV40TCL_RT_ENABLE_COLOR2							(1 <<  2) +#define   NV40TCL_RT_ENABLE_COLOR1							(1 <<  1) +#define   NV40TCL_RT_ENABLE_COLOR0							(1 <<  0) +#define  NV40TCL_ZETA_PITCH								0x0000022c +#define  NV40TCL_COLOR2_PITCH								0x00000280 +#define  NV40TCL_COLOR3_PITCH								0x00000284 +#define  NV40TCL_COLOR2_OFFSET								0x00000288 +#define  NV40TCL_COLOR3_OFFSET								0x0000028c +#define  NV40TCL_VIEWPORT_CLIP_HORIZ(x)							(0x000002c0+((x)*8)) +#define  NV40TCL_VIEWPORT_CLIP_HORIZ__SIZE						0x00000008 +#define  NV40TCL_VIEWPORT_CLIP_VERT(x)							(0x000002c4+((x)*8)) +#define  NV40TCL_VIEWPORT_CLIP_VERT__SIZE						0x00000008 +#define  NV40TCL_DITHER_ENABLE								0x00000300 +#define  NV40TCL_ALPHA_TEST_ENABLE							0x00000304 +#define  NV40TCL_ALPHA_TEST_FUNC							0x00000308 +#define   NV40TCL_ALPHA_TEST_FUNC_NEVER							0x00000200 +#define   NV40TCL_ALPHA_TEST_FUNC_LESS							0x00000201 +#define   NV40TCL_ALPHA_TEST_FUNC_EQUAL							0x00000202 +#define   NV40TCL_ALPHA_TEST_FUNC_LEQUAL						0x00000203 +#define   NV40TCL_ALPHA_TEST_FUNC_GREATER						0x00000204 +#define   NV40TCL_ALPHA_TEST_FUNC_GREATER						0x00000204 +#define   NV40TCL_ALPHA_TEST_FUNC_NOTEQUAL						0x00000205 +#define   NV40TCL_ALPHA_TEST_FUNC_GEQUAL						0x00000206 +#define   NV40TCL_ALPHA_TEST_FUNC_ALWAYS						0x00000207 +#define  NV40TCL_ALPHA_TEST_REF								0x0000030c +#define  NV40TCL_BLEND_ENABLE								0x00000310 +#define  NV40TCL_BLEND_FUNC_SRC								0x00000314 +#define   NV40TCL_BLEND_FUNC_SRC_RGB_SHIFT						0 +#define   NV40TCL_BLEND_FUNC_SRC_RGB_MASK						0x0000ffff +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ZERO						0x00000000 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE						0x00000001 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_SRC_COLOR						0x00000300 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR				0x00000301 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA						0x00000302 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA				0x00000303 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_DST_ALPHA						0x00000304 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA				0x00000305 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_DST_COLOR						0x00000306 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR				0x00000307 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE				0x00000308 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR					0x00008001 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA					0x00008003 +#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define   NV40TCL_BLEND_FUNC_SRC_ALPHA_SHIFT						16 +#define   NV40TCL_BLEND_FUNC_SRC_ALPHA_MASK						0xffff0000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ZERO						0x00000000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE						0x00010000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_SRC_COLOR					0x03000000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_COLOR				0x03010000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA					0x03020000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_ALPHA				0x03030000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_DST_ALPHA					0x03040000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_ALPHA				0x03050000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_DST_COLOR					0x03060000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_COLOR				0x03070000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA_SATURATE				0x03080000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_COLOR					0x80010000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_COLOR			0x80020000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_ALPHA					0x80030000 +#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_ALPHA			0x80040000 +#define  NV40TCL_BLEND_FUNC_DST								0x00000318 +#define   NV40TCL_BLEND_FUNC_DST_RGB_SHIFT						0 +#define   NV40TCL_BLEND_FUNC_DST_RGB_MASK						0x0000ffff +#define    NV40TCL_BLEND_FUNC_DST_RGB_ZERO						0x00000000 +#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE						0x00000001 +#define    NV40TCL_BLEND_FUNC_DST_RGB_SRC_COLOR						0x00000300 +#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_COLOR				0x00000301 +#define    NV40TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA						0x00000302 +#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_ALPHA				0x00000303 +#define    NV40TCL_BLEND_FUNC_DST_RGB_DST_ALPHA						0x00000304 +#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_ALPHA				0x00000305 +#define    NV40TCL_BLEND_FUNC_DST_RGB_DST_COLOR						0x00000306 +#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_COLOR				0x00000307 +#define    NV40TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA_SATURATE				0x00000308 +#define    NV40TCL_BLEND_FUNC_DST_RGB_CONSTANT_COLOR					0x00008001 +#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define    NV40TCL_BLEND_FUNC_DST_RGB_CONSTANT_ALPHA					0x00008003 +#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define   NV40TCL_BLEND_FUNC_DST_ALPHA_SHIFT						16 +#define   NV40TCL_BLEND_FUNC_DST_ALPHA_MASK						0xffff0000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ZERO						0x00000000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE						0x00010000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_SRC_COLOR					0x03000000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_COLOR				0x03010000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA					0x03020000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_ALPHA				0x03030000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_DST_ALPHA					0x03040000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_ALPHA				0x03050000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_DST_COLOR					0x03060000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_COLOR				0x03070000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA_SATURATE				0x03080000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_COLOR					0x80010000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_COLOR			0x80020000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_ALPHA					0x80030000 +#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_ALPHA			0x80040000 +#define  NV40TCL_BLEND_COLOR								0x0000031c +#define  NV40TCL_BLEND_EQUATION								0x00000320 +#define   NV40TCL_BLEND_EQUATION_RGB_SHIFT						0 +#define   NV40TCL_BLEND_EQUATION_RGB_MASK						0x0000ffff +#define    NV40TCL_BLEND_EQUATION_RGB_FUNC_ADD						0x00008006 +#define    NV40TCL_BLEND_EQUATION_RGB_MIN						0x00008007 +#define    NV40TCL_BLEND_EQUATION_RGB_MAX						0x00008008 +#define    NV40TCL_BLEND_EQUATION_RGB_FUNC_SUBTRACT					0x0000800a +#define    NV40TCL_BLEND_EQUATION_RGB_FUNC_REVERSE_SUBTRACT				0x0000800b +#define   NV40TCL_BLEND_EQUATION_ALPHA_SHIFT						16 +#define   NV40TCL_BLEND_EQUATION_ALPHA_MASK						0xffff0000 +#define    NV40TCL_BLEND_EQUATION_ALPHA_FUNC_ADD					0x80060000 +#define    NV40TCL_BLEND_EQUATION_ALPHA_MIN						0x80070000 +#define    NV40TCL_BLEND_EQUATION_ALPHA_MAX						0x80080000 +#define    NV40TCL_BLEND_EQUATION_ALPHA_FUNC_SUBTRACT					0x800a0000 +#define    NV40TCL_BLEND_EQUATION_ALPHA_FUNC_REVERSE_SUBTRACT				0x800b0000 +#define  NV40TCL_COLOR_MASK								0x00000324 +#define   NV40TCL_COLOR_MASK_BUFFER0_B_SHIFT						0 +#define   NV40TCL_COLOR_MASK_BUFFER0_B_MASK						0x000000ff +#define   NV40TCL_COLOR_MASK_BUFFER0_G_SHIFT						8 +#define   NV40TCL_COLOR_MASK_BUFFER0_G_MASK						0x0000ff00 +#define   NV40TCL_COLOR_MASK_BUFFER0_R_SHIFT						16 +#define   NV40TCL_COLOR_MASK_BUFFER0_R_MASK						0x00ff0000 +#define   NV40TCL_COLOR_MASK_BUFFER0_A_SHIFT						24 +#define   NV40TCL_COLOR_MASK_BUFFER0_A_MASK						0xff000000 +#define  NV40TCL_STENCIL_FRONT_ENABLE							0x00000328 +#define  NV40TCL_STENCIL_FRONT_MASK							0x0000032c +#define  NV40TCL_STENCIL_FRONT_FUNC_FUNC						0x00000330 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_NEVER						0x00000200 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_LESS						0x00000201 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_EQUAL						0x00000202 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_LEQUAL					0x00000203 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_GREATER					0x00000204 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_GREATER					0x00000204 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_NOTEQUAL					0x00000205 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_GEQUAL					0x00000206 +#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_ALWAYS					0x00000207 +#define  NV40TCL_STENCIL_FRONT_FUNC_REF							0x00000334 +#define  NV40TCL_STENCIL_FRONT_FUNC_MASK						0x00000338 +#define  NV40TCL_STENCIL_FRONT_OP_FAIL							0x0000033c +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_ZERO						0x00000000 +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_INVERT						0x0000150a +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_KEEP						0x00001e00 +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_REPLACE						0x00001e01 +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_INCR						0x00001e02 +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_DECR						0x00001e03 +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_INCR_WRAP					0x00008507 +#define   NV40TCL_STENCIL_FRONT_OP_FAIL_DECR_WRAP					0x00008508 +#define  NV40TCL_STENCIL_FRONT_OP_ZFAIL							0x00000340 +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_ZERO						0x00000000 +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_INVERT						0x0000150a +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_KEEP						0x00001e00 +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_REPLACE					0x00001e01 +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_INCR						0x00001e02 +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_DECR						0x00001e03 +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_INCR_WRAP					0x00008507 +#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_DECR_WRAP					0x00008508 +#define  NV40TCL_STENCIL_FRONT_OP_ZPASS							0x00000344 +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_ZERO						0x00000000 +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_INVERT						0x0000150a +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_KEEP						0x00001e00 +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_REPLACE					0x00001e01 +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_INCR						0x00001e02 +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_DECR						0x00001e03 +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_INCR_WRAP					0x00008507 +#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_DECR_WRAP					0x00008508 +#define  NV40TCL_STENCIL_BACK_ENABLE							0x00000348 +#define  NV40TCL_STENCIL_BACK_MASK							0x0000034c +#define  NV40TCL_STENCIL_BACK_FUNC_FUNC							0x00000350 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_NEVER						0x00000200 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_LESS						0x00000201 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_EQUAL						0x00000202 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_GREATER					0x00000204 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_GREATER					0x00000204 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_NOTEQUAL					0x00000205 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV40TCL_STENCIL_BACK_FUNC_REF							0x00000354 +#define  NV40TCL_STENCIL_BACK_FUNC_MASK							0x00000358 +#define  NV40TCL_STENCIL_BACK_OP_FAIL							0x0000035c +#define   NV40TCL_STENCIL_BACK_OP_FAIL_ZERO						0x00000000 +#define   NV40TCL_STENCIL_BACK_OP_FAIL_INVERT						0x0000150a +#define   NV40TCL_STENCIL_BACK_OP_FAIL_KEEP						0x00001e00 +#define   NV40TCL_STENCIL_BACK_OP_FAIL_REPLACE						0x00001e01 +#define   NV40TCL_STENCIL_BACK_OP_FAIL_INCR						0x00001e02 +#define   NV40TCL_STENCIL_BACK_OP_FAIL_DECR						0x00001e03 +#define   NV40TCL_STENCIL_BACK_OP_FAIL_INCR_WRAP					0x00008507 +#define   NV40TCL_STENCIL_BACK_OP_FAIL_DECR_WRAP					0x00008508 +#define  NV40TCL_STENCIL_BACK_OP_ZFAIL							0x00000360 +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_ZERO						0x00000000 +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_INVERT						0x0000150a +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_KEEP						0x00001e00 +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_REPLACE						0x00001e01 +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_INCR						0x00001e02 +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_DECR						0x00001e03 +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_INCR_WRAP					0x00008507 +#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_DECR_WRAP					0x00008508 +#define  NV40TCL_STENCIL_BACK_OP_ZPASS							0x00000364 +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_ZERO						0x00000000 +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_INVERT						0x0000150a +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_KEEP						0x00001e00 +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_REPLACE						0x00001e01 +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_INCR						0x00001e02 +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_DECR						0x00001e03 +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_INCR_WRAP					0x00008507 +#define   NV40TCL_STENCIL_BACK_OP_ZPASS_DECR_WRAP					0x00008508 +#define  NV40TCL_SHADE_MODEL								0x00000368 +#define   NV40TCL_SHADE_MODEL_FLAT							0x00001d00 +#define   NV40TCL_SHADE_MODEL_SMOOTH							0x00001d01 +#define  NV40TCL_MRT_COLOR_MASK								0x00000370 +#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_A						(1 <<  4) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_R						(1 <<  5) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_G						(1 <<  6) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_B						(1 <<  7) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_A						(1 <<  8) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_R						(1 <<  9) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_G						(1 << 10) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_B						(1 << 11) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_A						(1 << 12) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_R						(1 << 13) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_G						(1 << 14) +#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_B						(1 << 15) +#define  NV40TCL_COLOR_LOGIC_OP_ENABLE							0x00000374 +#define  NV40TCL_COLOR_LOGIC_OP								0x00000378 +#define   NV40TCL_COLOR_LOGIC_OP_CLEAR							0x00001500 +#define   NV40TCL_COLOR_LOGIC_OP_AND							0x00001501 +#define   NV40TCL_COLOR_LOGIC_OP_AND_REVERSE						0x00001502 +#define   NV40TCL_COLOR_LOGIC_OP_COPY							0x00001503 +#define   NV40TCL_COLOR_LOGIC_OP_AND_INVERTED						0x00001504 +#define   NV40TCL_COLOR_LOGIC_OP_NOOP							0x00001505 +#define   NV40TCL_COLOR_LOGIC_OP_XOR							0x00001506 +#define   NV40TCL_COLOR_LOGIC_OP_OR							0x00001507 +#define   NV40TCL_COLOR_LOGIC_OP_NOR							0x00001508 +#define   NV40TCL_COLOR_LOGIC_OP_EQUIV							0x00001509 +#define   NV40TCL_COLOR_LOGIC_OP_INVERT							0x0000150a +#define   NV40TCL_COLOR_LOGIC_OP_OR_REVERSE						0x0000150b +#define   NV40TCL_COLOR_LOGIC_OP_COPY_INVERTED						0x0000150c +#define   NV40TCL_COLOR_LOGIC_OP_OR_INVERTED						0x0000150d +#define   NV40TCL_COLOR_LOGIC_OP_NAND							0x0000150e +#define   NV40TCL_COLOR_LOGIC_OP_SET							0x0000150f +#define  NV40TCL_DEPTH_RANGE_NEAR							0x00000394 +#define  NV40TCL_DEPTH_RANGE_FAR							0x00000398 +#define  NV40TCL_LINE_WIDTH								0x000003b8 +#define  NV40TCL_LINE_SMOOTH_ENABLE							0x000003bc +#define  NV40TCL_UNK03C0(x)								(0x000003c0+((x)*4)) +#define  NV40TCL_UNK03C0__SIZE								0x00000010 +#define  NV40TCL_UNK0400(x)								(0x00000400+((x)*4)) +#define  NV40TCL_UNK0400__SIZE								0x00000010 +#define  NV40TCL_UNK0440(x)								(0x00000440+((x)*4)) +#define  NV40TCL_UNK0440__SIZE								0x00000020 +#define  NV40TCL_SCISSOR_HORIZ								0x000008c0 +#define   NV40TCL_SCISSOR_HORIZ_X_SHIFT							0 +#define   NV40TCL_SCISSOR_HORIZ_X_MASK							0x0000ffff +#define   NV40TCL_SCISSOR_HORIZ_W_SHIFT							16 +#define   NV40TCL_SCISSOR_HORIZ_W_MASK							0xffff0000 +#define  NV40TCL_SCISSOR_VERT								0x000008c4 +#define   NV40TCL_SCISSOR_VERT_Y_SHIFT							0 +#define   NV40TCL_SCISSOR_VERT_Y_MASK							0x0000ffff +#define   NV40TCL_SCISSOR_VERT_H_SHIFT							16 +#define   NV40TCL_SCISSOR_VERT_H_MASK							0xffff0000 +#define  NV40TCL_FOG_MODE								0x000008cc +#define  NV40TCL_FOG_EQUATION_CONSTANT							0x000008d0 +#define  NV40TCL_FOG_EQUATION_LINEAR							0x000008d4 +#define  NV40TCL_FOG_EQUATION_QUADRATIC							0x000008d8 +#define  NV40TCL_FP_ADDRESS								0x000008e4 +#define   NV40TCL_FP_ADDRESS_OFFSET_SHIFT						8 +#define   NV40TCL_FP_ADDRESS_OFFSET_MASK						0xffffff00 +#define   NV40TCL_FP_ADDRESS_DMA1							(1 <<  1) +#define   NV40TCL_FP_ADDRESS_DMA0							(1 <<  0) +#define  NV40TCL_VIEWPORT_HORIZ								0x00000a00 +#define   NV40TCL_VIEWPORT_HORIZ_W_SHIFT						16 +#define   NV40TCL_VIEWPORT_HORIZ_W_MASK							0xffff0000 +#define   NV40TCL_VIEWPORT_HORIZ_X_SHIFT						0 +#define   NV40TCL_VIEWPORT_HORIZ_X_MASK							0x0000ffff +#define  NV40TCL_VIEWPORT_VERT								0x00000a04 +#define   NV40TCL_VIEWPORT_VERT_H_SHIFT							16 +#define   NV40TCL_VIEWPORT_VERT_H_MASK							0xffff0000 +#define   NV40TCL_VIEWPORT_VERT_Y_SHIFT							0 +#define   NV40TCL_VIEWPORT_VERT_Y_MASK							0x0000ffff +#define  NV40TCL_VIEWPORT_TRANSLATE_X							0x00000a20 +#define  NV40TCL_VIEWPORT_TRANSLATE_Y							0x00000a24 +#define  NV40TCL_VIEWPORT_TRANSLATE_Z							0x00000a28 +#define  NV40TCL_VIEWPORT_TRANSLATE_W							0x00000a2c +#define  NV40TCL_VIEWPORT_SCALE_X							0x00000a30 +#define  NV40TCL_VIEWPORT_SCALE_Y							0x00000a34 +#define  NV40TCL_VIEWPORT_SCALE_Z							0x00000a38 +#define  NV40TCL_VIEWPORT_SCALE_W							0x00000a3c +#define  NV40TCL_POLYGON_OFFSET_POINT_ENABLE						0x00000a60 +#define  NV40TCL_POLYGON_OFFSET_LINE_ENABLE						0x00000a64 +#define  NV40TCL_POLYGON_OFFSET_FILL_ENABLE						0x00000a68 +#define  NV40TCL_DEPTH_FUNC								0x00000a6c +#define   NV40TCL_DEPTH_FUNC_NEVER							0x00000200 +#define   NV40TCL_DEPTH_FUNC_LESS							0x00000201 +#define   NV40TCL_DEPTH_FUNC_EQUAL							0x00000202 +#define   NV40TCL_DEPTH_FUNC_LEQUAL							0x00000203 +#define   NV40TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV40TCL_DEPTH_FUNC_GREATER							0x00000204 +#define   NV40TCL_DEPTH_FUNC_NOTEQUAL							0x00000205 +#define   NV40TCL_DEPTH_FUNC_GEQUAL							0x00000206 +#define   NV40TCL_DEPTH_FUNC_ALWAYS							0x00000207 +#define  NV40TCL_DEPTH_WRITE_ENABLE							0x00000a70 +#define  NV40TCL_DEPTH_TEST_ENABLE							0x00000a74 +#define  NV40TCL_POLYGON_OFFSET_FACTOR							0x00000a78 +#define  NV40TCL_POLYGON_OFFSET_UNITS							0x00000a7c +#define  NV40TCL_VTX_ATTR_3I_XY(x)							(0x00000a80+((x)*8)) +#define  NV40TCL_VTX_ATTR_3I_XY__SIZE							0x00000010 +#define   NV40TCL_VTX_ATTR_3I_XY_X_SHIFT						0 +#define   NV40TCL_VTX_ATTR_3I_XY_X_MASK							0x0000ffff +#define   NV40TCL_VTX_ATTR_3I_XY_Y_SHIFT						16 +#define   NV40TCL_VTX_ATTR_3I_XY_Y_MASK							0xffff0000 +#define  NV40TCL_VTX_ATTR_3I_Z(x)							(0x00000a84+((x)*8)) +#define  NV40TCL_VTX_ATTR_3I_Z__SIZE							0x00000010 +#define   NV40TCL_VTX_ATTR_3I_Z_Z_SHIFT							0 +#define   NV40TCL_VTX_ATTR_3I_Z_Z_MASK							0x0000ffff +#define  NV40TCL_UNK0B40(x)								(0x00000b40+((x)*4)) +#define  NV40TCL_UNK0B40__SIZE								0x00000008 +#define  NV40TCL_VP_UPLOAD_INST(x)							(0x00000b80+((x)*4)) +#define  NV40TCL_VP_UPLOAD_INST__SIZE							0x00000004 +#define  NV40TCL_CLIP_PLANE_ENABLE							0x00001478 +#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE0						(1 <<  1) +#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE1						(1 <<  5) +#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE2						(1 <<  9) +#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE3						(1 << 13) +#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE4						(1 << 17) +#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE5						(1 << 21) +#define  NV40TCL_POLYGON_STIPPLE_ENABLE							0x0000147c +#define  NV40TCL_POLYGON_STIPPLE_PATTERN(x)						(0x00001480+((x)*4)) +#define  NV40TCL_POLYGON_STIPPLE_PATTERN__SIZE						0x00000020 +#define  NV40TCL_VTX_ATTR_3F_X(x)							(0x00001500+((x)*16)) +#define  NV40TCL_VTX_ATTR_3F_X__SIZE							0x00000010 +#define  NV40TCL_VTX_ATTR_3F_Y(x)							(0x00001504+((x)*16)) +#define  NV40TCL_VTX_ATTR_3F_Y__SIZE							0x00000010 +#define  NV40TCL_VTX_ATTR_3F_Z(x)							(0x00001508+((x)*16)) +#define  NV40TCL_VTX_ATTR_3F_Z__SIZE							0x00000010 +#define  NV40TCL_VTXBUF_ADDRESS(x)							(0x00001680+((x)*4)) +#define  NV40TCL_VTXBUF_ADDRESS__SIZE							0x00000010 +#define   NV40TCL_VTXBUF_ADDRESS_DMA1							(1 << 31) +#define   NV40TCL_VTXBUF_ADDRESS_OFFSET_SHIFT						0 +#define   NV40TCL_VTXBUF_ADDRESS_OFFSET_MASK						0x0fffffff +#define  NV40TCL_VTX_CACHE_INVALIDATE							0x00001714 +#define  NV40TCL_VTXFMT(x)								(0x00001740+((x)*4)) +#define  NV40TCL_VTXFMT__SIZE								0x00000010 +#define   NV40TCL_VTXFMT_TYPE_SHIFT							0 +#define   NV40TCL_VTXFMT_TYPE_MASK							0x0000000f +#define    NV40TCL_VTXFMT_TYPE_FLOAT							0x00000002 +#define    NV40TCL_VTXFMT_TYPE_UBYTE							0x00000004 +#define    NV40TCL_VTXFMT_TYPE_USHORT							0x00000005 +#define   NV40TCL_VTXFMT_SIZE_SHIFT							4 +#define   NV40TCL_VTXFMT_SIZE_MASK							0x000000f0 +#define   NV40TCL_VTXFMT_STRIDE_SHIFT							8 +#define   NV40TCL_VTXFMT_STRIDE_MASK							0x0000ff00 +#define  NV40TCL_QUERY_RESET								0x000017c8 +#define  NV40TCL_QUERY_UNK17CC								0x000017cc +#define  NV40TCL_QUERY_GET								0x00001800 +#define   NV40TCL_QUERY_GET_UNK24_SHIFT							24 +#define   NV40TCL_QUERY_GET_UNK24_MASK							0xff000000 +#define   NV40TCL_QUERY_GET_OFFSET_SHIFT						0 +#define   NV40TCL_QUERY_GET_OFFSET_MASK							0x00ffffff +#define  NV40TCL_BEGIN_END								0x00001808 +#define   NV40TCL_BEGIN_END_STOP							0x00000000 +#define   NV40TCL_BEGIN_END_POINTS							0x00000001 +#define   NV40TCL_BEGIN_END_LINES							0x00000002 +#define   NV40TCL_BEGIN_END_LINE_LOOP							0x00000003 +#define   NV40TCL_BEGIN_END_LINE_STRIP							0x00000004 +#define   NV40TCL_BEGIN_END_TRIANGLES							0x00000005 +#define   NV40TCL_BEGIN_END_TRIANGLE_STRIP						0x00000006 +#define   NV40TCL_BEGIN_END_TRIANGLE_FAN						0x00000007 +#define   NV40TCL_BEGIN_END_QUADS							0x00000008 +#define   NV40TCL_BEGIN_END_QUAD_STRIP							0x00000009 +#define   NV40TCL_BEGIN_END_POLYGON							0x0000000a +#define  NV40TCL_VB_ELEMENT_U16								0x0000180c +#define   NV40TCL_VB_ELEMENT_U16_1_SHIFT						16 +#define   NV40TCL_VB_ELEMENT_U16_1_MASK							0xffff0000 +#define   NV40TCL_VB_ELEMENT_U16_0_SHIFT						0 +#define   NV40TCL_VB_ELEMENT_U16_0_MASK							0x0000ffff +#define  NV40TCL_VB_ELEMENT_U32								0x00001810 +#define  NV40TCL_VB_VERTEX_BATCH							0x00001814 +#define   NV40TCL_VB_VERTEX_BATCH_COUNT_SHIFT						24 +#define   NV40TCL_VB_VERTEX_BATCH_COUNT_MASK						0xff000000 +#define   NV40TCL_VB_VERTEX_BATCH_START_SHIFT						0 +#define   NV40TCL_VB_VERTEX_BATCH_START_MASK						0x00ffffff +#define  NV40TCL_VERTEX_DATA								0x00001818 +#define  NV40TCL_IDXBUF_ADDRESS								0x0000181c +#define  NV40TCL_IDXBUF_FORMAT								0x00001820 +#define   NV40TCL_IDXBUF_FORMAT_TYPE_SHIFT						4 +#define   NV40TCL_IDXBUF_FORMAT_TYPE_MASK						0x000000f0 +#define    NV40TCL_IDXBUF_FORMAT_TYPE_U32						0x00000000 +#define    NV40TCL_IDXBUF_FORMAT_TYPE_U16						0x00000010 +#define   NV40TCL_IDXBUF_FORMAT_DMA1							(1 <<  0) +#define  NV40TCL_VB_INDEX_BATCH								0x00001824 +#define   NV40TCL_VB_INDEX_BATCH_COUNT_SHIFT						24 +#define   NV40TCL_VB_INDEX_BATCH_COUNT_MASK						0xff000000 +#define   NV40TCL_VB_INDEX_BATCH_START_SHIFT						0 +#define   NV40TCL_VB_INDEX_BATCH_START_MASK						0x00ffffff +#define  NV40TCL_POLYGON_MODE_FRONT							0x00001828 +#define   NV40TCL_POLYGON_MODE_FRONT_POINT						0x00001b00 +#define   NV40TCL_POLYGON_MODE_FRONT_LINE						0x00001b01 +#define   NV40TCL_POLYGON_MODE_FRONT_FILL						0x00001b02 +#define  NV40TCL_POLYGON_MODE_BACK							0x0000182c +#define   NV40TCL_POLYGON_MODE_BACK_POINT						0x00001b00 +#define   NV40TCL_POLYGON_MODE_BACK_LINE						0x00001b01 +#define   NV40TCL_POLYGON_MODE_BACK_FILL						0x00001b02 +#define  NV40TCL_CULL_FACE								0x00001830 +#define   NV40TCL_CULL_FACE_FRONT							0x00000404 +#define   NV40TCL_CULL_FACE_BACK							0x00000405 +#define   NV40TCL_CULL_FACE_FRONT_AND_BACK						0x00000408 +#define  NV40TCL_FRONT_FACE								0x00001834 +#define   NV40TCL_FRONT_FACE_CW								0x00000900 +#define   NV40TCL_FRONT_FACE_CCW							0x00000901 +#define  NV40TCL_POLYGON_SMOOTH_ENABLE							0x00001838 +#define  NV40TCL_CULL_FACE_ENABLE							0x0000183c +#define  NV40TCL_TEX_SIZE1(x)								(0x00001840+((x)*4)) +#define  NV40TCL_TEX_SIZE1__SIZE							0x00000008 +#define   NV40TCL_TEX_SIZE1_DEPTH_SHIFT							20 +#define   NV40TCL_TEX_SIZE1_DEPTH_MASK							0xfff00000 +#define   NV40TCL_TEX_SIZE1_PITCH_SHIFT							0 +#define   NV40TCL_TEX_SIZE1_PITCH_MASK							0x0000ffff +#define  NV40TCL_VTX_ATTR_2F_X(x)							(0x00001880+((x)*8)) +#define  NV40TCL_VTX_ATTR_2F_X__SIZE							0x00000010 +#define  NV40TCL_VTX_ATTR_2F_Y(x)							(0x00001884+((x)*8)) +#define  NV40TCL_VTX_ATTR_2F_Y__SIZE							0x00000010 +#define  NV40TCL_VTX_ATTR_2I(x)								(0x00001900+((x)*4)) +#define  NV40TCL_VTX_ATTR_2I__SIZE							0x00000010 +#define   NV40TCL_VTX_ATTR_2I_X_SHIFT							0 +#define   NV40TCL_VTX_ATTR_2I_X_MASK							0x0000ffff +#define   NV40TCL_VTX_ATTR_2I_Y_SHIFT							16 +#define   NV40TCL_VTX_ATTR_2I_Y_MASK							0xffff0000 +#define  NV40TCL_VTX_ATTR_4UB(x)							(0x00001940+((x)*4)) +#define  NV40TCL_VTX_ATTR_4UB__SIZE							0x00000010 +#define   NV40TCL_VTX_ATTR_4UB_X_SHIFT							0 +#define   NV40TCL_VTX_ATTR_4UB_X_MASK							0x000000ff +#define   NV40TCL_VTX_ATTR_4UB_Y_SHIFT							8 +#define   NV40TCL_VTX_ATTR_4UB_Y_MASK							0x0000ff00 +#define   NV40TCL_VTX_ATTR_4UB_Z_SHIFT							16 +#define   NV40TCL_VTX_ATTR_4UB_Z_MASK							0x00ff0000 +#define   NV40TCL_VTX_ATTR_4UB_W_SHIFT							24 +#define   NV40TCL_VTX_ATTR_4UB_W_MASK							0xff000000 +#define  NV40TCL_VTX_ATTR_4I_XY(x)							(0x00001980+((x)*8)) +#define  NV40TCL_VTX_ATTR_4I_XY__SIZE							0x00000010 +#define   NV40TCL_VTX_ATTR_4I_XY_X_SHIFT						0 +#define   NV40TCL_VTX_ATTR_4I_XY_X_MASK							0x0000ffff +#define   NV40TCL_VTX_ATTR_4I_XY_Y_SHIFT						16 +#define   NV40TCL_VTX_ATTR_4I_XY_Y_MASK							0xffff0000 +#define  NV40TCL_VTX_ATTR_4I_ZW(x)							(0x00001984+((x)*8)) +#define  NV40TCL_VTX_ATTR_4I_ZW__SIZE							0x00000010 +#define   NV40TCL_VTX_ATTR_4I_ZW_Z_SHIFT						0 +#define   NV40TCL_VTX_ATTR_4I_ZW_Z_MASK							0x0000ffff +#define   NV40TCL_VTX_ATTR_4I_ZW_W_SHIFT						16 +#define   NV40TCL_VTX_ATTR_4I_ZW_W_MASK							0xffff0000 +#define  NV40TCL_TEX_OFFSET(x)								(0x00001a00+((x)*32)) +#define  NV40TCL_TEX_OFFSET__SIZE							0x00000010 +#define  NV40TCL_TEX_FORMAT(x)								(0x00001a04+((x)*32)) +#define  NV40TCL_TEX_FORMAT__SIZE							0x00000010 +#define   NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT						16 +#define   NV40TCL_TEX_FORMAT_MIPMAP_COUNT_MASK						0x000f0000 +#define   NV40TCL_TEX_FORMAT_RECT							(1 << 14) +#define   NV40TCL_TEX_FORMAT_LINEAR							(1 << 13) +#define   NV40TCL_TEX_FORMAT_FORMAT_SHIFT						8 +#define   NV40TCL_TEX_FORMAT_FORMAT_MASK						0x00001f00 +#define    NV40TCL_TEX_FORMAT_FORMAT_L8							0x00000100 +#define    NV40TCL_TEX_FORMAT_FORMAT_A1R5G5B5						0x00000200 +#define    NV40TCL_TEX_FORMAT_FORMAT_A4R4G4B4						0x00000300 +#define    NV40TCL_TEX_FORMAT_FORMAT_R5G6B5						0x00000400 +#define    NV40TCL_TEX_FORMAT_FORMAT_A8R8G8B8						0x00000500 +#define    NV40TCL_TEX_FORMAT_FORMAT_DXT1						0x00000600 +#define    NV40TCL_TEX_FORMAT_FORMAT_DXT3						0x00000700 +#define    NV40TCL_TEX_FORMAT_FORMAT_DXT5						0x00000800 +#define    NV40TCL_TEX_FORMAT_FORMAT_A8L8						0x00000b00 +#define    NV40TCL_TEX_FORMAT_FORMAT_Z24						0x00001000 +#define    NV40TCL_TEX_FORMAT_FORMAT_Z16						0x00001200 +#define    NV40TCL_TEX_FORMAT_FORMAT_A16                                                0x00001400 +#define    NV40TCL_TEX_FORMAT_FORMAT_HILO8						0x00001800 +#define    NV40TCL_TEX_FORMAT_FORMAT_RGBA16F						0x00001a00 +#define    NV40TCL_TEX_FORMAT_FORMAT_RGBA32F						0x00001b00 +#define   NV40TCL_TEX_FORMAT_DIMS_SHIFT							4 +#define   NV40TCL_TEX_FORMAT_DIMS_MASK							0x000000f0 +#define    NV40TCL_TEX_FORMAT_DIMS_1D							0x00000010 +#define    NV40TCL_TEX_FORMAT_DIMS_2D							0x00000020 +#define    NV40TCL_TEX_FORMAT_DIMS_3D							0x00000030 +#define   NV40TCL_TEX_FORMAT_NO_BORDER							(1 <<  3) +#define   NV40TCL_TEX_FORMAT_CUBIC							(1 <<  2) +#define   NV40TCL_TEX_FORMAT_DMA1							(1 <<  1) +#define   NV40TCL_TEX_FORMAT_DMA0							(1 <<  0) +#define  NV40TCL_TEX_WRAP(x)								(0x00001a08+((x)*32)) +#define  NV40TCL_TEX_WRAP__SIZE								0x00000010 +#define   NV40TCL_TEX_WRAP_S_SHIFT							0 +#define   NV40TCL_TEX_WRAP_S_MASK							0x000000ff +#define    NV40TCL_TEX_WRAP_S_REPEAT							0x00000001 +#define    NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT						0x00000002 +#define    NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE						0x00000003 +#define    NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER						0x00000004 +#define    NV40TCL_TEX_WRAP_S_CLAMP							0x00000005 +#define    NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE					0x00000006 +#define    NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER					0x00000007 +#define    NV40TCL_TEX_WRAP_S_MIRROR_CLAMP						0x00000008 +#define   NV40TCL_TEX_WRAP_T_SHIFT							8 +#define   NV40TCL_TEX_WRAP_T_MASK							0x0000ff00 +#define    NV40TCL_TEX_WRAP_T_REPEAT							0x00000100 +#define    NV40TCL_TEX_WRAP_T_MIRRORED_REPEAT						0x00000200 +#define    NV40TCL_TEX_WRAP_T_CLAMP_TO_EDGE						0x00000300 +#define    NV40TCL_TEX_WRAP_T_CLAMP_TO_BORDER						0x00000400 +#define    NV40TCL_TEX_WRAP_T_CLAMP							0x00000500 +#define    NV40TCL_TEX_WRAP_T_MIRROR_CLAMP_TO_EDGE					0x00000600 +#define    NV40TCL_TEX_WRAP_T_MIRROR_CLAMP_TO_BORDER					0x00000700 +#define    NV40TCL_TEX_WRAP_T_MIRROR_CLAMP						0x00000800 +#define   NV40TCL_TEX_WRAP_R_SHIFT							16 +#define   NV40TCL_TEX_WRAP_R_MASK							0x00ff0000 +#define    NV40TCL_TEX_WRAP_R_REPEAT							0x00010000 +#define    NV40TCL_TEX_WRAP_R_MIRRORED_REPEAT						0x00020000 +#define    NV40TCL_TEX_WRAP_R_CLAMP_TO_EDGE						0x00030000 +#define    NV40TCL_TEX_WRAP_R_CLAMP_TO_BORDER						0x00040000 +#define    NV40TCL_TEX_WRAP_R_CLAMP							0x00050000 +#define    NV40TCL_TEX_WRAP_R_MIRROR_CLAMP_TO_EDGE					0x00060000 +#define    NV40TCL_TEX_WRAP_R_MIRROR_CLAMP_TO_BORDER					0x00070000 +#define    NV40TCL_TEX_WRAP_R_MIRROR_CLAMP						0x00080000 +#define   NV40TCL_TEX_WRAP_RCOMP_SHIFT							28 +#define   NV40TCL_TEX_WRAP_RCOMP_MASK							0xf0000000 +#define    NV40TCL_TEX_WRAP_RCOMP_NEVER							0x00000000 +#define    NV40TCL_TEX_WRAP_RCOMP_GREATER						0x10000000 +#define    NV40TCL_TEX_WRAP_RCOMP_EQUAL							0x20000000 +#define    NV40TCL_TEX_WRAP_RCOMP_GEQUAL						0x30000000 +#define    NV40TCL_TEX_WRAP_RCOMP_LESS							0x40000000 +#define    NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL						0x50000000 +#define    NV40TCL_TEX_WRAP_RCOMP_LEQUAL						0x60000000 +#define    NV40TCL_TEX_WRAP_RCOMP_ALWAYS						0x70000000 +#define  NV40TCL_TEX_ENABLE(x)								(0x00001a0c+((x)*32)) +#define  NV40TCL_TEX_ENABLE__SIZE							0x00000010 +#define   NV40TCL_TEX_ENABLE_ENABLE							(1 << 31) +#define   NV40TCL_TEX_ENABLE_ANISO_SHIFT						4 +#define   NV40TCL_TEX_ENABLE_ANISO_MASK							0x000000f0 +#define    NV40TCL_TEX_ENABLE_ANISO_NONE						0x00000000 +#define    NV40TCL_TEX_ENABLE_ANISO_2X							0x00000010 +#define    NV40TCL_TEX_ENABLE_ANISO_4X							0x00000020 +#define    NV40TCL_TEX_ENABLE_ANISO_6X							0x00000030 +#define    NV40TCL_TEX_ENABLE_ANISO_8X							0x00000040 +#define    NV40TCL_TEX_ENABLE_ANISO_10X							0x00000050 +#define    NV40TCL_TEX_ENABLE_ANISO_12X							0x00000060 +#define    NV40TCL_TEX_ENABLE_ANISO_16X							0x00000070 +#define  NV40TCL_TEX_SWIZZLE(x)								(0x00001a10+((x)*32)) +#define  NV40TCL_TEX_SWIZZLE__SIZE							0x00000010 +#define   NV40TCL_TEX_SWIZZLE_S0_X_SHIFT						14 +#define   NV40TCL_TEX_SWIZZLE_S0_X_MASK							0x0000c000 +#define    NV40TCL_TEX_SWIZZLE_S0_X_ZERO						0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S0_X_ONE							0x00004000 +#define    NV40TCL_TEX_SWIZZLE_S0_X_S1							0x00008000 +#define   NV40TCL_TEX_SWIZZLE_S0_Y_SHIFT						12 +#define   NV40TCL_TEX_SWIZZLE_S0_Y_MASK							0x00003000 +#define    NV40TCL_TEX_SWIZZLE_S0_Y_ZERO						0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S0_Y_ONE							0x00001000 +#define    NV40TCL_TEX_SWIZZLE_S0_Y_S1							0x00002000 +#define   NV40TCL_TEX_SWIZZLE_S0_Z_SHIFT						10 +#define   NV40TCL_TEX_SWIZZLE_S0_Z_MASK							0x00000c00 +#define    NV40TCL_TEX_SWIZZLE_S0_Z_ZERO						0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S0_Z_ONE							0x00000400 +#define    NV40TCL_TEX_SWIZZLE_S0_Z_S1							0x00000800 +#define   NV40TCL_TEX_SWIZZLE_S0_W_SHIFT						8 +#define   NV40TCL_TEX_SWIZZLE_S0_W_MASK							0x00000300 +#define    NV40TCL_TEX_SWIZZLE_S0_W_ZERO						0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S0_W_ONE							0x00000100 +#define    NV40TCL_TEX_SWIZZLE_S0_W_S1							0x00000200 +#define   NV40TCL_TEX_SWIZZLE_S1_X_SHIFT						6 +#define   NV40TCL_TEX_SWIZZLE_S1_X_MASK							0x000000c0 +#define    NV40TCL_TEX_SWIZZLE_S1_X_W							0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S1_X_Z							0x00000040 +#define    NV40TCL_TEX_SWIZZLE_S1_X_Y							0x00000080 +#define    NV40TCL_TEX_SWIZZLE_S1_X_X							0x000000c0 +#define   NV40TCL_TEX_SWIZZLE_S1_Y_SHIFT						4 +#define   NV40TCL_TEX_SWIZZLE_S1_Y_MASK							0x00000030 +#define    NV40TCL_TEX_SWIZZLE_S1_Y_W							0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S1_Y_Z							0x00000010 +#define    NV40TCL_TEX_SWIZZLE_S1_Y_Y							0x00000020 +#define    NV40TCL_TEX_SWIZZLE_S1_Y_X							0x00000030 +#define   NV40TCL_TEX_SWIZZLE_S1_Z_SHIFT						2 +#define   NV40TCL_TEX_SWIZZLE_S1_Z_MASK							0x0000000c +#define    NV40TCL_TEX_SWIZZLE_S1_Z_W							0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S1_Z_Z							0x00000004 +#define    NV40TCL_TEX_SWIZZLE_S1_Z_Y							0x00000008 +#define    NV40TCL_TEX_SWIZZLE_S1_Z_X							0x0000000c +#define   NV40TCL_TEX_SWIZZLE_S1_W_SHIFT						0 +#define   NV40TCL_TEX_SWIZZLE_S1_W_MASK							0x00000003 +#define    NV40TCL_TEX_SWIZZLE_S1_W_W							0x00000000 +#define    NV40TCL_TEX_SWIZZLE_S1_W_Z							0x00000001 +#define    NV40TCL_TEX_SWIZZLE_S1_W_Y							0x00000002 +#define    NV40TCL_TEX_SWIZZLE_S1_W_X							0x00000003 +#define  NV40TCL_TEX_FILTER(x)								(0x00001a14+((x)*32)) +#define  NV40TCL_TEX_FILTER__SIZE							0x00000010 +#define   NV40TCL_TEX_FILTER_SIGNED_ALPHA						(1 << 31) +#define   NV40TCL_TEX_FILTER_SIGNED_RED							(1 << 30) +#define   NV40TCL_TEX_FILTER_SIGNED_GREEN						(1 << 29) +#define   NV40TCL_TEX_FILTER_SIGNED_BLUE						(1 << 28) +#define   NV40TCL_TEX_FILTER_MIN_SHIFT							16 +#define   NV40TCL_TEX_FILTER_MIN_MASK							0x000f0000 +#define    NV40TCL_TEX_FILTER_MIN_NEAREST						0x00010000 +#define    NV40TCL_TEX_FILTER_MIN_LINEAR						0x00020000 +#define    NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST				0x00030000 +#define    NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST					0x00040000 +#define    NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR					0x00050000 +#define    NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR					0x00060000 +#define   NV40TCL_TEX_FILTER_MAG_SHIFT							24 +#define   NV40TCL_TEX_FILTER_MAG_MASK							0x0f000000 +#define    NV40TCL_TEX_FILTER_MAG_NEAREST						0x01000000 +#define    NV40TCL_TEX_FILTER_MAG_LINEAR						0x02000000 +#define  NV40TCL_TEX_SIZE0(x)								(0x00001a18+((x)*32)) +#define  NV40TCL_TEX_SIZE0__SIZE							0x00000010 +#define   NV40TCL_TEX_SIZE0_H_SHIFT							0 +#define   NV40TCL_TEX_SIZE0_H_MASK							0x0000ffff +#define   NV40TCL_TEX_SIZE0_W_SHIFT							16 +#define   NV40TCL_TEX_SIZE0_W_MASK							0xffff0000 +#define  NV40TCL_TEX_BORDER_COLOR(x)							(0x00001a1c+((x)*32)) +#define  NV40TCL_TEX_BORDER_COLOR__SIZE							0x00000010 +#define   NV40TCL_TEX_BORDER_COLOR_B_SHIFT						0 +#define   NV40TCL_TEX_BORDER_COLOR_B_MASK						0x000000ff +#define   NV40TCL_TEX_BORDER_COLOR_G_SHIFT						8 +#define   NV40TCL_TEX_BORDER_COLOR_G_MASK						0x0000ff00 +#define   NV40TCL_TEX_BORDER_COLOR_R_SHIFT						16 +#define   NV40TCL_TEX_BORDER_COLOR_R_MASK						0x00ff0000 +#define   NV40TCL_TEX_BORDER_COLOR_A_SHIFT						24 +#define   NV40TCL_TEX_BORDER_COLOR_A_MASK						0xff000000 +#define  NV40TCL_VTX_ATTR_4F_X(x)							(0x00001c00+((x)*16)) +#define  NV40TCL_VTX_ATTR_4F_X__SIZE							0x00000010 +#define  NV40TCL_VTX_ATTR_4F_Y(x)							(0x00001c04+((x)*16)) +#define  NV40TCL_VTX_ATTR_4F_Y__SIZE							0x00000010 +#define  NV40TCL_VTX_ATTR_4F_Z(x)							(0x00001c08+((x)*16)) +#define  NV40TCL_VTX_ATTR_4F_Z__SIZE							0x00000010 +#define  NV40TCL_VTX_ATTR_4F_W(x)							(0x00001c0c+((x)*16)) +#define  NV40TCL_VTX_ATTR_4F_W__SIZE							0x00000010 +#define  NV40TCL_FP_CONTROL								0x00001d60 +#define   NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT						24 +#define   NV40TCL_FP_CONTROL_TEMP_COUNT_MASK						0xff000000 +#define   NV40TCL_FP_CONTROL_KIL							(1 <<  7) +#define  NV40TCL_MULTISAMPLE_CONTROL							0x00001d7c +#define  NV40TCL_CLEAR_VALUE_DEPTH							0x00001d8c +#define  NV40TCL_CLEAR_VALUE_COLOR							0x00001d90 +#define  NV40TCL_CLEAR_BUFFERS								0x00001d94 +#define   NV40TCL_CLEAR_BUFFERS_COLOR_A							(1 <<  7) +#define   NV40TCL_CLEAR_BUFFERS_COLOR_B							(1 <<  6) +#define   NV40TCL_CLEAR_BUFFERS_COLOR_G							(1 <<  5) +#define   NV40TCL_CLEAR_BUFFERS_COLOR_R							(1 <<  4) +#define   NV40TCL_CLEAR_BUFFERS_STENCIL							(1 <<  1) +#define   NV40TCL_CLEAR_BUFFERS_DEPTH							(1 <<  0) +#define  NV40TCL_LINE_STIPPLE_ENABLE							0x00001db4 +#define  NV40TCL_LINE_STIPPLE_PATTERN							0x00001db8 +#define   NV40TCL_LINE_STIPPLE_PATTERN_FACTOR_SHIFT					0 +#define   NV40TCL_LINE_STIPPLE_PATTERN_FACTOR_MASK					0x0000ffff +#define   NV40TCL_LINE_STIPPLE_PATTERN_PATTERN_SHIFT					16 +#define   NV40TCL_LINE_STIPPLE_PATTERN_PATTERN_MASK					0xffff0000 +#define  NV40TCL_VTX_ATTR_1F(x)								(0x00001e40+((x)*4)) +#define  NV40TCL_VTX_ATTR_1F__SIZE							0x00000010 +#define  NV40TCL_VP_UPLOAD_FROM_ID							0x00001e9c +#define  NV40TCL_VP_START_FROM_ID							0x00001ea0 +#define  NV40TCL_POINT_SIZE								0x00001ee0 +#define  NV40TCL_POINT_SPRITE								0x00001ee8 +#define  NV40TCL_VP_UPLOAD_CONST_ID							0x00001efc +#define  NV40TCL_VP_UPLOAD_CONST_X(x)							(0x00001f00+((x)*16)) +#define  NV40TCL_VP_UPLOAD_CONST_X__SIZE						0x00000004 +#define  NV40TCL_VP_UPLOAD_CONST_Y(x)							(0x00001f04+((x)*16)) +#define  NV40TCL_VP_UPLOAD_CONST_Y__SIZE						0x00000004 +#define  NV40TCL_VP_UPLOAD_CONST_Z(x)							(0x00001f08+((x)*16)) +#define  NV40TCL_VP_UPLOAD_CONST_Z__SIZE						0x00000004 +#define  NV40TCL_VP_UPLOAD_CONST_W(x)							(0x00001f0c+((x)*16)) +#define  NV40TCL_VP_UPLOAD_CONST_W__SIZE						0x00000004 +#define  NV40TCL_TEX_CACHE_CTL								0x00001fd8 +#define  NV40TCL_VP_ATTRIB_EN								0x00001ff0 +#define  NV40TCL_VP_RESULT_EN								0x00001ff4 + + +#define NV44TCL										0x00004497 + + + +#define NV50_2D										0x0000502d + +#define  NV50_2D_NOP									0x00000100 +#define  NV50_2D_NOTIFY									0x00000104 +#define  NV50_2D_DMA_NOTIFY								0x00000180 +#define  NV50_2D_DMA_IN_MEMORY0								0x00000184 +#define  NV50_2D_DMA_IN_MEMORY1								0x00000188 +#define  NV50_2D_DMA_IN_MEMORY2								0x0000018c +#define  NV50_2D_DST_FORMAT								0x00000200 +#define   NV50_2D_DST_FORMAT_32BPP							0x000000cf +#define   NV50_2D_DST_FORMAT_24BPP							0x000000e6 +#define   NV50_2D_DST_FORMAT_16BPP							0x000000e8 +#define   NV50_2D_DST_FORMAT_8BPP							0x000000f3 +#define   NV50_2D_DST_FORMAT_15BPP							0x000000f8 +#define  NV50_2D_DST_PITCH								0x00000214 +#define  NV50_2D_DST_WIDTH								0x00000218 +#define  NV50_2D_DST_HEIGHT								0x0000021c +#define  NV50_2D_DST_ADDRESS_HIGH							0x00000220 +#define  NV50_2D_DST_ADDRESS_LOW							0x00000224 +#define  NV50_2D_SRC_FORMAT								0x00000230 +#define   NV50_2D_SRC_FORMAT_32BPP							0x000000cf +#define   NV50_2D_SRC_FORMAT_24BPP							0x000000e6 +#define   NV50_2D_SRC_FORMAT_16BPP							0x000000e8 +#define   NV50_2D_SRC_FORMAT_8BPP							0x000000f3 +#define   NV50_2D_SRC_FORMAT_15BPP							0x000000f8 +#define  NV50_2D_SRC_PITCH								0x00000244 +#define  NV50_2D_SRC_WIDTH								0x00000248 +#define  NV50_2D_SRC_HEIGHT								0x0000024c +#define  NV50_2D_SRC_ADDRESS_HIGH							0x00000250 +#define  NV50_2D_SRC_ADDRESS_LOW							0x00000254 +#define  NV50_2D_CLIP_X									0x00000280 +#define  NV50_2D_CLIP_Y									0x00000284 +#define  NV50_2D_CLIP_Z									0x00000288 +#define  NV50_2D_CLIP_W									0x0000028c +#define  NV50_2D_ROP									0x000002a0 +#define  NV50_2D_OPERATION								0x000002ac +#define   NV50_2D_OPERATION_SRCCOPY_AND							0x00000000 +#define   NV50_2D_OPERATION_ROP_AND							0x00000001 +#define   NV50_2D_OPERATION_BLEND_AND							0x00000002 +#define   NV50_2D_OPERATION_SRCCOPY							0x00000003 +#define   NV50_2D_OPERATION_SRCCOPY_PREMULT						0x00000004 +#define   NV50_2D_OPERATION_BLEND_PREMULT						0x00000005 +#define  NV50_2D_PATTERN_FORMAT								0x000002e8 +#define   NV50_2D_PATTERN_FORMAT_16BPP							0x00000000 +#define   NV50_2D_PATTERN_FORMAT_15BPP							0x00000001 +#define   NV50_2D_PATTERN_FORMAT_32BPP							0x00000002 +#define   NV50_2D_PATTERN_FORMAT_8BPP							0x00000003 +#define  NV50_2D_PATTERN_COLOR(x)							(0x000002f0+((x)*4)) +#define  NV50_2D_PATTERN_COLOR__SIZE							0x00000002 +#define  NV50_2D_PATTERN_BITMAP(x)							(0x000002f8+((x)*4)) +#define  NV50_2D_PATTERN_BITMAP__SIZE							0x00000002 +#define  NV50_2D_RECT_FORMAT								0x00000584 +#define   NV50_2D_RECT_FORMAT_32BPP							0x000000cf +#define   NV50_2D_RECT_FORMAT_24BPP							0x000000e6 +#define   NV50_2D_RECT_FORMAT_16BPP							0x000000e8 +#define   NV50_2D_RECT_FORMAT_8BPP							0x000000f3 +#define   NV50_2D_RECT_FORMAT_15BPP							0x000000f8 +#define  NV50_2D_RECT_COLOR								0x00000588 +#define  NV50_2D_RECT_X1								0x00000600 +#define  NV50_2D_RECT_Y1								0x00000604 +#define  NV50_2D_RECT_X2								0x00000608 +#define  NV50_2D_RECT_Y2								0x0000060c +#define  NV50_2D_SIFC_UNK0800								0x00000800 +#define  NV50_2D_SIFC_FORMAT								0x00000804 +#define   NV50_2D_SIFC_FORMAT_32BPP							0x000000cf +#define   NV50_2D_SIFC_FORMAT_24BPP							0x000000e6 +#define   NV50_2D_SIFC_FORMAT_16BPP							0x000000e8 +#define   NV50_2D_SIFC_FORMAT_8BPP							0x000000f3 +#define   NV50_2D_SIFC_FORMAT_15BPP							0x000000f8 +#define  NV50_2D_SIFC_WIDTH								0x00000838 +#define  NV50_2D_SIFC_HEIGHT								0x0000083c +#define  NV50_2D_SIFC_SCALE_UNK0840							0x00000840 +#define  NV50_2D_SIFC_SCALE_UNK0844							0x00000844 +#define  NV50_2D_SIFC_SCALE_UNK0848							0x00000848 +#define  NV50_2D_SIFC_SCALE_UNK084C							0x0000084c +#define  NV50_2D_SIFC_UNK0850								0x00000850 +#define  NV50_2D_SIFC_DST_X								0x00000854 +#define  NV50_2D_SIFC_UNK0858								0x00000858 +#define  NV50_2D_SIFC_DST_Y								0x0000085c +#define  NV50_2D_SIFC_DATA								0x00000860 +#define  NV50_2D_BLIT_DST_X								0x000008b0 +#define  NV50_2D_BLIT_DST_Y								0x000008b4 +#define  NV50_2D_BLIT_DST_W								0x000008b8 +#define  NV50_2D_BLIT_DST_H								0x000008bc +#define  NV50_2D_BLIT_SRC_X								0x000008d4 +#define  NV50_2D_BLIT_SRC_Y								0x000008dc + + +#define NV50_MEMORY_TO_MEMORY_FORMAT							0x00005039 + +#define  NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH					0x00000238 +#define  NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH					0x0000023c + + +#define NV50TCL										0x00005097 + +#define  NV50TCL_NOP									0x00000100 +#define  NV50TCL_NOTIFY									0x00000104 +#define  NV50TCL_DMA_NOTIFY								0x00000180 +#define  NV50TCL_DMA_UNK0(x)								(0x00000184+((x)*4)) +#define  NV50TCL_DMA_UNK0__SIZE								0x0000000b +#define  NV50TCL_DMA_UNK1(x)								(0x000001c0+((x)*4)) +#define  NV50TCL_DMA_UNK1__SIZE								0x00000008 +#define  NV50TCL_RT_ADDRESS_HIGH(x)							(0x00000200+((x)*32)) +#define  NV50TCL_RT_ADDRESS_HIGH__SIZE							0x00000008 +#define  NV50TCL_RT_ADDRESS_LOW(x)							(0x00000204+((x)*32)) +#define  NV50TCL_RT_ADDRESS_LOW__SIZE							0x00000008 +#define  NV50TCL_RT_FORMAT(x)								(0x00000208+((x)*32)) +#define  NV50TCL_RT_FORMAT__SIZE							0x00000008 +#define   NV50TCL_RT_FORMAT_32BPP							0x000000cf +#define   NV50TCL_RT_FORMAT_24BPP							0x000000e6 +#define   NV50TCL_RT_FORMAT_16BPP							0x000000e8 +#define   NV50TCL_RT_FORMAT_8BPP							0x000000f3 +#define   NV50TCL_RT_FORMAT_15BPP							0x000000f8 +#define  NV50TCL_RT_TILE_UNK(x)								(0x0000020c+((x)*32)) +#define  NV50TCL_RT_TILE_UNK__SIZE							0x00000008 +#define  NV50TCL_RT_UNK4(x)								(0x00000210+((x)*32)) +#define  NV50TCL_RT_UNK4__SIZE								0x00000008 +#define  NV50TCL_VTX_ATTR_1F(x)								(0x00000300+((x)*4)) +#define  NV50TCL_VTX_ATTR_1F__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_2F_X(x)							(0x00000380+((x)*8)) +#define  NV50TCL_VTX_ATTR_2F_X__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_2F_Y(x)							(0x00000384+((x)*8)) +#define  NV50TCL_VTX_ATTR_2F_Y__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_3F_X(x)							(0x00000400+((x)*16)) +#define  NV50TCL_VTX_ATTR_3F_X__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_3F_Y(x)							(0x00000404+((x)*16)) +#define  NV50TCL_VTX_ATTR_3F_Y__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_3F_Z(x)							(0x00000408+((x)*16)) +#define  NV50TCL_VTX_ATTR_3F_Z__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_3F_W(x)							(0x0000040c+((x)*16)) +#define  NV50TCL_VTX_ATTR_3F_W__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_4F_X(x)							(0x00000500+((x)*16)) +#define  NV50TCL_VTX_ATTR_4F_X__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_4F_Y(x)							(0x00000504+((x)*16)) +#define  NV50TCL_VTX_ATTR_4F_Y__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_4F_Z(x)							(0x00000508+((x)*16)) +#define  NV50TCL_VTX_ATTR_4F_Z__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_4F_W(x)							(0x0000050c+((x)*16)) +#define  NV50TCL_VTX_ATTR_4F_W__SIZE							0x00000010 +#define  NV50TCL_VTX_ATTR_2I(x)								(0x00000680+((x)*4)) +#define  NV50TCL_VTX_ATTR_2I__SIZE							0x00000010 +#define   NV50TCL_VTX_ATTR_2I_X_SHIFT							0 +#define   NV50TCL_VTX_ATTR_2I_X_MASK							0x0000ffff +#define   NV50TCL_VTX_ATTR_2I_Y_SHIFT							16 +#define   NV50TCL_VTX_ATTR_2I_Y_MASK							0xffff0000 +#define  NV50TCL_VTX_ATTR_4I_0(x)							(0x00000700+((x)*8)) +#define  NV50TCL_VTX_ATTR_4I_0__SIZE							0x00000010 +#define   NV50TCL_VTX_ATTR_4I_0_X_SHIFT							0 +#define   NV50TCL_VTX_ATTR_4I_0_X_MASK							0x0000ffff +#define   NV50TCL_VTX_ATTR_4I_0_Y_SHIFT							16 +#define   NV50TCL_VTX_ATTR_4I_0_Y_MASK							0xffff0000 +#define  NV50TCL_VTX_ATTR_4I_1(x)							(0x00000704+((x)*8)) +#define  NV50TCL_VTX_ATTR_4I_1__SIZE							0x00000010 +#define   NV50TCL_VTX_ATTR_4I_1_Z_SHIFT							0 +#define   NV50TCL_VTX_ATTR_4I_1_Z_MASK							0x0000ffff +#define   NV50TCL_VTX_ATTR_4I_1_W_SHIFT							16 +#define   NV50TCL_VTX_ATTR_4I_1_W_MASK							0xffff0000 +#define  NV50TCL_VTX_ATTR_4NI_0(x)							(0x00000780+((x)*8)) +#define  NV50TCL_VTX_ATTR_4NI_0__SIZE							0x00000010 +#define   NV50TCL_VTX_ATTR_4NI_0_X_SHIFT						0 +#define   NV50TCL_VTX_ATTR_4NI_0_X_MASK							0x0000ffff +#define   NV50TCL_VTX_ATTR_4NI_0_Y_SHIFT						16 +#define   NV50TCL_VTX_ATTR_4NI_0_Y_MASK							0xffff0000 +#define  NV50TCL_VTX_ATTR_4NI_1(x)							(0x00000784+((x)*8)) +#define  NV50TCL_VTX_ATTR_4NI_1__SIZE							0x00000010 +#define   NV50TCL_VTX_ATTR_4NI_1_Z_SHIFT						0 +#define   NV50TCL_VTX_ATTR_4NI_1_Z_MASK							0x0000ffff +#define   NV50TCL_VTX_ATTR_4NI_1_W_SHIFT						16 +#define   NV50TCL_VTX_ATTR_4NI_1_W_MASK							0xffff0000 +#define  NV50TCL_VERTEX_ARRAY_FORMAT(x)							(0x00000900+((x)*16)) +#define  NV50TCL_VERTEX_ARRAY_FORMAT__SIZE						0x00000010 +#define  NV50TCL_VIEWPORT_UNK0(x)							(0x00000a00+((x)*4)) +#define  NV50TCL_VIEWPORT_UNK0__SIZE							0x00000003 +#define  NV50TCL_VIEWPORT_UNK1(x)							(0x00000a0c+((x)*4)) +#define  NV50TCL_VIEWPORT_UNK1__SIZE							0x00000003 +#define  NV50TCL_VIEWPORT_HORIZ								0x00000c00 +#define   NV50TCL_VIEWPORT_HORIZ_X_SHIFT						0 +#define   NV50TCL_VIEWPORT_HORIZ_X_MASK							0x0000ffff +#define   NV50TCL_VIEWPORT_HORIZ_W_SHIFT						16 +#define   NV50TCL_VIEWPORT_HORIZ_W_MASK							0xffff0000 +#define  NV50TCL_VIEWPORT_VERT								0x00000c04 +#define   NV50TCL_VIEWPORT_VERT_Y_SHIFT							0 +#define   NV50TCL_VIEWPORT_VERT_Y_MASK							0x0000ffff +#define   NV50TCL_VIEWPORT_VERT_H_SHIFT							16 +#define   NV50TCL_VIEWPORT_VERT_H_MASK							0xffff0000 +#define  NV50TCL_DEPTH_RANGE_NEAR							0x00000c08 +#define  NV50TCL_DEPTH_RANGE_FAR							0x00000c0c +#define  NV50TCL_VIEWPORT_CLIP_HORIZ(x)							(0x00000d00+((x)*8)) +#define  NV50TCL_VIEWPORT_CLIP_HORIZ__SIZE						0x00000008 +#define  NV50TCL_VIEWPORT_CLIP_VERT(x)							(0x00000d04+((x)*8)) +#define  NV50TCL_VIEWPORT_CLIP_VERT__SIZE						0x00000008 +#define  NV50TCL_VERTEX_BUFFER_FIRST							0x00000d74 +#define  NV50TCL_VERTEX_BUFFER_COUNT							0x00000d78 +#define  NV50TCL_CLEAR_COLOR(x)								(0x00000d80+((x)*4)) +#define  NV50TCL_CLEAR_COLOR__SIZE							0x00000004 +#define  NV50TCL_CLEAR_DEPTH								0x00000d90 +#define  NV50TCL_CLEAR_STENCIL								0x00000da0 +#define  NV50TCL_POLYGON_MODE_FRONT							0x00000dac +#define   NV50TCL_POLYGON_MODE_FRONT_POINT						0x00001b00 +#define   NV50TCL_POLYGON_MODE_FRONT_LINE						0x00001b01 +#define   NV50TCL_POLYGON_MODE_FRONT_FILL						0x00001b02 +#define  NV50TCL_POLYGON_MODE_BACK							0x00000db0 +#define   NV50TCL_POLYGON_MODE_BACK_POINT						0x00001b00 +#define   NV50TCL_POLYGON_MODE_BACK_LINE						0x00001b01 +#define   NV50TCL_POLYGON_MODE_BACK_FILL						0x00001b02 +#define  NV50TCL_POLYGON_SMOOTH_ENABLE							0x00000db4 +#define  NV50TCL_POLYGON_OFFSET_POINT_ENABLE						0x00000dc0 +#define  NV50TCL_POLYGON_OFFSET_LINE_ENABLE						0x00000dc4 +#define  NV50TCL_POLYGON_OFFSET_FILL_ENABLE						0x00000dc8 +#define  NV50TCL_SCISSOR_HORIZ								0x00000e04 +#define   NV50TCL_SCISSOR_HORIZ_L_SHIFT							0 +#define   NV50TCL_SCISSOR_HORIZ_L_MASK							0x0000ffff +#define   NV50TCL_SCISSOR_HORIZ_R_SHIFT							16 +#define   NV50TCL_SCISSOR_HORIZ_R_MASK							0xffff0000 +#define  NV50TCL_SCISSOR_VERT								0x00000e08 +#define   NV50TCL_SCISSOR_VERT_T_SHIFT							0 +#define   NV50TCL_SCISSOR_VERT_T_MASK							0x0000ffff +#define   NV50TCL_SCISSOR_VERT_B_SHIFT							16 +#define   NV50TCL_SCISSOR_VERT_B_MASK							0xffff0000 +#define  NV50TCL_CB_ADDR								0x00000f00 +#define   NV50TCL_CB_ADDR_ID_SHIFT							8 +#define   NV50TCL_CB_ADDR_ID_MASK							0xffffff00 +#define   NV50TCL_CB_ADDR_BUFFER_SHIFT							0 +#define   NV50TCL_CB_ADDR_BUFFER_MASK							0x000000ff +#define  NV50TCL_CB_DATA(x)								(0x00000f04+((x)*4)) +#define  NV50TCL_CB_DATA__SIZE								0x00000010 +#define  NV50TCL_STENCIL_FRONT_FUNC_REF							0x00000f54 +#define  NV50TCL_STENCIL_FRONT_MASK							0x00000f58 +#define  NV50TCL_STENCIL_FRONT_FUNC_MASK						0x00000f5c +#define  NV50TCL_GP_ADDRESS_HIGH							0x00000f70 +#define  NV50TCL_GP_ADDRESS_LOW								0x00000f74 +#define  NV50TCL_VP_ADDRESS_HIGH							0x00000f7c +#define  NV50TCL_VP_ADDRESS_LOW								0x00000f80 +#define  NV50TCL_FP_ADDRESS_HIGH							0x00000fa4 +#define  NV50TCL_FP_ADDRESS_LOW								0x00000fa8 +#define  NV50TCL_ZETA_ADDRESS_HIGH							0x00000fe0 +#define  NV50TCL_ZETA_ADDRESS_LOW							0x00000fe4 +#define  NV50TCL_UNKFF4									0x00000ff4 +#define   NV50TCL_UNKFF4_W_SHIFT							16 +#define   NV50TCL_UNKFF4_W_MASK								0xffff0000 +#define  NV50TCL_UNKFF8									0x00000ff8 +#define   NV50TCL_UNKFF8_H_SHIFT							16 +#define   NV50TCL_UNKFF8_H_MASK								0xffff0000 +#define  NV50TCL_RT_HORIZ(x)								(0x00001240+((x)*8)) +#define  NV50TCL_RT_HORIZ__SIZE								0x00000008 +#define  NV50TCL_RT_VERT(x)								(0x00001244+((x)*8)) +#define  NV50TCL_RT_VERT__SIZE								0x00000008 +#define  NV50TCL_CB_DEF_ADDRESS_HIGH							0x00001280 +#define  NV50TCL_CB_DEF_ADDRESS_LOW							0x00001284 +#define  NV50TCL_CB_DEF_SET								0x00001288 +#define   NV50TCL_CB_DEF_SET_SIZE_SHIFT							0 +#define   NV50TCL_CB_DEF_SET_SIZE_MASK							0x0000ffff +#define   NV50TCL_CB_DEF_SET_BUFFER_SHIFT						16 +#define   NV50TCL_CB_DEF_SET_BUFFER_MASK						0xffff0000 +#define  NV50TCL_DEPTH_TEST_ENABLE							0x000012cc +#define  NV50TCL_SHADE_MODEL								0x000012d4 +#define   NV50TCL_SHADE_MODEL_FLAT							0x00001d00 +#define   NV50TCL_SHADE_MODEL_SMOOTH							0x00001d01 +#define  NV50TCL_DEPTH_WRITE_ENABLE							0x000012e8 +#define  NV50TCL_ALPHA_TEST_ENABLE							0x000012ec +#define  NV50TCL_DEPTH_TEST_FUNC							0x0000130c +#define   NV50TCL_DEPTH_TEST_FUNC_NEVER							0x00000200 +#define   NV50TCL_DEPTH_TEST_FUNC_LESS							0x00000201 +#define   NV50TCL_DEPTH_TEST_FUNC_EQUAL							0x00000202 +#define   NV50TCL_DEPTH_TEST_FUNC_LEQUAL						0x00000203 +#define   NV50TCL_DEPTH_TEST_FUNC_GREATER						0x00000204 +#define   NV50TCL_DEPTH_TEST_FUNC_GREATER						0x00000204 +#define   NV50TCL_DEPTH_TEST_FUNC_NOTEQUAL						0x00000205 +#define   NV50TCL_DEPTH_TEST_FUNC_GEQUAL						0x00000206 +#define   NV50TCL_DEPTH_TEST_FUNC_ALWAYS						0x00000207 +#define  NV50TCL_ALPHA_TEST_REF								0x00001310 +#define  NV50TCL_ALPHA_TEST_FUNC							0x00001314 +#define   NV50TCL_ALPHA_TEST_FUNC_NEVER							0x00000200 +#define   NV50TCL_ALPHA_TEST_FUNC_LESS							0x00000201 +#define   NV50TCL_ALPHA_TEST_FUNC_EQUAL							0x00000202 +#define   NV50TCL_ALPHA_TEST_FUNC_LEQUAL						0x00000203 +#define   NV50TCL_ALPHA_TEST_FUNC_GREATER						0x00000204 +#define   NV50TCL_ALPHA_TEST_FUNC_GREATER						0x00000204 +#define   NV50TCL_ALPHA_TEST_FUNC_NOTEQUAL						0x00000205 +#define   NV50TCL_ALPHA_TEST_FUNC_GEQUAL						0x00000206 +#define   NV50TCL_ALPHA_TEST_FUNC_ALWAYS						0x00000207 +#define  NV50TCL_BLEND_COLOR(x)								(0x0000131c+((x)*4)) +#define  NV50TCL_BLEND_COLOR__SIZE							0x00000004 +#define  NV50TCL_BLEND_EQUATION_RGB							0x00001340 +#define   NV50TCL_BLEND_EQUATION_RGB_FUNC_ADD						0x00008006 +#define   NV50TCL_BLEND_EQUATION_RGB_MIN						0x00008007 +#define   NV50TCL_BLEND_EQUATION_RGB_MAX						0x00008008 +#define   NV50TCL_BLEND_EQUATION_RGB_FUNC_SUBTRACT					0x0000800a +#define   NV50TCL_BLEND_EQUATION_RGB_FUNC_REVERSE_SUBTRACT				0x0000800b +#define  NV50TCL_BLEND_FUNC_SRC_RGB							0x00001344 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ZERO						0x00000000 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE						0x00000001 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_SRC_COLOR						0x00000300 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR				0x00000301 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA						0x00000302 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA				0x00000303 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_DST_ALPHA						0x00000304 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA				0x00000305 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_DST_COLOR						0x00000306 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR				0x00000307 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE					0x00000308 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR					0x00008001 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA					0x00008003 +#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV50TCL_BLEND_FUNC_DST_RGB							0x00001348 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ZERO						0x00000000 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE						0x00000001 +#define   NV50TCL_BLEND_FUNC_DST_RGB_SRC_COLOR						0x00000300 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_COLOR				0x00000301 +#define   NV50TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA						0x00000302 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_ALPHA				0x00000303 +#define   NV50TCL_BLEND_FUNC_DST_RGB_DST_ALPHA						0x00000304 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_ALPHA				0x00000305 +#define   NV50TCL_BLEND_FUNC_DST_RGB_DST_COLOR						0x00000306 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_COLOR				0x00000307 +#define   NV50TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA_SATURATE					0x00000308 +#define   NV50TCL_BLEND_FUNC_DST_RGB_CONSTANT_COLOR					0x00008001 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV50TCL_BLEND_FUNC_DST_RGB_CONSTANT_ALPHA					0x00008003 +#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV50TCL_BLEND_EQUATION_ALPHA							0x0000134c +#define   NV50TCL_BLEND_EQUATION_ALPHA_FUNC_ADD						0x00008006 +#define   NV50TCL_BLEND_EQUATION_ALPHA_MIN						0x00008007 +#define   NV50TCL_BLEND_EQUATION_ALPHA_MAX						0x00008008 +#define   NV50TCL_BLEND_EQUATION_ALPHA_FUNC_SUBTRACT					0x0000800a +#define   NV50TCL_BLEND_EQUATION_ALPHA_FUNC_REVERSE_SUBTRACT				0x0000800b +#define  NV50TCL_BLEND_FUNC_SRC_ALPHA							0x00001350 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ZERO						0x00000000 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE						0x00000001 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_SRC_COLOR					0x00000300 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_COLOR				0x00000301 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA					0x00000302 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_ALPHA				0x00000303 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_DST_ALPHA					0x00000304 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_ALPHA				0x00000305 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_DST_COLOR					0x00000306 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_COLOR				0x00000307 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA_SATURATE				0x00000308 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_COLOR					0x00008001 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_ALPHA					0x00008003 +#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV50TCL_BLEND_FUNC_DST_ALPHA							0x00001358 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ZERO						0x00000000 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE						0x00000001 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_SRC_COLOR					0x00000300 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_COLOR				0x00000301 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA					0x00000302 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_ALPHA				0x00000303 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_DST_ALPHA					0x00000304 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_ALPHA				0x00000305 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_DST_COLOR					0x00000306 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_COLOR				0x00000307 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA_SATURATE				0x00000308 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_COLOR					0x00008001 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_COLOR				0x00008002 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_ALPHA					0x00008003 +#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_ALPHA				0x00008004 +#define  NV50TCL_BLEND_ENABLE(x)							(0x00001360+((x)*4)) +#define  NV50TCL_BLEND_ENABLE__SIZE							0x00000008 +#define  NV50TCL_STENCIL_BACK_ENABLE							0x00001380 +#define  NV50TCL_STENCIL_BACK_OP_FAIL							0x00001384 +#define   NV50TCL_STENCIL_BACK_OP_FAIL_ZERO						0x00000000 +#define   NV50TCL_STENCIL_BACK_OP_FAIL_INVERT						0x0000150a +#define   NV50TCL_STENCIL_BACK_OP_FAIL_KEEP						0x00001e00 +#define   NV50TCL_STENCIL_BACK_OP_FAIL_REPLACE						0x00001e01 +#define   NV50TCL_STENCIL_BACK_OP_FAIL_INCR						0x00001e02 +#define   NV50TCL_STENCIL_BACK_OP_FAIL_DECR						0x00001e03 +#define   NV50TCL_STENCIL_BACK_OP_FAIL_INCR_WRAP					0x00008507 +#define   NV50TCL_STENCIL_BACK_OP_FAIL_DECR_WRAP					0x00008508 +#define  NV50TCL_STENCIL_BACK_OP_ZFAIL							0x00001388 +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_ZERO						0x00000000 +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_INVERT						0x0000150a +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_KEEP						0x00001e00 +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_REPLACE						0x00001e01 +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_INCR						0x00001e02 +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_DECR						0x00001e03 +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_INCR_WRAP					0x00008507 +#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_DECR_WRAP					0x00008508 +#define  NV50TCL_STENCIL_BACK_OP_ZPASS							0x0000138c +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_ZERO						0x00000000 +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_INVERT						0x0000150a +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_KEEP						0x00001e00 +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_REPLACE						0x00001e01 +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_INCR						0x00001e02 +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_DECR						0x00001e03 +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_INCR_WRAP					0x00008507 +#define   NV50TCL_STENCIL_BACK_OP_ZPASS_DECR_WRAP					0x00008508 +#define  NV50TCL_STENCIL_BACK_FUNC_FUNC							0x00001390 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_NEVER						0x00000200 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_LESS						0x00000201 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_EQUAL						0x00000202 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_LEQUAL						0x00000203 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_GREATER					0x00000204 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_GREATER					0x00000204 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_NOTEQUAL					0x00000205 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_GEQUAL						0x00000206 +#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_ALWAYS						0x00000207 +#define  NV50TCL_STENCIL_BACK_FUNC_REF							0x00001394 +#define  NV50TCL_STENCIL_BACK_MASK							0x00001398 +#define  NV50TCL_STENCIL_BACK_FUNC_MASK							0x0000139c +#define  NV50TCL_LINE_WIDTH								0x000013b0 +#define  NV50TCL_VP_START_ID								0x0000140c +#define  NV50TCL_GP_START_ID								0x00001410 +#define  NV50TCL_FP_START_ID								0x00001414 +#define  NV50TCL_POINT_SIZE								0x00001518 +#define  NV50TCL_TSC_ADDRESS_HIGH							0x0000155c +#define  NV50TCL_TSC_ADDRESS_LOW							0x00001560 +#define  NV50TCL_POLYGON_OFFSET_FACTOR							0x0000156c +#define  NV50TCL_LINE_SMOOTH_ENABLE							0x00001570 +#define  NV50TCL_TIC_ADDRESS_HIGH							0x00001574 +#define  NV50TCL_TIC_ADDRESS_LOW							0x00001578 +#define  NV50TCL_STENCIL_FRONT_ENABLE							0x00001594 +#define  NV50TCL_STENCIL_FRONT_OP_FAIL							0x00001598 +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_ZERO						0x00000000 +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_INVERT						0x0000150a +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_KEEP						0x00001e00 +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_REPLACE						0x00001e01 +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_INCR						0x00001e02 +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_DECR						0x00001e03 +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_INCR_WRAP					0x00008507 +#define   NV50TCL_STENCIL_FRONT_OP_FAIL_DECR_WRAP					0x00008508 +#define  NV50TCL_STENCIL_FRONT_OP_ZFAIL							0x0000159c +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_ZERO						0x00000000 +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_INVERT						0x0000150a +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_KEEP						0x00001e00 +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_REPLACE					0x00001e01 +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_INCR						0x00001e02 +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_DECR						0x00001e03 +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_INCR_WRAP					0x00008507 +#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_DECR_WRAP					0x00008508 +#define  NV50TCL_STENCIL_FRONT_OP_ZPASS							0x000015a0 +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_ZERO						0x00000000 +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_INVERT						0x0000150a +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_KEEP						0x00001e00 +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_REPLACE					0x00001e01 +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_INCR						0x00001e02 +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_DECR						0x00001e03 +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_INCR_WRAP					0x00008507 +#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_DECR_WRAP					0x00008508 +#define  NV50TCL_STENCIL_FRONT_FUNC_FUNC						0x000015a4 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_NEVER						0x00000200 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_LESS						0x00000201 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_EQUAL						0x00000202 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_LEQUAL					0x00000203 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_GREATER					0x00000204 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_GREATER					0x00000204 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_NOTEQUAL					0x00000205 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_GEQUAL					0x00000206 +#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_ALWAYS					0x00000207 +#define  NV50TCL_POLYGON_OFFSET_UNITS							0x000015bc +#define  NV50TCL_VERTEX_BEGIN								0x000015dc +#define   NV50TCL_VERTEX_BEGIN_POINTS							0x00000000 +#define   NV50TCL_VERTEX_BEGIN_LINES							0x00000001 +#define   NV50TCL_VERTEX_BEGIN_LINE_LOOP						0x00000002 +#define   NV50TCL_VERTEX_BEGIN_LINE_STRIP						0x00000003 +#define   NV50TCL_VERTEX_BEGIN_TRIANGLES						0x00000004 +#define   NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP						0x00000005 +#define   NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN						0x00000006 +#define   NV50TCL_VERTEX_BEGIN_QUADS							0x00000007 +#define   NV50TCL_VERTEX_BEGIN_QUAD_STRIP						0x00000008 +#define   NV50TCL_VERTEX_BEGIN_POLYGON							0x00000009 +#define  NV50TCL_VERTEX_END								0x000015e0 +#define  NV50TCL_VERTEX_DATA								0x00001640 +#define  NV50TCL_VP_ATTR_EN_0								0x00001650 +#define   NV50TCL_VP_ATTR_EN_0_7_SHIFT							28 +#define   NV50TCL_VP_ATTR_EN_0_7_MASK							0xf0000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XNNN							0x10000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NYNN							0x20000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XYNN							0x30000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NNZN							0x40000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XNZN							0x50000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NYZN							0x60000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XYZN							0x70000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NNNW							0x80000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XNNW							0x90000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NYNW							0xa0000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XYNW							0xb0000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NNZW							0xc0000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XNZW							0xd0000000 +#define    NV50TCL_VP_ATTR_EN_0_7_NYZW							0xe0000000 +#define    NV50TCL_VP_ATTR_EN_0_7_XYZW							0xf0000000 +#define   NV50TCL_VP_ATTR_EN_0_6_SHIFT							24 +#define   NV50TCL_VP_ATTR_EN_0_6_MASK							0x0f000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XNNN							0x01000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NYNN							0x02000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XYNN							0x03000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NNZN							0x04000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XNZN							0x05000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NYZN							0x06000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XYZN							0x07000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NNNW							0x08000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XNNW							0x09000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NYNW							0x0a000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XYNW							0x0b000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NNZW							0x0c000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XNZW							0x0d000000 +#define    NV50TCL_VP_ATTR_EN_0_6_NYZW							0x0e000000 +#define    NV50TCL_VP_ATTR_EN_0_6_XYZW							0x0f000000 +#define   NV50TCL_VP_ATTR_EN_0_5_SHIFT							20 +#define   NV50TCL_VP_ATTR_EN_0_5_MASK							0x00f00000 +#define    NV50TCL_VP_ATTR_EN_0_5_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_5_XNNN							0x00100000 +#define    NV50TCL_VP_ATTR_EN_0_5_NYNN							0x00200000 +#define    NV50TCL_VP_ATTR_EN_0_5_XYNN							0x00300000 +#define    NV50TCL_VP_ATTR_EN_0_5_NNZN							0x00400000 +#define    NV50TCL_VP_ATTR_EN_0_5_XNZN							0x00500000 +#define    NV50TCL_VP_ATTR_EN_0_5_NYZN							0x00600000 +#define    NV50TCL_VP_ATTR_EN_0_5_XYZN							0x00700000 +#define    NV50TCL_VP_ATTR_EN_0_5_NNNW							0x00800000 +#define    NV50TCL_VP_ATTR_EN_0_5_XNNW							0x00900000 +#define    NV50TCL_VP_ATTR_EN_0_5_NYNW							0x00a00000 +#define    NV50TCL_VP_ATTR_EN_0_5_XYNW							0x00b00000 +#define    NV50TCL_VP_ATTR_EN_0_5_NNZW							0x00c00000 +#define    NV50TCL_VP_ATTR_EN_0_5_XNZW							0x00d00000 +#define    NV50TCL_VP_ATTR_EN_0_5_NYZW							0x00e00000 +#define    NV50TCL_VP_ATTR_EN_0_5_XYZW							0x00f00000 +#define   NV50TCL_VP_ATTR_EN_0_4_SHIFT							16 +#define   NV50TCL_VP_ATTR_EN_0_4_MASK							0x000f0000 +#define    NV50TCL_VP_ATTR_EN_0_4_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_4_XNNN							0x00010000 +#define    NV50TCL_VP_ATTR_EN_0_4_NYNN							0x00020000 +#define    NV50TCL_VP_ATTR_EN_0_4_XYNN							0x00030000 +#define    NV50TCL_VP_ATTR_EN_0_4_NNZN							0x00040000 +#define    NV50TCL_VP_ATTR_EN_0_4_XNZN							0x00050000 +#define    NV50TCL_VP_ATTR_EN_0_4_NYZN							0x00060000 +#define    NV50TCL_VP_ATTR_EN_0_4_XYZN							0x00070000 +#define    NV50TCL_VP_ATTR_EN_0_4_NNNW							0x00080000 +#define    NV50TCL_VP_ATTR_EN_0_4_XNNW							0x00090000 +#define    NV50TCL_VP_ATTR_EN_0_4_NYNW							0x000a0000 +#define    NV50TCL_VP_ATTR_EN_0_4_XYNW							0x000b0000 +#define    NV50TCL_VP_ATTR_EN_0_4_NNZW							0x000c0000 +#define    NV50TCL_VP_ATTR_EN_0_4_XNZW							0x000d0000 +#define    NV50TCL_VP_ATTR_EN_0_4_NYZW							0x000e0000 +#define    NV50TCL_VP_ATTR_EN_0_4_XYZW							0x000f0000 +#define   NV50TCL_VP_ATTR_EN_0_3_SHIFT							12 +#define   NV50TCL_VP_ATTR_EN_0_3_MASK							0x0000f000 +#define    NV50TCL_VP_ATTR_EN_0_3_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_3_XNNN							0x00001000 +#define    NV50TCL_VP_ATTR_EN_0_3_NYNN							0x00002000 +#define    NV50TCL_VP_ATTR_EN_0_3_XYNN							0x00003000 +#define    NV50TCL_VP_ATTR_EN_0_3_NNZN							0x00004000 +#define    NV50TCL_VP_ATTR_EN_0_3_XNZN							0x00005000 +#define    NV50TCL_VP_ATTR_EN_0_3_NYZN							0x00006000 +#define    NV50TCL_VP_ATTR_EN_0_3_XYZN							0x00007000 +#define    NV50TCL_VP_ATTR_EN_0_3_NNNW							0x00008000 +#define    NV50TCL_VP_ATTR_EN_0_3_XNNW							0x00009000 +#define    NV50TCL_VP_ATTR_EN_0_3_NYNW							0x0000a000 +#define    NV50TCL_VP_ATTR_EN_0_3_XYNW							0x0000b000 +#define    NV50TCL_VP_ATTR_EN_0_3_NNZW							0x0000c000 +#define    NV50TCL_VP_ATTR_EN_0_3_XNZW							0x0000d000 +#define    NV50TCL_VP_ATTR_EN_0_3_NYZW							0x0000e000 +#define    NV50TCL_VP_ATTR_EN_0_3_XYZW							0x0000f000 +#define   NV50TCL_VP_ATTR_EN_0_2_SHIFT							8 +#define   NV50TCL_VP_ATTR_EN_0_2_MASK							0x00000f00 +#define    NV50TCL_VP_ATTR_EN_0_2_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_2_XNNN							0x00000100 +#define    NV50TCL_VP_ATTR_EN_0_2_NYNN							0x00000200 +#define    NV50TCL_VP_ATTR_EN_0_2_XYNN							0x00000300 +#define    NV50TCL_VP_ATTR_EN_0_2_NNZN							0x00000400 +#define    NV50TCL_VP_ATTR_EN_0_2_XNZN							0x00000500 +#define    NV50TCL_VP_ATTR_EN_0_2_NYZN							0x00000600 +#define    NV50TCL_VP_ATTR_EN_0_2_XYZN							0x00000700 +#define    NV50TCL_VP_ATTR_EN_0_2_NNNW							0x00000800 +#define    NV50TCL_VP_ATTR_EN_0_2_XNNW							0x00000900 +#define    NV50TCL_VP_ATTR_EN_0_2_NYNW							0x00000a00 +#define    NV50TCL_VP_ATTR_EN_0_2_XYNW							0x00000b00 +#define    NV50TCL_VP_ATTR_EN_0_2_NNZW							0x00000c00 +#define    NV50TCL_VP_ATTR_EN_0_2_XNZW							0x00000d00 +#define    NV50TCL_VP_ATTR_EN_0_2_NYZW							0x00000e00 +#define    NV50TCL_VP_ATTR_EN_0_2_XYZW							0x00000f00 +#define   NV50TCL_VP_ATTR_EN_0_1_SHIFT							4 +#define   NV50TCL_VP_ATTR_EN_0_1_MASK							0x000000f0 +#define    NV50TCL_VP_ATTR_EN_0_1_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_1_XNNN							0x00000010 +#define    NV50TCL_VP_ATTR_EN_0_1_NYNN							0x00000020 +#define    NV50TCL_VP_ATTR_EN_0_1_XYNN							0x00000030 +#define    NV50TCL_VP_ATTR_EN_0_1_NNZN							0x00000040 +#define    NV50TCL_VP_ATTR_EN_0_1_XNZN							0x00000050 +#define    NV50TCL_VP_ATTR_EN_0_1_NYZN							0x00000060 +#define    NV50TCL_VP_ATTR_EN_0_1_XYZN							0x00000070 +#define    NV50TCL_VP_ATTR_EN_0_1_NNNW							0x00000080 +#define    NV50TCL_VP_ATTR_EN_0_1_XNNW							0x00000090 +#define    NV50TCL_VP_ATTR_EN_0_1_NYNW							0x000000a0 +#define    NV50TCL_VP_ATTR_EN_0_1_XYNW							0x000000b0 +#define    NV50TCL_VP_ATTR_EN_0_1_NNZW							0x000000c0 +#define    NV50TCL_VP_ATTR_EN_0_1_XNZW							0x000000d0 +#define    NV50TCL_VP_ATTR_EN_0_1_NYZW							0x000000e0 +#define    NV50TCL_VP_ATTR_EN_0_1_XYZW							0x000000f0 +#define   NV50TCL_VP_ATTR_EN_0_0_SHIFT							0 +#define   NV50TCL_VP_ATTR_EN_0_0_MASK							0x0000000f +#define    NV50TCL_VP_ATTR_EN_0_0_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_0_0_XNNN							0x00000001 +#define    NV50TCL_VP_ATTR_EN_0_0_NYNN							0x00000002 +#define    NV50TCL_VP_ATTR_EN_0_0_XYNN							0x00000003 +#define    NV50TCL_VP_ATTR_EN_0_0_NNZN							0x00000004 +#define    NV50TCL_VP_ATTR_EN_0_0_XNZN							0x00000005 +#define    NV50TCL_VP_ATTR_EN_0_0_NYZN							0x00000006 +#define    NV50TCL_VP_ATTR_EN_0_0_XYZN							0x00000007 +#define    NV50TCL_VP_ATTR_EN_0_0_NNNW							0x00000008 +#define    NV50TCL_VP_ATTR_EN_0_0_XNNW							0x00000009 +#define    NV50TCL_VP_ATTR_EN_0_0_NYNW							0x0000000a +#define    NV50TCL_VP_ATTR_EN_0_0_XYNW							0x0000000b +#define    NV50TCL_VP_ATTR_EN_0_0_NNZW							0x0000000c +#define    NV50TCL_VP_ATTR_EN_0_0_XNZW							0x0000000d +#define    NV50TCL_VP_ATTR_EN_0_0_NYZW							0x0000000e +#define    NV50TCL_VP_ATTR_EN_0_0_XYZW							0x0000000f +#define  NV50TCL_VP_ATTR_EN_1								0x00001654 +#define   NV50TCL_VP_ATTR_EN_1_15_SHIFT							28 +#define   NV50TCL_VP_ATTR_EN_1_15_MASK							0xf0000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XNNN							0x10000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NYNN							0x20000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XYNN							0x30000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NNZN							0x40000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XNZN							0x50000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NYZN							0x60000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XYZN							0x70000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NNNW							0x80000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XNNW							0x90000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NYNW							0xa0000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XYNW							0xb0000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NNZW							0xc0000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XNZW							0xd0000000 +#define    NV50TCL_VP_ATTR_EN_1_15_NYZW							0xe0000000 +#define    NV50TCL_VP_ATTR_EN_1_15_XYZW							0xf0000000 +#define   NV50TCL_VP_ATTR_EN_1_14_SHIFT							24 +#define   NV50TCL_VP_ATTR_EN_1_14_MASK							0x0f000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XNNN							0x01000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NYNN							0x02000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XYNN							0x03000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NNZN							0x04000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XNZN							0x05000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NYZN							0x06000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XYZN							0x07000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NNNW							0x08000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XNNW							0x09000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NYNW							0x0a000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XYNW							0x0b000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NNZW							0x0c000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XNZW							0x0d000000 +#define    NV50TCL_VP_ATTR_EN_1_14_NYZW							0x0e000000 +#define    NV50TCL_VP_ATTR_EN_1_14_XYZW							0x0f000000 +#define   NV50TCL_VP_ATTR_EN_1_13_SHIFT							20 +#define   NV50TCL_VP_ATTR_EN_1_13_MASK							0x00f00000 +#define    NV50TCL_VP_ATTR_EN_1_13_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_13_XNNN							0x00100000 +#define    NV50TCL_VP_ATTR_EN_1_13_NYNN							0x00200000 +#define    NV50TCL_VP_ATTR_EN_1_13_XYNN							0x00300000 +#define    NV50TCL_VP_ATTR_EN_1_13_NNZN							0x00400000 +#define    NV50TCL_VP_ATTR_EN_1_13_XNZN							0x00500000 +#define    NV50TCL_VP_ATTR_EN_1_13_NYZN							0x00600000 +#define    NV50TCL_VP_ATTR_EN_1_13_XYZN							0x00700000 +#define    NV50TCL_VP_ATTR_EN_1_13_NNNW							0x00800000 +#define    NV50TCL_VP_ATTR_EN_1_13_XNNW							0x00900000 +#define    NV50TCL_VP_ATTR_EN_1_13_NYNW							0x00a00000 +#define    NV50TCL_VP_ATTR_EN_1_13_XYNW							0x00b00000 +#define    NV50TCL_VP_ATTR_EN_1_13_NNZW							0x00c00000 +#define    NV50TCL_VP_ATTR_EN_1_13_XNZW							0x00d00000 +#define    NV50TCL_VP_ATTR_EN_1_13_NYZW							0x00e00000 +#define    NV50TCL_VP_ATTR_EN_1_13_XYZW							0x00f00000 +#define   NV50TCL_VP_ATTR_EN_1_12_SHIFT							16 +#define   NV50TCL_VP_ATTR_EN_1_12_MASK							0x000f0000 +#define    NV50TCL_VP_ATTR_EN_1_12_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_12_XNNN							0x00010000 +#define    NV50TCL_VP_ATTR_EN_1_12_NYNN							0x00020000 +#define    NV50TCL_VP_ATTR_EN_1_12_XYNN							0x00030000 +#define    NV50TCL_VP_ATTR_EN_1_12_NNZN							0x00040000 +#define    NV50TCL_VP_ATTR_EN_1_12_XNZN							0x00050000 +#define    NV50TCL_VP_ATTR_EN_1_12_NYZN							0x00060000 +#define    NV50TCL_VP_ATTR_EN_1_12_XYZN							0x00070000 +#define    NV50TCL_VP_ATTR_EN_1_12_NNNW							0x00080000 +#define    NV50TCL_VP_ATTR_EN_1_12_XNNW							0x00090000 +#define    NV50TCL_VP_ATTR_EN_1_12_NYNW							0x000a0000 +#define    NV50TCL_VP_ATTR_EN_1_12_XYNW							0x000b0000 +#define    NV50TCL_VP_ATTR_EN_1_12_NNZW							0x000c0000 +#define    NV50TCL_VP_ATTR_EN_1_12_XNZW							0x000d0000 +#define    NV50TCL_VP_ATTR_EN_1_12_NYZW							0x000e0000 +#define    NV50TCL_VP_ATTR_EN_1_12_XYZW							0x000f0000 +#define   NV50TCL_VP_ATTR_EN_1_11_SHIFT							12 +#define   NV50TCL_VP_ATTR_EN_1_11_MASK							0x0000f000 +#define    NV50TCL_VP_ATTR_EN_1_11_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_11_XNNN							0x00001000 +#define    NV50TCL_VP_ATTR_EN_1_11_NYNN							0x00002000 +#define    NV50TCL_VP_ATTR_EN_1_11_XYNN							0x00003000 +#define    NV50TCL_VP_ATTR_EN_1_11_NNZN							0x00004000 +#define    NV50TCL_VP_ATTR_EN_1_11_XNZN							0x00005000 +#define    NV50TCL_VP_ATTR_EN_1_11_NYZN							0x00006000 +#define    NV50TCL_VP_ATTR_EN_1_11_XYZN							0x00007000 +#define    NV50TCL_VP_ATTR_EN_1_11_NNNW							0x00008000 +#define    NV50TCL_VP_ATTR_EN_1_11_XNNW							0x00009000 +#define    NV50TCL_VP_ATTR_EN_1_11_NYNW							0x0000a000 +#define    NV50TCL_VP_ATTR_EN_1_11_XYNW							0x0000b000 +#define    NV50TCL_VP_ATTR_EN_1_11_NNZW							0x0000c000 +#define    NV50TCL_VP_ATTR_EN_1_11_XNZW							0x0000d000 +#define    NV50TCL_VP_ATTR_EN_1_11_NYZW							0x0000e000 +#define    NV50TCL_VP_ATTR_EN_1_11_XYZW							0x0000f000 +#define   NV50TCL_VP_ATTR_EN_1_10_SHIFT							8 +#define   NV50TCL_VP_ATTR_EN_1_10_MASK							0x00000f00 +#define    NV50TCL_VP_ATTR_EN_1_10_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_10_XNNN							0x00000100 +#define    NV50TCL_VP_ATTR_EN_1_10_NYNN							0x00000200 +#define    NV50TCL_VP_ATTR_EN_1_10_XYNN							0x00000300 +#define    NV50TCL_VP_ATTR_EN_1_10_NNZN							0x00000400 +#define    NV50TCL_VP_ATTR_EN_1_10_XNZN							0x00000500 +#define    NV50TCL_VP_ATTR_EN_1_10_NYZN							0x00000600 +#define    NV50TCL_VP_ATTR_EN_1_10_XYZN							0x00000700 +#define    NV50TCL_VP_ATTR_EN_1_10_NNNW							0x00000800 +#define    NV50TCL_VP_ATTR_EN_1_10_XNNW							0x00000900 +#define    NV50TCL_VP_ATTR_EN_1_10_NYNW							0x00000a00 +#define    NV50TCL_VP_ATTR_EN_1_10_XYNW							0x00000b00 +#define    NV50TCL_VP_ATTR_EN_1_10_NNZW							0x00000c00 +#define    NV50TCL_VP_ATTR_EN_1_10_XNZW							0x00000d00 +#define    NV50TCL_VP_ATTR_EN_1_10_NYZW							0x00000e00 +#define    NV50TCL_VP_ATTR_EN_1_10_XYZW							0x00000f00 +#define   NV50TCL_VP_ATTR_EN_1_9_SHIFT							4 +#define   NV50TCL_VP_ATTR_EN_1_9_MASK							0x000000f0 +#define    NV50TCL_VP_ATTR_EN_1_9_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_9_XNNN							0x00000010 +#define    NV50TCL_VP_ATTR_EN_1_9_NYNN							0x00000020 +#define    NV50TCL_VP_ATTR_EN_1_9_XYNN							0x00000030 +#define    NV50TCL_VP_ATTR_EN_1_9_NNZN							0x00000040 +#define    NV50TCL_VP_ATTR_EN_1_9_XNZN							0x00000050 +#define    NV50TCL_VP_ATTR_EN_1_9_NYZN							0x00000060 +#define    NV50TCL_VP_ATTR_EN_1_9_XYZN							0x00000070 +#define    NV50TCL_VP_ATTR_EN_1_9_NNNW							0x00000080 +#define    NV50TCL_VP_ATTR_EN_1_9_XNNW							0x00000090 +#define    NV50TCL_VP_ATTR_EN_1_9_NYNW							0x000000a0 +#define    NV50TCL_VP_ATTR_EN_1_9_XYNW							0x000000b0 +#define    NV50TCL_VP_ATTR_EN_1_9_NNZW							0x000000c0 +#define    NV50TCL_VP_ATTR_EN_1_9_XNZW							0x000000d0 +#define    NV50TCL_VP_ATTR_EN_1_9_NYZW							0x000000e0 +#define    NV50TCL_VP_ATTR_EN_1_9_XYZW							0x000000f0 +#define   NV50TCL_VP_ATTR_EN_1_8_SHIFT							0 +#define   NV50TCL_VP_ATTR_EN_1_8_MASK							0x0000000f +#define    NV50TCL_VP_ATTR_EN_1_8_NONE							0x00000000 +#define    NV50TCL_VP_ATTR_EN_1_8_XNNN							0x00000001 +#define    NV50TCL_VP_ATTR_EN_1_8_NYNN							0x00000002 +#define    NV50TCL_VP_ATTR_EN_1_8_XYNN							0x00000003 +#define    NV50TCL_VP_ATTR_EN_1_8_NNZN							0x00000004 +#define    NV50TCL_VP_ATTR_EN_1_8_XNZN							0x00000005 +#define    NV50TCL_VP_ATTR_EN_1_8_NYZN							0x00000006 +#define    NV50TCL_VP_ATTR_EN_1_8_XYZN							0x00000007 +#define    NV50TCL_VP_ATTR_EN_1_8_NNNW							0x00000008 +#define    NV50TCL_VP_ATTR_EN_1_8_XNNW							0x00000009 +#define    NV50TCL_VP_ATTR_EN_1_8_NYNW							0x0000000a +#define    NV50TCL_VP_ATTR_EN_1_8_XYNW							0x0000000b +#define    NV50TCL_VP_ATTR_EN_1_8_NNZW							0x0000000c +#define    NV50TCL_VP_ATTR_EN_1_8_XNZW							0x0000000d +#define    NV50TCL_VP_ATTR_EN_1_8_NYZW							0x0000000e +#define    NV50TCL_VP_ATTR_EN_1_8_XYZW							0x0000000f +#define  NV50TCL_LINE_STIPPLE_ENABLE							0x0000166c +#define  NV50TCL_LINE_STIPPLE_PATTERN							0x00001680 +#define  NV50TCL_POLYGON_STIPPLE_ENABLE							0x0000168c +#define  NV50TCL_VP_REG_HPOS								0x000016bc +#define   NV50TCL_VP_REG_HPOS_X_SHIFT							0 +#define   NV50TCL_VP_REG_HPOS_X_MASK							0x000000ff +#define   NV50TCL_VP_REG_HPOS_Y_SHIFT							8 +#define   NV50TCL_VP_REG_HPOS_Y_MASK							0x0000ff00 +#define   NV50TCL_VP_REG_HPOS_Z_SHIFT							16 +#define   NV50TCL_VP_REG_HPOS_Z_MASK							0x00ff0000 +#define   NV50TCL_VP_REG_HPOS_W_SHIFT							24 +#define   NV50TCL_VP_REG_HPOS_W_MASK							0xff000000 +#define  NV50TCL_VP_REG_COL0								0x000016c0 +#define   NV50TCL_VP_REG_COL0_X_SHIFT							0 +#define   NV50TCL_VP_REG_COL0_X_MASK							0x000000ff +#define   NV50TCL_VP_REG_COL0_Y_SHIFT							8 +#define   NV50TCL_VP_REG_COL0_Y_MASK							0x0000ff00 +#define   NV50TCL_VP_REG_COL0_Z_SHIFT							16 +#define   NV50TCL_VP_REG_COL0_Z_MASK							0x00ff0000 +#define   NV50TCL_VP_REG_COL0_W_SHIFT							24 +#define   NV50TCL_VP_REG_COL0_W_MASK							0xff000000 +#define  NV50TCL_POLYGON_STIPPLE_PATTERN(x)						(0x00001700+((x)*4)) +#define  NV50TCL_POLYGON_STIPPLE_PATTERN__SIZE						0x00000020 +#define  NV50TCL_CULL_FACE_ENABLE							0x00001918 +#define  NV50TCL_FRONT_FACE								0x0000191c +#define   NV50TCL_FRONT_FACE_CW								0x00000900 +#define   NV50TCL_FRONT_FACE_CCW							0x00000901 +#define  NV50TCL_CULL_FACE								0x00001920 +#define   NV50TCL_CULL_FACE_FRONT							0x00000404 +#define   NV50TCL_CULL_FACE_BACK							0x00000405 +#define   NV50TCL_CULL_FACE_FRONT_AND_BACK						0x00000408 +#define  NV50TCL_LOGIC_OP_ENABLE							0x000019c4 +#define  NV50TCL_LOGIC_OP								0x000019c8 +#define   NV50TCL_LOGIC_OP_CLEAR							0x00001500 +#define   NV50TCL_LOGIC_OP_AND								0x00001501 +#define   NV50TCL_LOGIC_OP_AND_REVERSE							0x00001502 +#define   NV50TCL_LOGIC_OP_COPY								0x00001503 +#define   NV50TCL_LOGIC_OP_AND_INVERTED							0x00001504 +#define   NV50TCL_LOGIC_OP_NOOP								0x00001505 +#define   NV50TCL_LOGIC_OP_XOR								0x00001506 +#define   NV50TCL_LOGIC_OP_OR								0x00001507 +#define   NV50TCL_LOGIC_OP_NOR								0x00001508 +#define   NV50TCL_LOGIC_OP_EQUIV							0x00001509 +#define   NV50TCL_LOGIC_OP_INVERT							0x0000150a +#define   NV50TCL_LOGIC_OP_OR_REVERSE							0x0000150b +#define   NV50TCL_LOGIC_OP_COPY_INVERTED						0x0000150c +#define   NV50TCL_LOGIC_OP_OR_INVERTED							0x0000150d +#define   NV50TCL_LOGIC_OP_NAND								0x0000150e +#define   NV50TCL_LOGIC_OP_SET								0x0000150f +#define  NV50TCL_CLEAR_BUFFERS								0x000019d0 +#define  NV50TCL_COLOR_MASK(x)								(0x00001a00+((x)*4)) +#define  NV50TCL_COLOR_MASK__SIZE							0x00000008 +#define   NV50TCL_COLOR_MASK_R_SHIFT							0 +#define   NV50TCL_COLOR_MASK_R_MASK							0x0000000f +#define   NV50TCL_COLOR_MASK_G_SHIFT							4 +#define   NV50TCL_COLOR_MASK_G_MASK							0x000000f0 +#define   NV50TCL_COLOR_MASK_B_SHIFT							8 +#define   NV50TCL_COLOR_MASK_B_MASK							0x00000f00 +#define   NV50TCL_COLOR_MASK_A_SHIFT							12 +#define   NV50TCL_COLOR_MASK_A_MASK							0x0000f000 + + +#define NV50_COMPUTE									0x000050c0 + +#define  NV50_COMPUTE_DMA_UNK0								0x000001a0 +#define  NV50_COMPUTE_DMA_STATUS							0x000001a4 +#define  NV50_COMPUTE_DMA_UNK1								0x000001b8 +#define  NV50_COMPUTE_DMA_UNK2								0x000001bc +#define  NV50_COMPUTE_DMA_UNK3								0x000001c0 +#define  NV50_COMPUTE_UNK4_HIGH								0x00000210 +#define  NV50_COMPUTE_UNK4_LOW								0x00000214 +#define  NV50_COMPUTE_UNK5_HIGH								0x00000218 +#define  NV50_COMPUTE_UNK5_LOW								0x0000021c +#define  NV50_COMPUTE_UNK6_HIGH								0x00000294 +#define  NV50_COMPUTE_UNK6_LOW								0x00000298 +#define  NV50_COMPUTE_CONST_BASE_HIGH							0x000002a4 +#define  NV50_COMPUTE_CONST_BASE_LO							0x000002a8 +#define  NV50_COMPUTE_CONST_SIZE_SEG							0x000002ac +#define  NV50_COMPUTE_REG_COUNT								0x000002c0 +#define  NV50_COMPUTE_STATUS_HIGH							0x00000310 +#define  NV50_COMPUTE_STATUS_LOW							0x00000314 +#define  NV50_COMPUTE_EXECUTE								0x0000031c +#define  NV50_COMPUTE_USER_PARAM_COUNT							0x00000374 +#define  NV50_COMPUTE_GRIDDIM_YX							0x000003a4 +#define  NV50_COMPUTE_SHARED_SIZE							0x000003a8 +#define  NV50_COMPUTE_BLOCKDIM_YX							0x000003ac +#define  NV50_COMPUTE_BLOCKDIM_Z							0x000003b0 +#define  NV50_COMPUTE_CALL_ADDRESS							0x000003b4 +#define  NV50_COMPUTE_GLOBAL_BASE_HIGH(x)						(0x00000400+((x)*32)) +#define  NV50_COMPUTE_GLOBAL_BASE_HIGH__SIZE						0x00000010 +#define  NV50_COMPUTE_GLOBAL_BASE_LOW(x)						(0x00000404+((x)*32)) +#define  NV50_COMPUTE_GLOBAL_BASE_LOW__SIZE						0x00000010 +#define  NV50_COMPUTE_GLOBAL_LIMIT_HIGH(x)						(0x00000408+((x)*32)) +#define  NV50_COMPUTE_GLOBAL_LIMIT_HIGH__SIZE						0x00000010 +#define  NV50_COMPUTE_GLOBAL_LIMIT_LOW(x)						(0x0000040c+((x)*32)) +#define  NV50_COMPUTE_GLOBAL_LIMIT_LOW__SIZE						0x00000010 +#define  NV50_COMPUTE_GLOBAL_UNK(x)							(0x00000410+((x)*32)) +#define  NV50_COMPUTE_GLOBAL_UNK__SIZE							0x00000010 +#define  NV50_COMPUTE_USER_PARAM(x)							(0x00000600+((x)*4)) +#define  NV50_COMPUTE_USER_PARAM__SIZE							0x00000040 + + +#define NV54TCL										0x00008297 + + + +#endif /* NOUVEAU_REG_H */ diff --git a/src/gallium/drivers/nouveau/nouveau_device.h b/src/gallium/drivers/nouveau/nouveau_device.h new file mode 100644 index 0000000000..e25e89fedd --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_device.h @@ -0,0 +1,30 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_DEVICE_H__ +#define __NOUVEAU_DEVICE_H__ + +struct nouveau_device { +	unsigned chipset; +}; + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_gldefs.h b/src/gallium/drivers/nouveau/nouveau_gldefs.h new file mode 100644 index 0000000000..e1015c93a2 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_gldefs.h @@ -0,0 +1,196 @@ +#ifndef __NOUVEAU_GLDEFS_H__ +#define __NOUVEAU_GLDEFS_H__ + +static INLINE unsigned +nvgl_blend_func(unsigned factor) +{ +	switch (factor) { +	case PIPE_BLENDFACTOR_ZERO: +		return 0x0000; +	case PIPE_BLENDFACTOR_ONE: +		return 0x0001; +	case PIPE_BLENDFACTOR_SRC_COLOR: +		return 0x0300; +	case PIPE_BLENDFACTOR_INV_SRC_COLOR: +		return 0x0301; +	case PIPE_BLENDFACTOR_SRC_ALPHA: +		return 0x0302; +	case PIPE_BLENDFACTOR_INV_SRC_ALPHA: +		return 0x0303; +	case PIPE_BLENDFACTOR_DST_ALPHA: +		return 0x0304; +	case PIPE_BLENDFACTOR_INV_DST_ALPHA: +		return 0x0305; +	case PIPE_BLENDFACTOR_DST_COLOR: +		return 0x0306; +	case PIPE_BLENDFACTOR_INV_DST_COLOR: +		return 0x0307; +	case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: +		return 0x0308; +	case PIPE_BLENDFACTOR_CONST_COLOR: +		return 0x8001; +	case PIPE_BLENDFACTOR_INV_CONST_COLOR: +		return 0x8002; +	case PIPE_BLENDFACTOR_CONST_ALPHA: +		return 0x8003; +	case PIPE_BLENDFACTOR_INV_CONST_ALPHA: +		return 0x8004; +	default: +		return 0x0000; +	} +} + +static INLINE unsigned +nvgl_blend_eqn(unsigned func) +{ +	switch (func) { +	case PIPE_BLEND_ADD: +		return 0x8006; +	case PIPE_BLEND_MIN: +		return 0x8007; +	case PIPE_BLEND_MAX: +		return 0x8008; +	case PIPE_BLEND_SUBTRACT: +		return 0x800a; +	case PIPE_BLEND_REVERSE_SUBTRACT: +		return 0x800b; +	default: +		return 0x8006; +	} +} + +static INLINE unsigned +nvgl_logicop_func(unsigned func) +{ +	switch (func) { +	case PIPE_LOGICOP_CLEAR: +		return 0x1500; +	case PIPE_LOGICOP_NOR: +		return 0x1508; +	case PIPE_LOGICOP_AND_INVERTED: +		return 0x1504; +	case PIPE_LOGICOP_COPY_INVERTED: +		return 0x150c; +	case PIPE_LOGICOP_AND_REVERSE: +		return 0x1502; +	case PIPE_LOGICOP_INVERT: +		return 0x150a; +	case PIPE_LOGICOP_XOR: +		return 0x1506; +	case PIPE_LOGICOP_NAND: +		return 0x150e; +	case PIPE_LOGICOP_AND: +		return 0x1501; +	case PIPE_LOGICOP_EQUIV: +		return 0x1509; +	case PIPE_LOGICOP_NOOP: +		return 0x1505; +	case PIPE_LOGICOP_OR_INVERTED: +		return 0x150d; +	case PIPE_LOGICOP_COPY: +		return 0x1503; +	case PIPE_LOGICOP_OR_REVERSE: +		return 0x150b; +	case PIPE_LOGICOP_OR: +		return 0x1507; +	case PIPE_LOGICOP_SET: +		return 0x150f; +	default: +		return 0x1505; +	} +} + +static INLINE unsigned +nvgl_comparison_op(unsigned op) +{ +	switch (op) { +	case PIPE_FUNC_NEVER: +		return 0x0200; +	case PIPE_FUNC_LESS: +		return 0x0201; +	case PIPE_FUNC_EQUAL: +		return 0x0202; +	case PIPE_FUNC_LEQUAL: +		return 0x0203; +	case PIPE_FUNC_GREATER: +		return 0x0204; +	case PIPE_FUNC_NOTEQUAL: +		return 0x0205; +	case PIPE_FUNC_GEQUAL: +		return 0x0206; +	case PIPE_FUNC_ALWAYS: +		return 0x0207; +	default: +		return 0x0207; +	} +} + +static INLINE unsigned +nvgl_polygon_mode(unsigned mode) +{ +	switch (mode) { +	case PIPE_POLYGON_MODE_POINT: +		return 0x1b00; +	case PIPE_POLYGON_MODE_LINE: +		return 0x1b01; +	case PIPE_POLYGON_MODE_FILL: +		return 0x1b02; +	default: +		return 0x1b02; +	} +} + +static INLINE unsigned +nvgl_stencil_op(unsigned op) +{ +	switch (op) { +	case PIPE_STENCIL_OP_ZERO: +		return 0x0000; +	case PIPE_STENCIL_OP_INVERT: +		return 0x150a; +	case PIPE_STENCIL_OP_KEEP: +		return 0x1e00; +	case PIPE_STENCIL_OP_REPLACE: +		return 0x1e01; +	case PIPE_STENCIL_OP_INCR: +		return 0x1e02; +	case PIPE_STENCIL_OP_DECR: +		return 0x1e03; +	case PIPE_STENCIL_OP_INCR_WRAP: +		return 0x8507; +	case PIPE_STENCIL_OP_DECR_WRAP: +		return 0x8508; +	default: +		return 0x1e00; +	} +} + +static INLINE unsigned +nvgl_primitive(unsigned prim) { +	switch (prim) { +	case PIPE_PRIM_POINTS: +		return 0x0001; +	case PIPE_PRIM_LINES: +		return 0x0002; +	case PIPE_PRIM_LINE_LOOP: +		return 0x0003; +	case PIPE_PRIM_LINE_STRIP: +		return 0x0004; +	case PIPE_PRIM_TRIANGLES: +		return 0x0005; +	case PIPE_PRIM_TRIANGLE_STRIP: +		return 0x0006; +	case PIPE_PRIM_TRIANGLE_FAN: +		return 0x0007; +	case PIPE_PRIM_QUADS: +		return 0x0008; +	case PIPE_PRIM_QUAD_STRIP: +		return 0x0009; +	case PIPE_PRIM_POLYGON: +		return 0x000a; +	default: +		return 0x0001; +	} +} + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_grobj.h b/src/gallium/drivers/nouveau/nouveau_grobj.h new file mode 100644 index 0000000000..8f5abf9051 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_grobj.h @@ -0,0 +1,35 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_GROBJ_H__ +#define __NOUVEAU_GROBJ_H__ + +#include "nouveau_channel.h" + +struct nouveau_grobj { +	struct nouveau_channel *channel; +	int grclass; +	uint32_t handle; +	int subc; +}; + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_notifier.h b/src/gallium/drivers/nouveau/nouveau_notifier.h new file mode 100644 index 0000000000..35adde1e32 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_notifier.h @@ -0,0 +1,43 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_NOTIFIER_H__ +#define __NOUVEAU_NOTIFIER_H__ + +#define NV_NOTIFIER_SIZE                                                      32 +#define NV_NOTIFY_TIME_0                                              0x00000000 +#define NV_NOTIFY_TIME_1                                              0x00000004 +#define NV_NOTIFY_RETURN_VALUE                                        0x00000008 +#define NV_NOTIFY_STATE                                               0x0000000C +#define NV_NOTIFY_STATE_STATUS_MASK                                   0xFF000000 +#define NV_NOTIFY_STATE_STATUS_SHIFT                                          24 +#define NV_NOTIFY_STATE_STATUS_COMPLETED                                    0x00 +#define NV_NOTIFY_STATE_STATUS_IN_PROCESS                                   0x01 +#define NV_NOTIFY_STATE_ERROR_CODE_MASK                               0x0000FFFF +#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT                                       0 + +struct nouveau_notifier { +	struct nouveau_channel *channel; +	uint32_t handle; +}; + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_push.h b/src/gallium/drivers/nouveau/nouveau_push.h new file mode 100644 index 0000000000..54ef1c1291 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_push.h @@ -0,0 +1,82 @@ +#ifndef __NOUVEAU_PUSH_H__ +#define __NOUVEAU_PUSH_H__ + +#include "nouveau/nouveau_winsys.h" + +#ifndef NOUVEAU_PUSH_CONTEXT +#error undefined push context +#endif + +#define OUT_RING(data) do {                                                    \ +	NOUVEAU_PUSH_CONTEXT(pc);                                              \ +	(*pc->nvws->channel->pushbuf->cur++) = (data);                         \ +} while(0) + +#define OUT_RINGp(src,size) do {                                               \ +	NOUVEAU_PUSH_CONTEXT(pc);                                              \ +	memcpy(pc->nvws->channel->pushbuf->cur, (src), (size) * 4);            \ +	pc->nvws->channel->pushbuf->cur += (size);                             \ +} while(0) + +#define OUT_RINGf(data) do {                                                   \ +	union { float v; uint32_t u; } c;                                      \ +	c.v = (data);                                                          \ +	OUT_RING(c.u);                                                         \ +} while(0) + +#define BEGIN_RING(obj,mthd,size) do {                                         \ +	NOUVEAU_PUSH_CONTEXT(pc);                                              \ +	if (pc->nvws->channel->pushbuf->remaining < ((size) + 1))              \ +		pc->nvws->push_flush(pc->nvws, ((size) + 1), NULL);            \ +	OUT_RING((pc->obj->subc << 13) | ((size) << 18) | (mthd));             \ +	pc->nvws->channel->pushbuf->remaining -= ((size) + 1);                 \ +} while(0) + +#define BEGIN_RING_NI(obj,mthd,size) do {                                      \ +	BEGIN_RING(obj, (mthd) | 0x40000000, (size));                          \ +} while(0) + +#define FIRE_RING(fence) do {                                                  \ +	NOUVEAU_PUSH_CONTEXT(pc);                                              \ +	pc->nvws->push_flush(pc->nvws, 0, fence);                              \ +} while(0) + +#define OUT_RELOC(bo,data,flags,vor,tor) do {                                  \ +	NOUVEAU_PUSH_CONTEXT(pc);                                              \ +	pc->nvws->push_reloc(pc->nvws, pc->nvws->channel->pushbuf->cur++,      \ +			     (bo), (data), (flags), (vor), (tor));             \ +} while(0) + +/* Raw data + flags depending on FB/TT buffer */ +#define OUT_RELOCd(bo,data,flags,vor,tor) do {                                 \ +	OUT_RELOC((bo), (data), (flags) | NOUVEAU_BO_OR, (vor), (tor));        \ +} while(0) + +/* FB/TT object handle */ +#define OUT_RELOCo(bo,flags) do {                                              \ +	OUT_RELOC((bo), 0, (flags) | NOUVEAU_BO_OR,                            \ +		  pc->nvws->channel->vram->handle,                             \ +		  pc->nvws->channel->gart->handle);                            \ +} while(0) + +/* Low 32-bits of offset */ +#define OUT_RELOCl(bo,delta,flags) do {                                        \ +	OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_LOW, 0, 0);              \ +} while(0) + +/* High 32-bits of offset */ +#define OUT_RELOCh(bo,delta,flags) do {                                        \ +	OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_HIGH, 0, 0);             \ +} while(0) + +/* A reloc which'll recombine into a NV_DMA_METHOD packet header */ +#define OUT_RELOCm(bo, flags, obj, mthd, size) do {                            \ +	NOUVEAU_PUSH_CONTEXT(pc);                                              \ +	if (pc->nvws->channel->pushbuf->remaining < ((size) + 1))              \ +		pc->nvws->push_flush(pc->nvws->channel, ((size) + 1), NULL);   \ +	OUT_RELOCd((bo), (pc->obj->subc << 13) | ((size) << 18) | (mthd),      \ +		   (flags), 0, 0);                                             \ +	pc->nvws->channel->pushbuf->remaining -= ((size) + 1);                 \ +} while(0) + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_pushbuf.h b/src/gallium/drivers/nouveau/nouveau_pushbuf.h new file mode 100644 index 0000000000..1909765098 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_pushbuf.h @@ -0,0 +1,32 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_PUSHBUF_H__ +#define __NOUVEAU_PUSHBUF_H__ + +struct nouveau_pushbuf { +	struct nouveau_channel *channel; +	unsigned remaining; +	uint32_t *cur; +}; + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_resource.h b/src/gallium/drivers/nouveau/nouveau_resource.h new file mode 100644 index 0000000000..1af7961d30 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_resource.h @@ -0,0 +1,37 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_RESOURCE_H__ +#define __NOUVEAU_RESOURCE_H__ + +struct nouveau_resource { +	struct nouveau_resource *prev; +	struct nouveau_resource *next; + +	int in_use; +	void *priv; + +	unsigned int start; +	unsigned int size; +}; + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h new file mode 100644 index 0000000000..998ec2d4ad --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h @@ -0,0 +1,159 @@ +#ifndef __NOUVEAU_STATEOBJ_H__ +#define __NOUVEAU_STATEOBJ_H__ + +#include "pipe/p_util.h" +#include "pipe/p_debug.h" + +struct nouveau_stateobj_reloc { +	struct pipe_buffer *bo; + +	unsigned offset; +	unsigned packet; + +	unsigned data; +	unsigned flags; +	unsigned vor; +	unsigned tor; +}; + +struct nouveau_stateobj { +	int refcount; + +	unsigned *push; +	struct nouveau_stateobj_reloc *reloc; + +	unsigned *cur; +	unsigned cur_packet; +	unsigned cur_reloc; +}; + +static INLINE struct nouveau_stateobj * +so_new(unsigned push, unsigned reloc) +{ +	struct nouveau_stateobj *so; + +	so = MALLOC(sizeof(struct nouveau_stateobj)); +	so->refcount = 0; +	so->push = MALLOC(sizeof(unsigned) * push); +	so->reloc = MALLOC(sizeof(struct nouveau_stateobj_reloc) * reloc); + +	so->cur = so->push; +	so->cur_reloc = so->cur_packet = 0; + +	return so; +} + +static INLINE void +so_ref(struct nouveau_stateobj *ref, struct nouveau_stateobj **pso) +{ +	struct nouveau_stateobj *so = *pso; + +	if (ref) { +		ref->refcount++; +	} + +	if (so && --so->refcount <= 0) { +		free(so->push); +		free(so->reloc); +		free(so); +	} + +	*pso = ref; +} + +static INLINE void +so_data(struct nouveau_stateobj *so, unsigned data) +{ +	(*so->cur++) = (data); +	so->cur_packet += 4; +} + +static INLINE void +so_datap(struct nouveau_stateobj *so, unsigned *data, unsigned size) +{ +	so->cur_packet += (4 * size); +	while (size--) +		(*so->cur++) = (*data++); +} + +static INLINE void +so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr, +	  unsigned mthd, unsigned size) +{ +	so->cur_packet = (gr->subc << 13) | (1 << 18) | (mthd - 4); +	so_data(so, (gr->subc << 13) | (size << 18) | mthd); +} + +static INLINE void +so_reloc(struct nouveau_stateobj *so, struct pipe_buffer *bo, +	 unsigned data, unsigned flags, unsigned vor, unsigned tor) +{ +	struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++]; +	 +	r->bo = bo; +	r->offset = so->cur - so->push; +	r->packet = so->cur_packet; +	r->data = data; +	r->flags = flags; +	r->vor = vor; +	r->tor = tor; +	so_data(so, data); +} + +static INLINE void +so_dump(struct nouveau_stateobj *so) +{ +	unsigned i, nr = so->cur - so->push; + +	for (i = 0; i < nr; i++) +		debug_printf("+0x%04x: 0x%08x\n", i, so->push[i]); +} + +static INLINE void +so_emit(struct nouveau_winsys *nvws, struct nouveau_stateobj *so) +{ +	struct nouveau_pushbuf *pb = nvws->channel->pushbuf; +	unsigned nr, i; + +	nr = so->cur - so->push; +	if (pb->remaining < nr) +		nvws->push_flush(nvws, nr, NULL); +	pb->remaining -= nr; + +	memcpy(pb->cur, so->push, nr * 4); +	for (i = 0; i < so->cur_reloc; i++) { +		struct nouveau_stateobj_reloc *r = &so->reloc[i]; + +		nvws->push_reloc(nvws, pb->cur + r->offset, r->bo, +				 r->data, r->flags, r->vor, r->tor); +	} +	pb->cur += nr; +} + +static INLINE void +so_emit_reloc_markers(struct nouveau_winsys *nvws, struct nouveau_stateobj *so) +{ +	struct nouveau_pushbuf *pb = nvws->channel->pushbuf; +	unsigned i; + +	if (!so) +		return; + +	i = so->cur_reloc << 1; +	if (nvws->channel->pushbuf->remaining < i) +		nvws->push_flush(nvws, i, NULL); +	nvws->channel->pushbuf->remaining -= i; + +	for (i = 0; i < so->cur_reloc; i++) { +		struct nouveau_stateobj_reloc *r = &so->reloc[i]; + +		nvws->push_reloc(nvws, pb->cur++, r->bo, r->packet, +				 (r->flags & +				  (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) | +				 NOUVEAU_BO_DUMMY, 0, 0); +		nvws->push_reloc(nvws, pb->cur++, r->bo, r->data, +				 r->flags | NOUVEAU_BO_DUMMY, r->vor, r->tor); +	} +} + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h new file mode 100644 index 0000000000..c92041ebeb --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_util.h @@ -0,0 +1,64 @@ +#ifndef __NOUVEAU_UTIL_H__ +#define __NOUVEAU_UTIL_H__ + +/* Determine how many vertices can be pushed into the command stream. + * Where the remaining space isn't large enough to represent all verices, + * split the buffer at primitive boundaries. + * + * Returns a count of vertices that can be rendered, and an index to + * restart drawing at after a flush. + */ +static INLINE unsigned +nouveau_vbuf_split(unsigned remaining, unsigned overhead, unsigned vpp, +		   unsigned mode, unsigned start, unsigned count, +		   unsigned *restart) +{ +	int max, adj = 0; + +	max  = remaining - overhead; +	if (max < 0) +		return 0; + +	max *= vpp; +	if (max >= count) +		return count; + +	switch (mode) { +	case PIPE_PRIM_POINTS: +		break; +	case PIPE_PRIM_LINES: +		max = max & 1; +		break; +	case PIPE_PRIM_TRIANGLES: +		max = max - (max % 3); +		break; +	case PIPE_PRIM_QUADS: +		max = max & 3; +		break; +	case PIPE_PRIM_LINE_LOOP: +	case PIPE_PRIM_LINE_STRIP: +		if (max < 2) +			max = 0; +		adj = 1; +		break; +	case PIPE_PRIM_POLYGON: +	case PIPE_PRIM_TRIANGLE_STRIP: +	case PIPE_PRIM_TRIANGLE_FAN: +		if (max < 3) +			max = 0; +		adj = 2; +		break; +	case PIPE_PRIM_QUAD_STRIP: +		if (max < 4) +			max = 0; +		adj = 3; +		break; +	default: +		assert(0); +	} + +	*restart = start + max - adj; +	return max; +} + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h new file mode 100644 index 0000000000..48feeba309 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -0,0 +1,90 @@ +#ifndef NOUVEAU_WINSYS_H +#define NOUVEAU_WINSYS_H + +#include <stdint.h> +#include "pipe/p_winsys.h" +#include "pipe/p_defines.h" + +#include "nouveau/nouveau_bo.h" +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_class.h" +#include "nouveau/nouveau_device.h" +#include "nouveau/nouveau_grobj.h" +#include "nouveau/nouveau_notifier.h" +#include "nouveau/nouveau_resource.h" +#include "nouveau/nouveau_pushbuf.h" + +#define NOUVEAU_CAP_HW_VTXBUF (0xbeef0000) +#define NOUVEAU_CAP_HW_IDXBUF (0xbeef0001) + +#define NOUVEAU_BUFFER_USAGE_TEXTURE (1 << 16) +#define NOUVEAU_BUFFER_USAGE_ZETA    (1 << 17) + +struct nouveau_winsys { +	struct nouveau_context *nv; + +	struct nouveau_channel *channel; + +	int  (*res_init)(struct nouveau_resource **heap, unsigned start, +			 unsigned size); +	int  (*res_alloc)(struct nouveau_resource *heap, int size, void *priv, +			  struct nouveau_resource **); +	void (*res_free)(struct nouveau_resource **); + +	int  (*push_reloc)(struct nouveau_winsys *, void *ptr, +			   struct pipe_buffer *, uint32_t data, +			   uint32_t flags, uint32_t vor, uint32_t tor); +	int  (*push_flush)(struct nouveau_winsys *, unsigned size, +			   struct pipe_fence_handle **fence); +			        +	int       (*grobj_alloc)(struct nouveau_winsys *, int grclass, +				 struct nouveau_grobj **); +	void      (*grobj_free)(struct nouveau_grobj **); + +	int       (*notifier_alloc)(struct nouveau_winsys *, int count, +				    struct nouveau_notifier **); +	void      (*notifier_free)(struct nouveau_notifier **); +	void      (*notifier_reset)(struct nouveau_notifier *, int id); +	uint32_t  (*notifier_status)(struct nouveau_notifier *, int id); +	uint32_t  (*notifier_retval)(struct nouveau_notifier *, int id); +	int       (*notifier_wait)(struct nouveau_notifier *, int id, +				   int status, int timeout); + +	int (*surface_copy)(struct nouveau_winsys *, struct pipe_surface *, +			    unsigned, unsigned, struct pipe_surface *, +			    unsigned, unsigned, unsigned, unsigned); +	int (*surface_fill)(struct nouveau_winsys *, struct pipe_surface *, +			    unsigned, unsigned, unsigned, unsigned, unsigned); +}; + +extern struct pipe_screen * +nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); + +extern struct pipe_context * +nv04_create(struct pipe_screen *, unsigned pctx_id); + +extern struct pipe_screen * +nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); + +extern struct pipe_context * +nv10_create(struct pipe_screen *, unsigned pctx_id); + +extern struct pipe_screen * +nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); + +extern struct pipe_context * +nv30_create(struct pipe_screen *, unsigned pctx_id); + +extern struct pipe_screen * +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); + +extern struct pipe_context * +nv40_create(struct pipe_screen *, unsigned pctx_id); + +extern struct pipe_screen * +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); + +extern struct pipe_context * +nv50_create(struct pipe_screen *, unsigned pctx_id); + +#endif diff --git a/src/gallium/drivers/nv04/Makefile b/src/gallium/drivers/nv04/Makefile new file mode 100644 index 0000000000..5ea51a2f42 --- /dev/null +++ b/src/gallium/drivers/nv04/Makefile @@ -0,0 +1,28 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nv04 + +DRIVER_SOURCES = \ +	nv04_clear.c \ +	nv04_context.c \ +	nv04_fragprog.c \ +	nv04_fragtex.c \ +	nv04_miptree.c \ +	nv04_prim_vbuf.c \ +	nv04_screen.c \ +	nv04_state.c \ +	nv04_state_emit.c \ +	nv04_surface.c \ +	nv04_vbo.c + +C_SOURCES = \ +	$(COMMON_SOURCES) \ +	$(DRIVER_SOURCES) + +ASM_SOURCES =  + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/drivers/nv04/nv04_clear.c b/src/gallium/drivers/nv04/nv04_clear.c new file mode 100644 index 0000000000..01cacd36fe --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_clear.c @@ -0,0 +1,12 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "nv04_context.h" + +void +nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps, +	   unsigned clearValue) +{ +	pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); +} diff --git a/src/gallium/drivers/nv04/nv04_context.c b/src/gallium/drivers/nv04/nv04_context.c new file mode 100644 index 0000000000..852a8edf5f --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_context.c @@ -0,0 +1,107 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" +#include "pipe/p_util.h" + +#include "nv04_context.h" +#include "nv04_screen.h" + +static void +nv04_flush(struct pipe_context *pipe, unsigned flags, +	   struct pipe_fence_handle **fence) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	draw_flush(nv04->draw); + +	FIRE_RING(fence); +} + +static void +nv04_destroy(struct pipe_context *pipe) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	if (nv04->draw) +		draw_destroy(nv04->draw); + +	FREE(nv04); +} + +static void +nv04_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) +{ +} + +static boolean +nv04_init_hwctx(struct nv04_context *nv04) +{ +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_NOTIFY, 1); +	OUT_RING(0); +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_NOP, 1); +	OUT_RING(0); + +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1); +	OUT_RING(0x40182800); +//	OUT_RING(1<<20/*no cull*/); +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1); +//	OUT_RING(0x24|(1<<6)|(1<<8)); +	OUT_RING(0x120001a4); +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FORMAT, 1); +	OUT_RING(0x332213a1); +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FILTER, 1); +	OUT_RING(0x11001010); +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_COLORKEY, 1); +	OUT_RING(0x0); +//	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 1); +//	OUT_RING(SCREEN_OFFSET); +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR, 1); +	OUT_RING(0xff000000); + + + +	FIRE_RING (NULL); +	return TRUE; +} + +struct pipe_context * +nv04_create(struct pipe_screen *pscreen, unsigned pctx_id) +{ +	struct nv04_screen *screen = nv04_screen(pscreen); +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv04_context *nv04; +	struct nouveau_winsys *nvws = screen->nvws; + +	nv04 = CALLOC(1, sizeof(struct nv04_context)); +	if (!nv04) +		return NULL; +	nv04->screen = screen; +	nv04->pctx_id = pctx_id; + +	nv04->nvws = nvws; + +	nv04->pipe.winsys = ws; +	nv04->pipe.screen = pscreen; +	nv04->pipe.destroy = nv04_destroy; +	nv04->pipe.set_edgeflags = nv04_set_edgeflags; +	nv04->pipe.draw_arrays = nv04_draw_arrays; +	nv04->pipe.draw_elements = nv04_draw_elements; +	nv04->pipe.clear = nv04_clear; +	nv04->pipe.flush = nv04_flush; + +	nv04_init_surface_functions(nv04); +	nv04_init_state_functions(nv04); + +	nv04->draw = draw_create(); +	assert(nv04->draw); +	draw_wide_point_threshold(nv04->draw, 0.0); +	draw_wide_line_threshold(nv04->draw, 0.0); +	draw_enable_line_stipple(nv04->draw, FALSE); +	draw_enable_point_sprites(nv04->draw, FALSE); +	draw_set_rasterize_stage(nv04->draw, nv04_draw_vbuf_stage(nv04)); + +	nv04_init_hwctx(nv04); + +	return &nv04->pipe; +} + diff --git a/src/gallium/drivers/nv04/nv04_context.h b/src/gallium/drivers/nv04/nv04_context.h new file mode 100644 index 0000000000..5ba1d4ecdc --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_context.h @@ -0,0 +1,142 @@ +#ifndef __NV04_CONTEXT_H__ +#define __NV04_CONTEXT_H__ + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" + +#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \ +	struct nv04_screen *ctx = nv04->screen +#include "nouveau/nouveau_push.h" + +#include "nv04_state.h" + +#define NOUVEAU_ERR(fmt, args...) \ +	fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ +	fprintf(stderr, "nouveau: "fmt, ##args); + +#include "nv04_screen.h" + +#define NV04_NEW_VERTPROG	(1 << 1) +#define NV04_NEW_FRAGPROG	(1 << 2) +#define NV04_NEW_BLEND		(1 << 3) +#define NV04_NEW_RAST		(1 << 4) +#define NV04_NEW_CONTROL	(1 << 5) +#define NV04_NEW_VIEWPORT	(1 << 6) +#define NV04_NEW_SAMPLER	(1 << 7) + +struct nv04_context { +	struct pipe_context pipe; + +	struct nouveau_winsys *nvws; +	struct nv04_screen *screen; +	unsigned pctx_id; + +	struct draw_context *draw; + +	int chipset; +	struct nouveau_notifier *sync; + +	uint32_t dirty; + +	struct nv04_blend_state *blend; +	struct nv04_sampler_state *sampler[PIPE_MAX_SAMPLERS]; +	struct nv04_fragtex_state fragtex; +	struct nv04_rasterizer_state *rast; +	struct nv04_depth_stencil_alpha_state *dsa; + +	struct nv04_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; +	unsigned dirty_samplers; +	unsigned fp_samplers; +	unsigned vp_samplers; + +	uint32_t rt_enable; +	struct pipe_buffer *rt[4]; +	struct pipe_buffer *zeta; + +	struct { +		struct pipe_buffer *buffer; +		uint32_t format; +	} tex[16]; + +	unsigned vb_enable; +	struct { +		struct pipe_buffer *buffer; +		unsigned delta; +	} vb[16]; + +	struct vertex_info vertex_info; +	struct { +	 +		struct nouveau_resource *exec_heap; +		struct nouveau_resource *data_heap; + +		struct nv04_vertex_program *active; + +		struct nv04_vertex_program *current; +		struct pipe_buffer *constant_buf; +	} vertprog; + +	struct { +		struct nv04_fragment_program *active; + +		struct nv04_fragment_program *current; +		struct pipe_buffer *constant_buf; +	} fragprog; + +	struct pipe_vertex_buffer  vertex_buffer[PIPE_MAX_ATTRIBS]; +	unsigned num_vertex_buffers; +	unsigned num_vertex_elements; + +	struct pipe_viewport_state viewport; +}; + +static INLINE struct nv04_context * +nv04_context(struct pipe_context *pipe) +{ +	return (struct nv04_context *)pipe; +} + +extern void nv04_init_state_functions(struct nv04_context *nv04); +extern void nv04_init_surface_functions(struct nv04_context *nv04); +extern void nv04_init_miptree_functions(struct pipe_screen *screen); + +/* nv04_clear.c */ +extern void nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps, +		       unsigned clearValue); + +/* nv04_draw.c */ +extern struct draw_stage *nv04_draw_render_stage(struct nv04_context *nv04); + +/* nv04_fragprog.c */ +extern void nv04_fragprog_bind(struct nv04_context *, +			       struct nv04_fragment_program *); +extern void nv04_fragprog_destroy(struct nv04_context *, +				  struct nv04_fragment_program *); + +/* nv04_fragtex.c */ +extern void nv04_fragtex_bind(struct nv04_context *); + +/* nv04_prim_vbuf.c */ +struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 ); + +/* nv04_state.c and friends */ +extern void nv04_emit_hw_state(struct nv04_context *nv04); +extern void nv04_state_tex_update(struct nv04_context *nv04); + +/* nv04_vbo.c */ +extern boolean nv04_draw_arrays(struct pipe_context *, unsigned mode, +				unsigned start, unsigned count); +extern boolean nv04_draw_elements( struct pipe_context *pipe, +                    struct pipe_buffer *indexBuffer, +                    unsigned indexSize, +                    unsigned prim, unsigned start, unsigned count); + + +#endif diff --git a/src/gallium/drivers/nv04/nv04_fragprog.c b/src/gallium/drivers/nv04/nv04_fragprog.c new file mode 100644 index 0000000000..215974eec0 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_fragprog.c @@ -0,0 +1,22 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" + +#include "nv04_context.h" + +void +nv04_fragprog_bind(struct nv04_context *nv04, struct nv04_fragment_program *fp) +{ +} + +void +nv04_fragprog_destroy(struct nv04_context *nv04, +		      struct nv04_fragment_program *fp) +{ +} + diff --git a/src/gallium/drivers/nv04/nv04_fragtex.c b/src/gallium/drivers/nv04/nv04_fragtex.c new file mode 100644 index 0000000000..3db673cd2c --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_fragtex.c @@ -0,0 +1,100 @@ +#include "nv04_context.h" + +static INLINE int log2i(int i) +{ +	int r = 0; + +	if (i & 0xffff0000) { +		i >>= 16; +		r += 16; +	} +	if (i & 0x0000ff00) { +		i >>= 8; +		r += 8; +	} +	if (i & 0x000000f0) { +		i >>= 4; +		r += 4; +	} +	if (i & 0x0000000c) { +		i >>= 2; +		r += 2; +	} +	if (i & 0x00000002) { +		r += 1; +	} +	return r; +} + +#define _(m,tf)                                                                \ +{                                                                              \ +  PIPE_FORMAT_##m,                                                             \ +  NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_##tf,                                               \ +} + +struct nv04_texture_format { +	uint	pipe; +	int     format; +}; + +static struct nv04_texture_format +nv04_texture_formats[] = { +	_(A8R8G8B8_UNORM, A8R8G8B8), +	_(X8R8G8B8_UNORM, X8R8G8B8), +	_(A1R5G5B5_UNORM, A1R5G5B5), +	_(A4R4G4B4_UNORM, A4R4G4B4), +	_(L8_UNORM,       Y8      ), +	_(A8_UNORM,       Y8      ), +}; + +static uint32_t +nv04_fragtex_format(uint pipe_format) +{ +	struct nv04_texture_format *tf = nv04_texture_formats; +	char fs[128]; +	int i; + +	for (i=0; i< sizeof(nv04_texture_formats)/sizeof(nv04_texture_formats[0]); i++) { +		if (tf->pipe == pipe_format) +			return tf->format; +		tf++; +	} + +	pf_sprint_name(fs, pipe_format); +	NOUVEAU_ERR("unknown texture format %s\n", fs); +	return 0; +} + + +static void +nv04_fragtex_build(struct nv04_context *nv04, int unit) +{ +	struct nv04_miptree *nv04mt = nv04->tex_miptree[unit]; +	struct pipe_texture *pt = &nv04mt->base; + +	switch (pt->target) { +	case PIPE_TEXTURE_2D: +		break; +	default: +		NOUVEAU_ERR("Unknown target %d\n", pt->target); +		return; +	} + +	nv04->fragtex.format = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER  +		| NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER +		| nv04_fragtex_format(pt->format) +		| ( (pt->last_level + 1) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT ) +		| ( log2i(pt->width[0]) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT ) +		| ( log2i(pt->height[0]) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT ) +		| NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE +		| NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE +		; +} + + +void +nv04_fragtex_bind(struct nv04_context *nv04) +{ +	nv04_fragtex_build(nv04, 0); +} + diff --git a/src/gallium/drivers/nv04/nv04_miptree.c b/src/gallium/drivers/nv04/nv04_miptree.c new file mode 100644 index 0000000000..97f679731e --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_miptree.c @@ -0,0 +1,138 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "nv04_context.h" +#include "nv04_screen.h" + +static void +nv04_miptree_layout(struct nv04_miptree *nv04mt) +{ +	struct pipe_texture *pt = &nv04mt->base; +	uint width = pt->width[0], height = pt->height[0]; +	uint offset = 0; +	int nr_faces, l, f; + +	nr_faces = 1; + +	for (l = 0; l <= pt->last_level; l++) { +		pt->width[l] = width; +		pt->height[l] = height; + +		pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); +		pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); +		 +		nv04mt->level[l].pitch = pt->width[0] * pt->block.size; +		nv04mt->level[l].pitch = (nv04mt->level[l].pitch + 63) & ~63; + +		nv04mt->level[l].image_offset = +			CALLOC(nr_faces, sizeof(unsigned)); + +		width  = MAX2(1, width  >> 1); +		height = MAX2(1, height >> 1); + +	} + +	for (f = 0; f < nr_faces; f++) { +		for (l = 0; l <= pt->last_level; l++) { +			nv04mt->level[l].image_offset[f] = offset; +			offset += nv04mt->level[l].pitch * pt->height[l]; +		} +	} + +	nv04mt->total_size = offset; +} + +static struct pipe_texture * +nv04_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) +{ +	struct pipe_winsys *ws = screen->winsys; +	struct nv04_miptree *mt; + +	mt = MALLOC(sizeof(struct nv04_miptree)); +	if (!mt) +		return NULL; +	mt->base = *pt; +	mt->base.refcount = 1; +	mt->base.screen = screen; + +	nv04_miptree_layout(mt); + +	mt->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL, +					   mt->total_size); +	if (!mt->buffer) { +		FREE(mt); +		return NULL; +	} +	 +	return &mt->base; +} + +static void +nv04_miptree_release(struct pipe_screen *screen, struct pipe_texture **pt) +{ +	struct pipe_winsys *ws = screen->winsys; +	struct pipe_texture *mt = *pt; + +	*pt = NULL; +	if (--mt->refcount <= 0) { +		struct nv04_miptree *nv04mt = (struct nv04_miptree *)mt; +		int l; + +		pipe_buffer_reference(ws, &nv04mt->buffer, NULL); +		for (l = 0; l <= mt->last_level; l++) { +			if (nv04mt->level[l].image_offset) +				FREE(nv04mt->level[l].image_offset); +		} +		FREE(nv04mt); +	} +} + +static struct pipe_surface * +nv04_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +			 unsigned face, unsigned level, unsigned zslice, +			 unsigned flags) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv04_miptree *nv04mt = (struct nv04_miptree *)pt; +	struct pipe_surface *ps; + +	ps = ws->surface_alloc(ws); +	if (!ps) +		return NULL; +	pipe_buffer_reference(ws, &ps->buffer, nv04mt->buffer); +	ps->format = pt->format; +		ps->width = pt->width[level]; +	ps->height = pt->height[level]; +	ps->block = pt->block; +	ps->width = pt->width[level]; +	ps->height = pt->height[level]; +	ps->nblocksx = pt->nblocksx[level]; +	ps->nblocksy = pt->nblocksy[level]; +	ps->stride = nv04mt->level[level].pitch; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		ps->offset = nv04mt->level[level].image_offset[face]; +	} else { +		ps->offset = nv04mt->level[level].image_offset[0]; +	} + +	return ps; +} + +static void +nv04_miptree_surface_del(struct pipe_screen *pscreen, +			 struct pipe_surface **psurface) +{ +} + +void +nv04_init_miptree_functions(struct pipe_screen *pscreen) +{ +	pscreen->texture_create = nv04_miptree_create; +	pscreen->texture_release = nv04_miptree_release; +	pscreen->get_tex_surface = nv04_miptree_surface_new; +	pscreen->tex_surface_release = nv04_miptree_surface_del; +} + diff --git a/src/gallium/drivers/nv04/nv04_prim_vbuf.c b/src/gallium/drivers/nv04/nv04_prim_vbuf.c new file mode 100644 index 0000000000..d3963d1f59 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_prim_vbuf.c @@ -0,0 +1,308 @@ + +#include "draw/draw_vbuf.h" +#include "pipe/p_debug.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" +#include "pipe/p_winsys.h" + +#include "nv04_context.h" +#include "nv04_state.h" + +#define VERTEX_SIZE 40 +#define VERTEX_BUFFER_SIZE (4096*VERTEX_SIZE) // 4096 vertices of 40 bytes each + +/** + * Primitive renderer for nv04. + */ +struct nv04_vbuf_render { +	struct vbuf_render base; + +	struct nv04_context *nv04;    + +	/** Vertex buffer */ +	unsigned char* buffer; + +	/** Vertex size in bytes */ +	unsigned vertex_size; + +	/** Current primitive */ +	unsigned prim; +}; + + +/** + * Basically a cast wrapper. + */ +static INLINE struct nv04_vbuf_render * +nv04_vbuf_render( struct vbuf_render *render ) +{ +	assert(render); +	return (struct nv04_vbuf_render *)render; +} + + +static const struct vertex_info * +nv04_vbuf_render_get_vertex_info( struct vbuf_render *render ) +{ +	struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); +	struct nv04_context *nv04 = nv04_render->nv04; +	return &nv04->vertex_info; +} + + +static void * +nv04_vbuf_render_allocate_vertices( struct vbuf_render *render, +		ushort vertex_size, +		ushort nr_vertices ) +{ +	struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); + +	nv04_render->buffer = (unsigned char*) MALLOC(VERTEX_BUFFER_SIZE); +	assert(!nv04_render->buffer); + +	return nv04_render->buffer; +} + + +static boolean  +nv04_vbuf_render_set_primitive( struct vbuf_render *render,  +		unsigned prim ) +{ +	struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); + +	if (prim <= PIPE_PRIM_LINE_STRIP) +		return FALSE; + +	nv04_render->prim = prim; +	return TRUE; +} + +static INLINE void nv04_2triangles(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5) +{ +	BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49); +	OUT_RINGp(buffer + VERTEX_SIZE * v0,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v1,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v2,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v3,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v4,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v5,8); +	OUT_RING(0xFEDCBA); +} + +static INLINE void nv04_1triangle(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2) +{ +	BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25); +	OUT_RINGp(buffer + VERTEX_SIZE * v0,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v1,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v2,8); +	OUT_RING(0xFED); +} + +static INLINE void nv04_1quad(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3) +{ +	BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33); +	OUT_RINGp(buffer + VERTEX_SIZE * v0,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v1,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v2,8); +	OUT_RINGp(buffer + VERTEX_SIZE * v3,8); +	OUT_RING(0xFECEDC); +} + +static void nv04_vbuf_render_triangles_elts(struct nv04_vbuf_render * render, const ushort * indices, uint nr_indices) +{ +	unsigned char* buffer = render->buffer; +	struct nv04_context* nv04 = render->nv04; +	int i; + +	for( i=0; i< nr_indices-5; i+=6) +		nv04_2triangles(nv04, +				buffer, +				indices[i+0], +				indices[i+1], +				indices[i+2], +				indices[i+3], +				indices[i+4], +				indices[i+5] +			       ); +	if (i != nr_indices) +	{ +		nv04_1triangle(nv04, +				buffer, +				indices[i+0], +				indices[i+1], +				indices[i+2] +			       ); +		i+=3; +	} +	if (i != nr_indices) +		NOUVEAU_ERR("Houston, we have lost some vertices\n"); +} + +static void nv04_vbuf_render_tri_strip_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices) +{ +	const uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC}; +	unsigned char* buffer = render->buffer; +	struct nv04_context* nv04 = render->nv04; +	int i,j; + +	for(i = 0; i<nr_indices; i+=14)  +	{ +		int numvert = MIN2(16, nr_indices - i); +		int numtri = numvert - 2; +		if (numvert<3) +			break; + +		BEGIN_RING( fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), numvert*8 ); +		for(j = 0; j<numvert; j++) +			OUT_RINGp( buffer + VERTEX_SIZE * indices [i+j], 8 ); + +		BEGIN_RING_NI( fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri+1)/2 ); +		for(j = 0; j<numtri/2; j++ ) +			OUT_RING(striptbl[j]); +		if (numtri%2) +			OUT_RING(striptbl[numtri/2]&0xFFF); +	} +} + +static void nv04_vbuf_render_tri_fan_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices) +{ +	const uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0}; +	unsigned char* buffer = render->buffer; +	struct nv04_context* nv04 = render->nv04; +	int i,j; + +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), 8); +	OUT_RINGp(buffer + VERTEX_SIZE * indices[0], 8); + +	for(i = 1; i<nr_indices; i+=14) +	{ +		int numvert=MIN2(15, nr_indices - i); +		int numtri=numvert-2; +		if (numvert < 3) +			break; + +		BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1), numvert*8); + +		for(j=0;j<numvert;j++) +			OUT_RINGp( buffer + VERTEX_SIZE * indices[ i+j ], 8 ); + +		BEGIN_RING_NI(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri+1)/2); +		for(j = 0; j<numtri/2; j++) +			OUT_RING(fantbl[j]); +		if (numtri%2) +			OUT_RING(fantbl[numtri/2]&0xFFF); +	} +} + +static void nv04_vbuf_render_quads_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices) +{ +	unsigned char* buffer = render->buffer; +	struct nv04_context* nv04 = render->nv04; +	int i; + +	for(i = 0; i < nr_indices; i += 4) +		nv04_1quad(nv04, +				buffer, +				indices[i+0], +				indices[i+1], +				indices[i+2], +				indices[i+3] +			       ); +} + + +static void  +nv04_vbuf_render_draw( struct vbuf_render *render, +		const ushort *indices, +		uint nr_indices) +{ +	struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); + +	// emit the indices +	switch( nv04_render->prim ) +	{ +		case PIPE_PRIM_TRIANGLES: +			nv04_vbuf_render_triangles_elts(nv04_render, indices, nr_indices); +			break; +		case PIPE_PRIM_QUAD_STRIP: +		case PIPE_PRIM_TRIANGLE_STRIP: +			nv04_vbuf_render_tri_strip_elts(nv04_render, indices, nr_indices); +			break; +		case PIPE_PRIM_TRIANGLE_FAN: +		case PIPE_PRIM_POLYGON: +			nv04_vbuf_render_tri_fan_elts(nv04_render, indices, nr_indices); +			break; +		case PIPE_PRIM_QUADS: +			nv04_vbuf_render_quads_elts(nv04_render, indices, nr_indices); +			break; +		default: +			NOUVEAU_ERR("You have to implement primitive %d, young padawan\n", nv04_render->prim); +			break; +	} +} + + +static void +nv04_vbuf_render_release_vertices( struct vbuf_render *render, +		void *vertices,  +		unsigned vertex_size, +		unsigned vertices_used ) +{ +	struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); + +	free(nv04_render->buffer); +	nv04_render->buffer = NULL; +} + + +static void +nv04_vbuf_render_destroy( struct vbuf_render *render ) +{ +	struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); +	FREE(nv04_render); +} + + +/** + * Create a new primitive render. + */ +static struct vbuf_render * +nv04_vbuf_render_create( struct nv04_context *nv04 ) +{ +	struct nv04_vbuf_render *nv04_render = CALLOC_STRUCT(nv04_vbuf_render); + +	nv04_render->nv04 = nv04; + +	nv04_render->base.max_vertex_buffer_bytes = VERTEX_BUFFER_SIZE; +	nv04_render->base.max_indices = 65536;  +	nv04_render->base.get_vertex_info = nv04_vbuf_render_get_vertex_info; +	nv04_render->base.allocate_vertices = nv04_vbuf_render_allocate_vertices; +	nv04_render->base.set_primitive = nv04_vbuf_render_set_primitive; +	nv04_render->base.draw = nv04_vbuf_render_draw; +	nv04_render->base.release_vertices = nv04_vbuf_render_release_vertices; +	nv04_render->base.destroy = nv04_vbuf_render_destroy; + +	return &nv04_render->base; +} + + +/** + * Create a new primitive vbuf/render stage. + */ +struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 ) +{ +	struct vbuf_render *render; +	struct draw_stage *stage; + +	render = nv04_vbuf_render_create(nv04); +	if(!render) +		return NULL; + +	stage = draw_vbuf_stage( nv04->draw, render ); +	if(!stage) { +		render->destroy(render); +		return NULL; +	} + +	return stage; +} diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c new file mode 100644 index 0000000000..da09a3a5fe --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_screen.c @@ -0,0 +1,213 @@ +#include "pipe/p_screen.h" +#include "pipe/p_util.h" + +#include "nv04_context.h" +#include "nv04_screen.h" + +static const char * +nv04_screen_get_name(struct pipe_screen *screen) +{ +	struct nv04_screen *nv04screen = nv04_screen(screen); +	struct nouveau_device *dev = nv04screen->nvws->channel->device; +	static char buffer[128]; + +	snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); +	return buffer; +} + +static const char * +nv04_screen_get_vendor(struct pipe_screen *screen) +{ +	return "nouveau"; +} + +static int +nv04_screen_get_param(struct pipe_screen *screen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: +		return 1; +	case PIPE_CAP_NPOT_TEXTURES: +		return 0; +	case PIPE_CAP_TWO_SIDED_STENCIL: +		return 0; +	case PIPE_CAP_GLSL: +		return 0; +	case PIPE_CAP_S3TC: +		return 0; +	case PIPE_CAP_ANISOTROPIC_FILTER: +		return 0; +	case PIPE_CAP_POINT_SPRITE: +		return 0; +	case PIPE_CAP_MAX_RENDER_TARGETS: +		return 1; +	case PIPE_CAP_OCCLUSION_QUERY: +		return 0; +	case PIPE_CAP_TEXTURE_SHADOW_MAP: +		return 0; +	case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: +		return 10; +	case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: +		return 0; +	case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: +		return 0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0; +	} +} + +static float +nv04_screen_get_paramf(struct pipe_screen *screen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_LINE_WIDTH: +	case PIPE_CAP_MAX_LINE_WIDTH_AA: +		return 0.0; +	case PIPE_CAP_MAX_POINT_WIDTH: +	case PIPE_CAP_MAX_POINT_WIDTH_AA: +		return 0.0; +	case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: +		return 0.0; +	case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: +		return 0.0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0.0; +	} +} + +static boolean +nv04_screen_is_format_supported(struct pipe_screen *screen, +				enum pipe_format format, +				enum pipe_texture_target target, +				unsigned tex_usage, unsigned geom_flags) +{ +	if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM:  +		case PIPE_FORMAT_Z16_UNORM: +			return TRUE; +		default: +			break; +		} +	} else { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_X8R8G8B8_UNORM: +		case PIPE_FORMAT_A1R5G5B5_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM:  +		case PIPE_FORMAT_L8_UNORM: +		case PIPE_FORMAT_A8_UNORM: +			return TRUE; +		default: +			break; +		} +	} + +	return FALSE; +} + +static void * +nv04_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, +		 unsigned flags ) +{ +	struct pipe_winsys *ws = screen->winsys; +	void *map; + +	map = ws->buffer_map(ws, surface->buffer, flags); +	if (!map) +		return NULL; + +	return map + surface->offset; +} + +static void +nv04_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) +{ +	struct pipe_winsys *ws = screen->winsys; + +	ws->buffer_unmap(ws, surface->buffer); +} + +static void +nv04_screen_destroy(struct pipe_screen *pscreen) +{ +	struct nv04_screen *screen = nv04_screen(pscreen); +	struct nouveau_winsys *nvws = screen->nvws; + +	nvws->notifier_free(&screen->sync); +	nvws->grobj_free(&screen->fahrenheit); + +	FREE(pscreen); +} + +struct pipe_screen * +nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +{ +	struct nv04_screen *screen = CALLOC_STRUCT(nv04_screen); +	unsigned fahrenheit_class = 0, sub3d_class = 0; +	unsigned chipset = nvws->channel->device->chipset; +	int ret; + +	if (!screen) +		return NULL; +	screen->nvws = nvws; + +	if (chipset>=0x20) { +		fahrenheit_class = 0; +		sub3d_class = 0; +	} else if (chipset>=0x10) { +		fahrenheit_class = NV10_DX5_TEXTURED_TRIANGLE; +		sub3d_class = NV10_CONTEXT_SURFACES_3D; +	} else { +		fahrenheit_class=NV04_DX5_TEXTURED_TRIANGLE; +		sub3d_class = NV04_CONTEXT_SURFACES_3D; +	} + +	if (!fahrenheit_class) { +		NOUVEAU_ERR("Unknown nv04 chipset: nv%02x\n", chipset); +		return NULL; +	} + +	/* 3D object */ +	ret = nvws->grobj_alloc(nvws, fahrenheit_class, &screen->fahrenheit); +	if (ret) { +		NOUVEAU_ERR("Error creating 3D object: %d\n", ret); +		return NULL; +	} + +	/* 3D surface object */ +	ret = nvws->grobj_alloc(nvws, sub3d_class, &screen->context_surfaces_3d); +	if (ret) { +		NOUVEAU_ERR("Error creating 3D surface object: %d\n", ret); +		return NULL; +	} + +	/* Notifier for sync purposes */ +	ret = nvws->notifier_alloc(nvws, 1, &screen->sync); +	if (ret) { +		NOUVEAU_ERR("Error creating notifier object: %d\n", ret); +		nv04_screen_destroy(&screen->pipe); +		return NULL; +	} + +	screen->pipe.winsys = ws; +	screen->pipe.destroy = nv04_screen_destroy; + +	screen->pipe.get_name = nv04_screen_get_name; +	screen->pipe.get_vendor = nv04_screen_get_vendor; +	screen->pipe.get_param = nv04_screen_get_param; +	screen->pipe.get_paramf = nv04_screen_get_paramf; + +	screen->pipe.is_format_supported = nv04_screen_is_format_supported; + +	screen->pipe.surface_map = nv04_surface_map; +	screen->pipe.surface_unmap = nv04_surface_unmap; + +	nv04_screen_init_miptree_functions(&screen->pipe); + +	return &screen->pipe; +} + diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h new file mode 100644 index 0000000000..99a49cdf7a --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_screen.h @@ -0,0 +1,25 @@ +#ifndef __NV04_SCREEN_H__ +#define __NV04_SCREEN_H__ + +#include "pipe/p_screen.h" + +struct nv04_screen { +	struct pipe_screen pipe; + +	struct nouveau_winsys *nvws; +	unsigned chipset; + +	/* HW graphics objects */ +	struct nouveau_grobj *fahrenheit; +	struct nouveau_grobj *context_surfaces_3d; +	struct nouveau_notifier *sync; + +}; + +static INLINE struct nv04_screen * +nv04_screen(struct pipe_screen *screen) +{ +	return (struct nv04_screen *)screen; +} + +#endif diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c new file mode 100644 index 0000000000..668d875671 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_state.c @@ -0,0 +1,496 @@ +#include "draw/draw_context.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_shader_tokens.h" + +#include "tgsi/tgsi_parse.h" + +#include "nv04_context.h" +#include "nv04_state.h" + +static void * +nv04_blend_state_create(struct pipe_context *pipe, +			const struct pipe_blend_state *cso) +{ +	struct nv04_blend_state *cb; + +	cb = MALLOC(sizeof(struct nv04_blend_state)); + +	cb->b_enable = cso->blend_enable ? 1 : 0; +	cb->b_src = ((nvgl_blend_func(cso->alpha_src_factor)<<16) | +			 (nvgl_blend_func(cso->rgb_src_factor))); +	cb->b_dst = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) | +			 (nvgl_blend_func(cso->rgb_dst_factor))); +	 + +	return (void *)cb; +} + +static void +nv04_blend_state_bind(struct pipe_context *pipe, void *blend) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	nv04->blend = (struct nv04_blend_state*)blend; + +	nv04->dirty |= NV04_NEW_BLEND; +} + +static void +nv04_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	free(hwcso); +} + + +static INLINE unsigned +wrap_mode(unsigned wrap) { +	unsigned ret; + +	switch (wrap) { +	case PIPE_TEX_WRAP_REPEAT: +		ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT; +		break; +	case PIPE_TEX_WRAP_MIRROR_REPEAT: +		ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_EDGE: +		ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_BORDER: +		ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER; +		break; +	case PIPE_TEX_WRAP_CLAMP: +		ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP; +		break; +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: +	case PIPE_TEX_WRAP_MIRROR_CLAMP: +	default: +		NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); +		ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP; +	} +	return ret >> NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT; +} + +static void * +nv04_sampler_state_create(struct pipe_context *pipe, +			  const struct pipe_sampler_state *cso) +{ + +	struct nv04_sampler_state *ss; +	uint32_t filter = 0; + +	ss = MALLOC(sizeof(struct nv04_sampler_state)); + +	ss->format = ((wrap_mode(cso->wrap_s) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT) | +		    (wrap_mode(cso->wrap_t) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_SHIFT)); + +	if (cso->max_anisotropy > 1.0) { +		filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE | NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE; +	} + +	switch (cso->mag_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR; +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST; +		break; +	} + +	switch (cso->min_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; +			break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR; +			break; +		} +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; +		break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST; +			break; +		} +		break; +	} + +	ss->filter = filter; + +	return (void *)ss; +} + +static void +nv04_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv04->sampler[unit] = sampler[unit]; +		nv04->dirty_samplers |= (1 << unit); +	} +} + +static void +nv04_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	free(hwcso); +} + +static void +nv04_set_sampler_texture(struct pipe_context *pipe, unsigned nr, +			 struct pipe_texture **miptree) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv04->tex_miptree[unit] = (struct nv04_miptree *)miptree[unit]; +		nv04->dirty_samplers |= (1 << unit); +	} +} + +static void * +nv04_rasterizer_state_create(struct pipe_context *pipe, +			     const struct pipe_rasterizer_state *cso) +{ +	struct nv04_rasterizer_state *rs; + +	/*XXX: ignored: +	 * 	scissor +	 * 	points/lines (no hw support, emulated with tris in gallium) +	 */ +	rs = MALLOC(sizeof(struct nv04_rasterizer_state)); + +	rs->blend = cso->flatshade ? NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT : NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD; + +	return (void *)rs; +} + +static void +nv04_rasterizer_state_bind(struct pipe_context *pipe, void *rast) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	nv04->rast = (struct nv04_rasterizer_state*)rast; + +	draw_set_rasterizer_state(nv04->draw, (nv04->rast ? nv04->rast->templ : NULL)); + +	nv04->dirty |= NV04_NEW_RAST | NV04_NEW_BLEND; +} + +static void +nv04_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	free(hwcso); +} + +static INLINE uint32_t nv04_compare_func(uint32_t f) +{ +	switch ( f ) { +		case PIPE_FUNC_NEVER:		return 1; +		case PIPE_FUNC_LESS:		return 2; +		case PIPE_FUNC_EQUAL:		return 3; +		case PIPE_FUNC_LEQUAL:		return 4; +		case PIPE_FUNC_GREATER:		return 5; +		case PIPE_FUNC_NOTEQUAL:	return 6; +		case PIPE_FUNC_GEQUAL:		return 7; +		case PIPE_FUNC_ALWAYS:		return 8; +	} +	NOUVEAU_MSG("Unable to find the function\n"); +	return 0; +} + +static void * +nv04_depth_stencil_alpha_state_create(struct pipe_context *pipe, +			const struct pipe_depth_stencil_alpha_state *cso) +{ +	struct nv04_depth_stencil_alpha_state *hw; + +	hw = MALLOC(sizeof(struct nv04_depth_stencil_alpha_state)); + +	hw->control = float_to_ubyte(cso->alpha.ref); +	hw->control |= ( nv04_compare_func(cso->alpha.func) << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_SHIFT ); +	hw->control |= cso->alpha.enabled ? NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_TEST_ENABLE : 0; +	hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ORIGIN; +	hw->control |= cso->depth.enabled ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_SHIFT) : 0; +	hw->control |= ( nv04_compare_func(cso->depth.func)<< NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_SHIFT ); +	hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_SHIFT; // no culling, handled by the draw module +	hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE; +	hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE; +	hw->control |= cso->depth.writemask ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_SHIFT) : 0; +	hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_SHIFT; // integer zbuffer format + +	return (void *)hw; +} + +static void +nv04_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	nv04->dsa = hwcso; +	nv04->dirty |= NV04_NEW_CONTROL; +} + +static void +nv04_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	free(hwcso); +} + +static void * +nv04_vp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *templ) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	return draw_create_vertex_shader(nv04->draw, templ); +} + +static void +nv04_vp_state_bind(struct pipe_context *pipe, void *shader) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	draw_bind_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader); + +	nv04->dirty |= NV04_NEW_VERTPROG; +} + +static void +nv04_vp_state_delete(struct pipe_context *pipe, void *shader) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	draw_delete_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader); +} + +static void * +nv04_fp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv04_fragment_program *fp; + +	fp = CALLOC(1, sizeof(struct nv04_fragment_program)); +	fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + +	return (void *)fp; +} + +static void +nv04_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	struct nv04_fragment_program *fp = hwcso; + +	nv04->fragprog.current = fp; +	nv04->dirty |= NV04_NEW_FRAGPROG; +} + +static void +nv04_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	struct nv04_fragment_program *fp = hwcso; + +	nv04_fragprog_destroy(nv04, fp); +	free((void*)fp->pipe.tokens); +	free(fp); +} + +static void +nv04_set_blend_color(struct pipe_context *pipe, +		     const struct pipe_blend_color *bcol) +{ +} + +static void +nv04_set_clip_state(struct pipe_context *pipe, +		    const struct pipe_clip_state *clip) +{ +} + +static void +nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, +			 const struct pipe_constant_buffer *buf ) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	if (shader == PIPE_SHADER_VERTEX) { +		nv04->vertprog.constant_buf = buf->buffer; +		nv04->dirty |= NV04_NEW_VERTPROG; +	} else +	if (shader == PIPE_SHADER_FRAGMENT) { +		nv04->fragprog.constant_buf = buf->buffer; +		nv04->dirty |= NV04_NEW_FRAGPROG; +	} +} + +static void +nv04_set_framebuffer_state(struct pipe_context *pipe, +			   const struct pipe_framebuffer_state *fb) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	struct pipe_surface *rt, *zeta; +	uint32_t rt_format, w, h; +	int colour_format = 0, zeta_format = 0; + +	w = fb->cbufs[0]->width; +	h = fb->cbufs[0]->height; +	colour_format = fb->cbufs[0]->format; +	rt = fb->cbufs[0]; + +	if (fb->zsbuf) { +		if (colour_format) { +			assert(w == fb->zsbuf->width); +			assert(h == fb->zsbuf->height); +		} else { +			w = fb->zsbuf->width; +			h = fb->zsbuf->height; +		} + +		zeta_format = fb->zsbuf->format; +		zeta = fb->zsbuf; +	} + +	switch (colour_format) { +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case 0: +		rt_format = 0x108; +		break; +	case PIPE_FORMAT_R5G6B5_UNORM: +		rt_format = 0x103; +		break; +	default: +		assert(0); +	} + +	BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1); +	OUT_RING(rt_format); + +	/* FIXME pitches have to be aligned ! */ +	BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2); +	OUT_RING(rt->stride|(zeta->stride<<16)); +	OUT_RELOCl(rt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	if (fb->zsbuf) { +		BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1); +		OUT_RELOCl(zeta->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	} +} + +static void +nv04_set_polygon_stipple(struct pipe_context *pipe, +			 const struct pipe_poly_stipple *stipple) +{ +	NOUVEAU_ERR("line stipple hahaha\n"); +} + +static void +nv04_set_scissor_state(struct pipe_context *pipe, +		       const struct pipe_scissor_state *s) +{ +/*	struct nv04_context *nv04 = nv04_context(pipe); + +	// XXX +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_SCISSOR_HORIZ, 2); +	OUT_RING  (((s->maxx - s->minx) << 16) | s->minx); +	OUT_RING  (((s->maxy - s->miny) << 16) | s->miny);*/ +} + +static void +nv04_set_viewport_state(struct pipe_context *pipe, +			const struct pipe_viewport_state *viewport) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	nv04->viewport = *viewport; + +	draw_set_viewport_state(nv04->draw, &nv04->viewport); +} + +static void +nv04_set_vertex_buffers(struct pipe_context *pipe, unsigned count, +		       const struct pipe_vertex_buffer *buffers) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	draw_flush(nv04->draw); + +	memcpy(nv04->vertex_buffer, buffers, count * sizeof(buffers[0])); +	nv04->num_vertex_buffers = count; + +	draw_set_vertex_buffers(nv04->draw, count, buffers); +} + +static void +nv04_set_vertex_elements(struct pipe_context *pipe, unsigned count, +			const struct pipe_vertex_element *elements) +{ +	struct nv04_context *nv04 = nv04_context(pipe); + +	draw_flush(nv04->draw); + +	nv04->num_vertex_elements = count; +	draw_set_vertex_elements(nv04->draw, count, elements); +} + +void +nv04_init_state_functions(struct nv04_context *nv04) +{ +	nv04->pipe.create_blend_state = nv04_blend_state_create; +	nv04->pipe.bind_blend_state = nv04_blend_state_bind; +	nv04->pipe.delete_blend_state = nv04_blend_state_delete; + +	nv04->pipe.create_sampler_state = nv04_sampler_state_create; +	nv04->pipe.bind_sampler_states = nv04_sampler_state_bind; +	nv04->pipe.delete_sampler_state = nv04_sampler_state_delete; +	nv04->pipe.set_sampler_textures = nv04_set_sampler_texture; + +	nv04->pipe.create_rasterizer_state = nv04_rasterizer_state_create; +	nv04->pipe.bind_rasterizer_state = nv04_rasterizer_state_bind; +	nv04->pipe.delete_rasterizer_state = nv04_rasterizer_state_delete; + +	nv04->pipe.create_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_create; +	nv04->pipe.bind_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_bind; +	nv04->pipe.delete_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_delete; + +	nv04->pipe.create_vs_state = nv04_vp_state_create; +	nv04->pipe.bind_vs_state = nv04_vp_state_bind; +	nv04->pipe.delete_vs_state = nv04_vp_state_delete; + +	nv04->pipe.create_fs_state = nv04_fp_state_create; +	nv04->pipe.bind_fs_state = nv04_fp_state_bind; +	nv04->pipe.delete_fs_state = nv04_fp_state_delete; + +	nv04->pipe.set_blend_color = nv04_set_blend_color; +	nv04->pipe.set_clip_state = nv04_set_clip_state; +	nv04->pipe.set_constant_buffer = nv04_set_constant_buffer; +	nv04->pipe.set_framebuffer_state = nv04_set_framebuffer_state; +	nv04->pipe.set_polygon_stipple = nv04_set_polygon_stipple; +	nv04->pipe.set_scissor_state = nv04_set_scissor_state; +	nv04->pipe.set_viewport_state = nv04_set_viewport_state; + +	nv04->pipe.set_vertex_buffers = nv04_set_vertex_buffers; +	nv04->pipe.set_vertex_elements = nv04_set_vertex_elements; +} + diff --git a/src/gallium/drivers/nv04/nv04_state.h b/src/gallium/drivers/nv04/nv04_state.h new file mode 100644 index 0000000000..399f750dbe --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_state.h @@ -0,0 +1,71 @@ +#ifndef __NV04_STATE_H__ +#define __NV04_STATE_H__ + +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" + +struct nv04_blend_state { +	uint32_t b_enable; +	uint32_t b_src; +	uint32_t b_dst; +}; + +struct nv04_fragtex_state { +	uint32_t format; +}; + +struct nv04_sampler_state { +	uint32_t filter; +	uint32_t format; +}; + +struct nv04_depth_stencil_alpha_state { +	uint32_t control; +}; + +struct nv04_rasterizer_state { +	uint32_t blend; + +	const struct pipe_rasterizer_state *templ; +}; + +struct nv04_miptree { +	struct pipe_texture base; + +	struct pipe_buffer *buffer; +	uint total_size; + +	struct { +		uint pitch; +		uint *image_offset; +	} level[PIPE_MAX_TEXTURE_LEVELS]; +}; + +struct nv04_fragment_program_data { +	unsigned offset; +	unsigned index; +}; + +struct nv04_fragment_program { +	struct pipe_shader_state pipe; +	struct tgsi_shader_info info; + +	boolean translated; +	boolean on_hw; +	unsigned samplers; + +	uint32_t *insn; +	int       insn_len; + +	struct nv04_fragment_program_data *consts; +	unsigned nr_consts; + +	struct pipe_buffer *buffer; + +	uint32_t fp_control; +	uint32_t fp_reg_control; +}; + + + +#endif diff --git a/src/gallium/drivers/nv04/nv04_state_emit.c b/src/gallium/drivers/nv04/nv04_state_emit.c new file mode 100644 index 0000000000..0ad40a092e --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_state_emit.c @@ -0,0 +1,156 @@ +#include "nv04_context.h" +#include "nv04_state.h" + +static void nv04_vertex_layout(struct pipe_context* pipe) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	struct nv04_fragment_program *fp = nv04->fragprog.current; +	uint32_t src = 0; +	int i; +	struct vertex_info vinfo; + +	memset(&vinfo, 0, sizeof(vinfo)); + +	for (i = 0; i < fp->info.num_inputs; i++) { +		switch (i) { +			case TGSI_SEMANTIC_POSITION: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); +				break; +			case TGSI_SEMANTIC_COLOR: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); +				break; +			default: +			case TGSI_SEMANTIC_GENERIC: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); +				break; +			case TGSI_SEMANTIC_FOG: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); +				break; +		} +	} +	draw_compute_vertex_size(&vinfo); +} + +static uint32_t nv04_blend_func(uint32_t f) +{ +	switch ( f ) { +		case PIPE_BLENDFACTOR_ZERO:			return 0x1; +		case PIPE_BLENDFACTOR_ONE:			return 0x2; +		case PIPE_BLENDFACTOR_SRC_COLOR:		return 0x3; +		case PIPE_BLENDFACTOR_INV_SRC_COLOR:		return 0x4; +		case PIPE_BLENDFACTOR_SRC_ALPHA:		return 0x5; +		case PIPE_BLENDFACTOR_INV_SRC_ALPHA:		return 0x6; +		case PIPE_BLENDFACTOR_DST_ALPHA:		return 0x7; +		case PIPE_BLENDFACTOR_INV_DST_ALPHA:		return 0x8; +		case PIPE_BLENDFACTOR_DST_COLOR:		return 0x9; +		case PIPE_BLENDFACTOR_INV_DST_COLOR:		return 0xA; +		case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:	return 0xB; +	} +	NOUVEAU_MSG("Unable to find the blend function 0x%x\n",f); +	return 0; +} + +static void nv04_emit_control(struct nv04_context* nv04) +{ +	uint32_t control = nv04->dsa->control; + +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1); +	OUT_RING(control); +} + +static void nv04_emit_blend(struct nv04_context* nv04) +{ +	uint32_t blend; + +	blend=0x4; // texture MODULATE_ALPHA +	blend|=0x20; // alpha is MSB +	blend|=(2<<6); // flat shading +	blend|=(1<<8); // persp correct +	blend|=(0<<16); // no fog +	blend|=(nv04->blend->b_enable<<20); +	blend|=(nv04_blend_func(nv04->blend->b_src)<<24); +	blend|=(nv04_blend_func(nv04->blend->b_dst)<<28); + +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1); +	OUT_RING(blend); +} + +static void nv04_emit_sampler(struct nv04_context *nv04, int unit) +{ +	struct nv04_miptree *nv04mt = nv04->tex_miptree[unit]; +	struct pipe_texture *pt = &nv04mt->base; + +	BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 3); +	OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); +	OUT_RELOCd(nv04mt->buffer, (nv04->fragtex.format | nv04->sampler[unit]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); +	OUT_RING(nv04->sampler[unit]->filter); +} + +void +nv04_emit_hw_state(struct nv04_context *nv04) +{ +	int i; + +	if (nv04->dirty & NV04_NEW_VERTPROG) { +		//nv04_vertprog_bind(nv04, nv04->vertprog.current); +		nv04->dirty &= ~NV04_NEW_VERTPROG; +	} + +	if (nv04->dirty & NV04_NEW_FRAGPROG) { +		nv04_fragprog_bind(nv04, nv04->fragprog.current); +		/*XXX: clear NV04_NEW_FRAGPROG if no new program uploaded */ +		nv04->dirty_samplers |= (1<<10); +		nv04->dirty_samplers = 0; +	} + +	if (nv04->dirty & NV04_NEW_CONTROL) { +		nv04->dirty &= ~NV04_NEW_CONTROL; + +		BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1); +		OUT_RING(nv04->dsa->control); +	} + +	if (nv04->dirty & NV04_NEW_BLEND) { +		nv04->dirty &= ~NV04_NEW_BLEND; + +		nv04_emit_blend(nv04); +	} + +	if (nv04->dirty & NV04_NEW_SAMPLER) { +		nv04->dirty &= ~NV04_NEW_SAMPLER; + +		nv04_emit_sampler(nv04, 0); +	} + +	if (nv04->dirty & NV04_NEW_VIEWPORT) { +		nv04->dirty &= ~NV04_NEW_VIEWPORT; +//		nv04_state_emit_viewport(nv04); +	} + +	/* Emit relocs for every referenced buffer. +	 * This is to ensure the bufmgr has an accurate idea of how +	 * the buffer is used.  This isn't very efficient, but we don't +	 * seem to take a significant performance hit.  Will be improved +	 * at some point.  Vertex arrays are emitted by nv04_vbo.c +	 */ + +	/* Render target */ +/*	BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2); +	OUT_RING(rt->stride|(zeta->stride<<16)); +	OUT_RELOCl(rt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	if (fb->zsbuf) { +		BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1); +		OUT_RELOCl(zeta->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	}*/ + +	/* Texture images */ +	for (i = 0; i < 1; i++) { +		if (!(nv04->fp_samplers & (1 << i))) +			continue; +		struct nv04_miptree *nv04mt = nv04->tex_miptree[i]; +		BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 2); +		OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); +		OUT_RELOCd(nv04mt->buffer, (nv04->fragtex.format | nv04->sampler[i]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); +	} +} + diff --git a/src/gallium/drivers/nv04/nv04_surface.c b/src/gallium/drivers/nv04/nv04_surface.c new file mode 100644 index 0000000000..b13ebf9f9b --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_surface.c @@ -0,0 +1,65 @@ + +/************************************************************************** + *  + * Copyright 2003 Tungsten Graphics, 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, 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 TUNGSTEN GRAPHICS 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. + *  + **************************************************************************/ + +#include "nv04_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_winsys.h" +#include "pipe/p_inlines.h" +#include "util/p_tile.h" + +static void +nv04_surface_copy(struct pipe_context *pipe, unsigned do_flip, +		  struct pipe_surface *dest, unsigned destx, unsigned desty, +		  struct pipe_surface *src, unsigned srcx, unsigned srcy, +		  unsigned width, unsigned height) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	struct nouveau_winsys *nvws = nv04->nvws; + +	nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, +			   width, height); +} + +static void +nv04_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +		  unsigned destx, unsigned desty, unsigned width, +		  unsigned height, unsigned value) +{ +	struct nv04_context *nv04 = nv04_context(pipe); +	struct nouveau_winsys *nvws = nv04->nvws; + +	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +} + +void +nv04_init_surface_functions(struct nv04_context *nv04) +{ +	nv04->pipe.surface_copy = nv04_surface_copy; +	nv04->pipe.surface_fill = nv04_surface_fill; +} diff --git a/src/gallium/drivers/nv04/nv04_vbo.c b/src/gallium/drivers/nv04/nv04_vbo.c new file mode 100644 index 0000000000..fbfe0cf406 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_vbo.c @@ -0,0 +1,72 @@ +#include "draw/draw_context.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" + +#include "nv04_context.h" +#include "nv04_state.h" + +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_pushbuf.h" + +boolean nv04_draw_elements( struct pipe_context *pipe, +                    struct pipe_buffer *indexBuffer, +                    unsigned indexSize, +                    unsigned prim, unsigned start, unsigned count) +{ +	struct nv04_context *nv04 = nv04_context( pipe ); +	struct draw_context *draw = nv04->draw; +	unsigned i; + +	/* +	 * Map vertex buffers +	 */ +	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { +		if (nv04->vertex_buffer[i].buffer) { +			void *buf +				= pipe->winsys->buffer_map(pipe->winsys, +						nv04->vertex_buffer[i].buffer, +						PIPE_BUFFER_USAGE_CPU_READ); +			draw_set_mapped_vertex_buffer(draw, i, buf); +		} +	} +	/* Map index buffer, if present */ +	if (indexBuffer) { +		void *mapped_indexes +			= pipe->winsys->buffer_map(pipe->winsys, indexBuffer, +					PIPE_BUFFER_USAGE_CPU_READ); +		draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); +	} +	else { +		/* no index/element buffer */ +		draw_set_mapped_element_buffer(draw, 0, NULL); +	} + +	/* draw! */ +	draw_arrays(nv04->draw, prim, start, count); + +	/* +	 * unmap vertex/index buffers +	 */ +	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { +		if (nv04->vertex_buffer[i].buffer) { +			pipe->winsys->buffer_unmap(pipe->winsys, nv04->vertex_buffer[i].buffer); +			draw_set_mapped_vertex_buffer(draw, i, NULL); +		} +	} +	if (indexBuffer) { +		pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer); +		draw_set_mapped_element_buffer(draw, 0, NULL); +	} + +	return TRUE; +} + +boolean nv04_draw_arrays( struct pipe_context *pipe, +				 unsigned prim, unsigned start, unsigned count) +{ +	return nv04_draw_elements(pipe, NULL, 0, prim, start, count); +} + + + diff --git a/src/gallium/drivers/nv10/Makefile b/src/gallium/drivers/nv10/Makefile new file mode 100644 index 0000000000..4ba7ce586d --- /dev/null +++ b/src/gallium/drivers/nv10/Makefile @@ -0,0 +1,28 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nv10 + +DRIVER_SOURCES = \ +	nv10_clear.c \ +	nv10_context.c \ +	nv10_fragprog.c \ +	nv10_fragtex.c \ +	nv10_miptree.c \ +	nv10_prim_vbuf.c \ +	nv10_screen.c \ +	nv10_state.c \ +	nv10_state_emit.c \ +	nv10_surface.c \ +	nv10_vbo.c + +C_SOURCES = \ +	$(COMMON_SOURCES) \ +	$(DRIVER_SOURCES) + +ASM_SOURCES =  + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/drivers/nv10/nv10_clear.c b/src/gallium/drivers/nv10/nv10_clear.c new file mode 100644 index 0000000000..be7e09cf4b --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_clear.c @@ -0,0 +1,12 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "nv10_context.h" + +void +nv10_clear(struct pipe_context *pipe, struct pipe_surface *ps, +	   unsigned clearValue) +{ +	pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); +} diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c new file mode 100644 index 0000000000..9fcd0b0fc3 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_context.c @@ -0,0 +1,297 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" +#include "pipe/p_util.h" + +#include "nv10_context.h" +#include "nv10_screen.h" + +static void +nv10_flush(struct pipe_context *pipe, unsigned flags, +	   struct pipe_fence_handle **fence) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	draw_flush(nv10->draw); + +	FIRE_RING(fence); +} + +static void +nv10_destroy(struct pipe_context *pipe) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	if (nv10->draw) +		draw_destroy(nv10->draw); + +	FREE(nv10); +} + +static void nv10_init_hwctx(struct nv10_context *nv10) +{ +	struct nv10_screen *screen = nv10->screen; +	struct nouveau_winsys *nvws = screen->nvws; +	int i; +	float projectionmatrix[16]; + +	BEGIN_RING(celsius, NV10TCL_DMA_NOTIFY, 1); +	OUT_RING  (screen->sync->handle); +	BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY0, 2); +	OUT_RING  (nvws->channel->vram->handle); +	OUT_RING  (nvws->channel->gart->handle); +	BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY2, 2); +	OUT_RING  (nvws->channel->vram->handle); +	OUT_RING  (nvws->channel->vram->handle); + +	BEGIN_RING(celsius, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 2); +	OUT_RING  (0); +	OUT_RING  (0); + +	BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1); +	OUT_RING  ((0x7ff<<16)|0x800); +	BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1); +	OUT_RING  ((0x7ff<<16)|0x800); + +	for (i=1;i<8;i++) { +		BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1); +		OUT_RING  (0); +		BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(i), 1); +		OUT_RING  (0); +	} + +	BEGIN_RING(celsius, 0x290, 1); +	OUT_RING  ((0x10<<16)|1); +	BEGIN_RING(celsius, 0x3f4, 1); +	OUT_RING  (0); + +	BEGIN_RING(celsius, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	if (nv10->screen->celsius->grclass != NV10TCL) { +		/* For nv11, nv17 */ +		BEGIN_RING(celsius, 0x120, 3); +		OUT_RING  (0); +		OUT_RING  (1); +		OUT_RING  (2); + +		BEGIN_RING(celsius, NV10TCL_NOP, 1); +		OUT_RING  (0); +	} + +	BEGIN_RING(celsius, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	/* Set state */ +	BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 2); +	OUT_RING  (0x207); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_TX_ENABLE(0), 2); +	OUT_RING  (0); +	OUT_RING  (0); + +	BEGIN_RING(celsius, NV10TCL_RC_IN_ALPHA(0), 12); +	OUT_RING  (0x30141010); +	OUT_RING  (0); +	OUT_RING  (0x20040000); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0x00000c00); +	OUT_RING  (0); +	OUT_RING  (0x00000c00); +	OUT_RING  (0x18000000); +	OUT_RING  (0x300e0300); +	OUT_RING  (0x0c091c80); + +	BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 2); +	OUT_RING  (1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_VERTEX_WEIGHT_ENABLE, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_SRC, 4); +	OUT_RING  (1); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0x8006); +	BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 8); +	OUT_RING  (0xff); +	OUT_RING  (0x207); +	OUT_RING  (0); +	OUT_RING  (0xff); +	OUT_RING  (0x1e00); +	OUT_RING  (0x1e00); +	OUT_RING  (0x1e00); +	OUT_RING  (0x1d01); +	BEGIN_RING(celsius, NV10TCL_NORMALIZE_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_LIGHT_MODEL, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_COLOR_CONTROL, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_ENABLED_LIGHTS, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1); +	OUT_RING  (0x201); +	BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1); +	OUT_RING  (8); +	BEGIN_RING(celsius, NV10TCL_POINT_PARAMETERS_ENABLE, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_LINE_WIDTH, 1); +	OUT_RING  (8); +	BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2); +	OUT_RING  (0x1b02); +	OUT_RING  (0x1b02); +	BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2); +	OUT_RING  (0x405); +	OUT_RING  (0x901); +	BEGIN_RING(celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_CLIP_PLANE_ENABLE(0), 8); +	for (i=0;i<8;i++) { +		OUT_RING  (0); +	} +	BEGIN_RING(celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3); +	OUT_RING  (0x3fc00000);	/* -1.50 */ +	OUT_RING  (0xbdb8aa0a);	/* -0.09 */ +	OUT_RING  (0);		/*  0.00 */ + +	BEGIN_RING(celsius, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	BEGIN_RING(celsius, NV10TCL_FOG_MODE, 2); +	OUT_RING  (0x802); +	OUT_RING  (2); +	/* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when +	 * using texturing, except when using the texture matrix +	 */ +	BEGIN_RING(celsius, NV10TCL_VIEW_MATRIX_ENABLE, 1); +	OUT_RING  (6); +	BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1); +	OUT_RING  (0x01010101); + +	/* Set vertex component */ +	BEGIN_RING(celsius, NV10TCL_VERTEX_COL_4F_R, 4); +	OUT_RINGf (1.0); +	OUT_RINGf (1.0); +	OUT_RINGf (1.0); +	OUT_RINGf (1.0); +	BEGIN_RING(celsius, NV10TCL_VERTEX_COL2_3F_R, 3); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(celsius, NV10TCL_VERTEX_NOR_3F_X, 3); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RINGf (1.0); +	BEGIN_RING(celsius, NV10TCL_VERTEX_TX0_4F_S, 4); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (1.0); +	BEGIN_RING(celsius, NV10TCL_VERTEX_TX1_4F_S, 4); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (1.0); +	BEGIN_RING(celsius, NV10TCL_VERTEX_FOG_1F, 1); +	OUT_RINGf (0.0); +	BEGIN_RING(celsius, NV10TCL_EDGEFLAG_ENABLE, 1); +	OUT_RING  (1); + +	memset(projectionmatrix, 0, sizeof(projectionmatrix)); +	BEGIN_RING(celsius, NV10TCL_PROJECTION_MATRIX(0), 16); +	projectionmatrix[0*4+0] = 1.0; +	projectionmatrix[1*4+1] = 1.0; +	projectionmatrix[2*4+2] = 1.0; +	projectionmatrix[3*4+3] = 1.0; +	for (i=0;i<16;i++) { +		OUT_RINGf  (projectionmatrix[i]); +	} + +	BEGIN_RING(celsius, NV10TCL_DEPTH_RANGE_NEAR, 2); +	OUT_RING  (0.0); +	OUT_RINGf  (16777216.0); + +	BEGIN_RING(celsius, NV10TCL_VIEWPORT_SCALE_X, 4); +	OUT_RINGf  (-2048.0); +	OUT_RINGf  (-2048.0); +	OUT_RINGf  (16777215.0 * 0.5); +	OUT_RING  (0); + +	FIRE_RING (NULL); +} + +static void +nv10_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) +{ +} + +struct pipe_context * +nv10_create(struct pipe_screen *pscreen, unsigned pctx_id) +{ +	struct nv10_screen *screen = nv10_screen(pscreen); +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv10_context *nv10; +	struct nouveau_winsys *nvws = screen->nvws; + +	nv10 = CALLOC(1, sizeof(struct nv10_context)); +	if (!nv10) +		return NULL; +	nv10->screen = screen; +	nv10->pctx_id = pctx_id; + +	nv10->nvws = nvws; + +	nv10->pipe.winsys = ws; +	nv10->pipe.screen = pscreen; +	nv10->pipe.destroy = nv10_destroy; +	nv10->pipe.set_edgeflags = nv10_set_edgeflags; +	nv10->pipe.draw_arrays = nv10_draw_arrays; +	nv10->pipe.draw_elements = nv10_draw_elements; +	nv10->pipe.clear = nv10_clear; +	nv10->pipe.flush = nv10_flush; + +	nv10_init_surface_functions(nv10); +	nv10_init_state_functions(nv10); + +	nv10->draw = draw_create(); +	assert(nv10->draw); +	draw_set_rasterize_stage(nv10->draw, nv10_draw_vbuf_stage(nv10)); + +	nv10_init_hwctx(nv10); + +	return &nv10->pipe; +} + diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h new file mode 100644 index 0000000000..2bdba53db8 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_context.h @@ -0,0 +1,149 @@ +#ifndef __NV10_CONTEXT_H__ +#define __NV10_CONTEXT_H__ + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" + +#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \ +	struct nv10_screen *ctx = nv10->screen +#include "nouveau/nouveau_push.h" + +#include "nv10_state.h" + +#define NOUVEAU_ERR(fmt, args...) \ +	fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ +	fprintf(stderr, "nouveau: "fmt, ##args); + +#define NV10_NEW_VERTPROG	(1 << 0) +#define NV10_NEW_FRAGPROG	(1 << 1) +#define NV10_NEW_VTXARRAYS	(1 << 2) +#define NV10_NEW_BLEND		(1 << 3) +#define NV10_NEW_BLENDCOL	(1 << 4) +#define NV10_NEW_RAST 		(1 << 5) +#define NV10_NEW_DSA  		(1 << 6) +#define NV10_NEW_VIEWPORT	(1 << 7) +#define NV10_NEW_SCISSOR	(1 << 8) +#define NV10_NEW_FRAMEBUFFER	(1 << 9) + +#include "nv10_screen.h" + +struct nv10_context { +	struct pipe_context pipe; + +	struct nouveau_winsys *nvws; +	struct nv10_screen *screen; +	unsigned pctx_id; + +	struct draw_context *draw; + +	uint32_t dirty; + +	struct nv10_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; +	struct nv10_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; +	unsigned dirty_samplers; +	unsigned fp_samplers; +	unsigned vp_samplers; + +	uint32_t rt_enable; +	struct pipe_buffer *rt[4]; +	struct pipe_buffer *zeta; +	uint32_t lma_offset; + +	struct nv10_blend_state *blend; +	struct pipe_blend_color *blend_color; +	struct nv10_rasterizer_state *rast; +	struct nv10_depth_stencil_alpha_state *dsa; +	struct pipe_viewport_state *viewport; +	struct pipe_scissor_state *scissor; +	struct pipe_framebuffer_state *framebuffer; + +	//struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; +	float *constbuf[PIPE_SHADER_TYPES][32][4]; +	unsigned constbuf_nr[PIPE_SHADER_TYPES]; + +	struct vertex_info vertex_info; + +	struct { +		struct pipe_buffer *buffer; +		uint32_t format; +	} tex[2]; + +	unsigned vb_enable; +	struct { +		struct pipe_buffer *buffer; +		unsigned delta; +	} vb[16]; + +/*	struct { +	 +		struct nouveau_resource *exec_heap; +		struct nouveau_resource *data_heap; + +		struct nv10_vertex_program *active; + +		struct nv10_vertex_program *current; +	} vertprog; +*/ +	struct { +		struct nv10_fragment_program *active; + +		struct nv10_fragment_program *current; +		struct pipe_buffer *constant_buf; +	} fragprog; + +	struct pipe_vertex_buffer  vtxbuf[PIPE_MAX_ATTRIBS]; +	struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; +}; + +static INLINE struct nv10_context * +nv10_context(struct pipe_context *pipe) +{ +	return (struct nv10_context *)pipe; +} + +extern void nv10_init_state_functions(struct nv10_context *nv10); +extern void nv10_init_surface_functions(struct nv10_context *nv10); + +extern void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen); + +/* nv10_clear.c */ +extern void nv10_clear(struct pipe_context *pipe, struct pipe_surface *ps, +		       unsigned clearValue); + +/* nv10_draw.c */ +extern struct draw_stage *nv10_draw_render_stage(struct nv10_context *nv10); + +/* nv10_fragprog.c */ +extern void nv10_fragprog_bind(struct nv10_context *, +			       struct nv10_fragment_program *); +extern void nv10_fragprog_destroy(struct nv10_context *, +				  struct nv10_fragment_program *); + +/* nv10_fragtex.c */ +extern void nv10_fragtex_bind(struct nv10_context *); + +/* nv10_prim_vbuf.c */ +struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 ); +extern void nv10_vtxbuf_bind(struct nv10_context* nv10); + +/* nv10_state.c and friends */ +extern void nv10_emit_hw_state(struct nv10_context *nv10); +extern void nv10_state_tex_update(struct nv10_context *nv10); + +/* nv10_vbo.c */ +extern boolean nv10_draw_arrays(struct pipe_context *, unsigned mode, +				unsigned start, unsigned count); +extern boolean nv10_draw_elements( struct pipe_context *pipe, +                    struct pipe_buffer *indexBuffer, +                    unsigned indexSize, +                    unsigned prim, unsigned start, unsigned count); + + +#endif diff --git a/src/gallium/drivers/nv10/nv10_fragprog.c b/src/gallium/drivers/nv10/nv10_fragprog.c new file mode 100644 index 0000000000..137de9d53e --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_fragprog.c @@ -0,0 +1,22 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" + +#include "nv10_context.h" + +void +nv10_fragprog_bind(struct nv10_context *nv10, struct nv10_fragment_program *fp) +{ +} + +void +nv10_fragprog_destroy(struct nv10_context *nv10, +		      struct nv10_fragment_program *fp) +{ +} + diff --git a/src/gallium/drivers/nv10/nv10_fragtex.c b/src/gallium/drivers/nv10/nv10_fragtex.c new file mode 100644 index 0000000000..238634d0bb --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_fragtex.c @@ -0,0 +1,149 @@ +#include "nv10_context.h" + +static INLINE int log2i(int i) +{ +	int r = 0; + +	if (i & 0xffff0000) { +		i >>= 16; +		r += 16; +	} +	if (i & 0x0000ff00) { +		i >>= 8; +		r += 8; +	} +	if (i & 0x000000f0) { +		i >>= 4; +		r += 4; +	} +	if (i & 0x0000000c) { +		i >>= 2; +		r += 2; +	} +	if (i & 0x00000002) { +		r += 1; +	} +	return r; +} + +#define _(m,tf)                                                                \ +{                                                                              \ +  TRUE,                                                                        \ +  PIPE_FORMAT_##m,                                                             \ +  NV10TCL_TX_FORMAT_FORMAT_##tf,                                               \ +} + +struct nv10_texture_format { +	boolean defined; +	uint	pipe; +	int     format; +}; + +static struct nv10_texture_format +nv10_texture_formats[] = { +	_(A8R8G8B8_UNORM, A8R8G8B8), +	_(A1R5G5B5_UNORM, A1R5G5B5), +	_(A4R4G4B4_UNORM, A4R4G4B4), +	_(L8_UNORM      , L8      ), +	_(A8_UNORM      , A8      ), +	_(A8L8_UNORM    , A8L8    ), +//	_(RGB_DXT1      , DXT1,   ), +//	_(RGBA_DXT1     , DXT1,   ), +//	_(RGBA_DXT3     , DXT3,   ), +//	_(RGBA_DXT5     , DXT5,   ), +	{}, +}; + +static struct nv10_texture_format * +nv10_fragtex_format(uint pipe_format) +{ +	struct nv10_texture_format *tf = nv10_texture_formats; + +	while (tf->defined) { +		if (tf->pipe == pipe_format) +			return tf; +		tf++; +	} + +	return NULL; +} + + +static void +nv10_fragtex_build(struct nv10_context *nv10, int unit) +{ +#if 0 +	struct nv10_sampler_state *ps = nv10->tex_sampler[unit]; +	struct nv10_miptree *nv10mt = nv10->tex_miptree[unit]; +	struct pipe_texture *pt = &nv10mt->base; +	struct nv10_texture_format *tf; +	uint32_t txf, txs, txp; + +	tf = nv10_fragtex_format(pt->format); +	if (!tf || !tf->defined) { +		NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format); +		return; +	} + +	txf  = tf->format << 8; +	txf |= (pt->last_level + 1) << 16; +	txf |= log2i(pt->width[0]) << 20; +	txf |= log2i(pt->height[0]) << 24; +	txf |= log2i(pt->depth[0]) << 28; +	txf |= 8; + +	switch (pt->target) { +	case PIPE_TEXTURE_CUBE: +		txf |= NV10TCL_TX_FORMAT_CUBE_MAP; +		/* fall-through */ +	case PIPE_TEXTURE_2D: +		txf |= (2<<4); +		break; +	case PIPE_TEXTURE_1D: +		txf |= (1<<4); +		break; +	default: +		NOUVEAU_ERR("Unknown target %d\n", pt->target); +		return; +	} + +	BEGIN_RING(celsius, NV10TCL_TX_OFFSET(unit), 8); +	OUT_RELOCl(nv10mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); +	OUT_RELOCd(nv10mt->buffer,txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); +	OUT_RING  (ps->wrap); +	OUT_RING  (0x40000000); /* enable */ +	OUT_RING  (txs); +	OUT_RING  (ps->filt | 0x2000 /* magic */); +	OUT_RING  ((pt->width[0] << 16) | pt->height[0]); +	OUT_RING  (ps->bcol); +#endif +} + +void +nv10_fragtex_bind(struct nv10_context *nv10) +{ +#if 0 +	struct nv10_fragment_program *fp = nv10->fragprog.active; +	unsigned samplers, unit; + +	samplers = nv10->fp_samplers & ~fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		BEGIN_RING(celsius, NV10TCL_TX_ENABLE(unit), 1); +		OUT_RING  (0); +	} + +	samplers = nv10->dirty_samplers & fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		nv10_fragtex_build(nv10, unit); +	} + +	nv10->fp_samplers = fp->samplers; +#endif +} + diff --git a/src/gallium/drivers/nv10/nv10_miptree.c b/src/gallium/drivers/nv10/nv10_miptree.c new file mode 100644 index 0000000000..9a68df2925 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_miptree.c @@ -0,0 +1,149 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "nv10_context.h" +#include "nv10_screen.h" + +static void +nv10_miptree_layout(struct nv10_miptree *nv10mt) +{ +	struct pipe_texture *pt = &nv10mt->base; +	boolean swizzled = FALSE; +	uint width = pt->width[0], height = pt->height[0]; +	uint offset = 0; +	int nr_faces, l, f; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		nr_faces = 6; +	} else { +		nr_faces = 1; +	} +	 +	for (l = 0; l <= pt->last_level; l++) { +		pt->width[l] = width; +		pt->height[l] = height; +		pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); +		pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); + +		if (swizzled) +			nv10mt->level[l].pitch = pt->nblocksx[l] * pt->block.size; +		else +			nv10mt->level[l].pitch = pt->nblocksx[0] * pt->block.size; +		nv10mt->level[l].pitch = (nv10mt->level[l].pitch + 63) & ~63; + +		nv10mt->level[l].image_offset = +			CALLOC(nr_faces, sizeof(unsigned)); + +		width  = MAX2(1, width  >> 1); +		height = MAX2(1, height >> 1); + +	} + +	for (f = 0; f < nr_faces; f++) { +		for (l = 0; l <= pt->last_level; l++) { +			nv10mt->level[l].image_offset[f] = offset; +			offset += nv10mt->level[l].pitch * pt->height[l]; +		} +	} + +	nv10mt->total_size = offset; +} + +static struct pipe_texture * +nv10_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) +{ +	struct pipe_winsys *ws = screen->winsys; +	struct nv10_miptree *mt; + +	mt = MALLOC(sizeof(struct nv10_miptree)); +	if (!mt) +		return NULL; +	mt->base = *pt; +	mt->base.refcount = 1; +	mt->base.screen = screen; + +	nv10_miptree_layout(mt); + +	mt->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL, +					   mt->total_size); +	if (!mt->buffer) { +		FREE(mt); +		return NULL; +	} +	 +	return &mt->base; +} + +static void +nv10_miptree_release(struct pipe_screen *screen, struct pipe_texture **pt) +{ +	struct pipe_winsys *ws = screen->winsys; +	struct pipe_texture *mt = *pt; + +	*pt = NULL; +	if (--mt->refcount <= 0) { +		struct nv10_miptree *nv10mt = (struct nv10_miptree *)mt; +		int l; + +		pipe_buffer_reference(ws, &nv10mt->buffer, NULL); +		for (l = 0; l <= mt->last_level; l++) { +			if (nv10mt->level[l].image_offset) +				FREE(nv10mt->level[l].image_offset); +		} +		FREE(nv10mt); +	} +} + +static void +nv10_miptree_update(struct pipe_context *pipe, struct pipe_texture *mt, +		    uint face, uint levels) +{ +} + + +static struct pipe_surface * +nv10_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, +			 unsigned face, unsigned level, unsigned zslice, +			 unsigned flags) +{ +	struct pipe_winsys *ws = screen->winsys; +	struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt; +	struct pipe_surface *ps; + +	ps = ws->surface_alloc(ws); +	if (!ps) +		return NULL; +	pipe_buffer_reference(ws, &ps->buffer, nv10mt->buffer); +	ps->format = pt->format; +	ps->width = pt->width[level]; +	ps->height = pt->height[level]; +	ps->block = pt->block; +	ps->nblocksx = pt->nblocksx[level]; +	ps->nblocksy = pt->nblocksy[level]; +	ps->stride = nv10mt->level[level].pitch; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		ps->offset = nv10mt->level[level].image_offset[face]; +	} else { +		ps->offset = nv10mt->level[level].image_offset[0]; +	} + +	return ps; +} + +static void +nv10_miptree_surface_release(struct pipe_screen *screen, +			     struct pipe_surface **surface) +{ +} + +void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen) +{ +	pscreen->texture_create = nv10_miptree_create; +	pscreen->texture_release = nv10_miptree_release; +	pscreen->get_tex_surface = nv10_miptree_surface_get; +	pscreen->tex_surface_release = nv10_miptree_surface_release; +} + diff --git a/src/gallium/drivers/nv10/nv10_prim_vbuf.c b/src/gallium/drivers/nv10/nv10_prim_vbuf.c new file mode 100644 index 0000000000..930536b946 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_prim_vbuf.c @@ -0,0 +1,240 @@ +/************************************************************************** + *  + * Copyright 2007 Tungsten Graphics, 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, 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 TUNGSTEN GRAPHICS 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. + *  + **************************************************************************/ + +/** + * \file + * Build post-transformation, post-clipping vertex buffers and element + * lists by hooking into the end of the primitive pipeline and + * manipulating the vertex_id field in the vertex headers. + * + * XXX: work in progress  + *  + * \author José Fonseca <jrfonseca@tungstengraphics.com> + * \author Keith Whitwell <keith@tungstengraphics.com> + */ + + +#include "draw/draw_vbuf.h" +#include "pipe/p_debug.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" +#include "pipe/p_winsys.h" + +#include "nv10_context.h" +#include "nv10_state.h" + + +/** + * Primitive renderer for nv10. + */ +struct nv10_vbuf_render { +	struct vbuf_render base; + +	struct nv10_context *nv10;    + +	/** Vertex buffer */ +	struct pipe_buffer* buffer; + +	/** Vertex size in bytes */ +	unsigned vertex_size; + +	/** Hardware primitive */ +	unsigned hwprim; +}; + + +void nv10_vtxbuf_bind( struct nv10_context* nv10 ) +{ +	int i; +	for(i = 0; i < 8; i++) { +		BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(i), 1); +		OUT_RING(0/*nv10->vtxbuf*/); +		BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(i) ,1); +		OUT_RING(0/*XXX*/); +	} +} + +/** + * Basically a cast wrapper. + */ +static INLINE struct nv10_vbuf_render * +nv10_vbuf_render( struct vbuf_render *render ) +{ +	assert(render); +	return (struct nv10_vbuf_render *)render; +} + + +static const struct vertex_info * +nv10_vbuf_render_get_vertex_info( struct vbuf_render *render ) +{ +	struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); +	struct nv10_context *nv10 = nv10_render->nv10; + +	nv10_emit_hw_state(nv10); + +	return &nv10->vertex_info; +} + + +static void * +nv10_vbuf_render_allocate_vertices( struct vbuf_render *render, +		ushort vertex_size, +		ushort nr_vertices ) +{ +	struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); +	struct nv10_context *nv10 = nv10_render->nv10; +	struct pipe_winsys *winsys = nv10->pipe.winsys; +	size_t size = (size_t)vertex_size * (size_t)nr_vertices; + +	assert(!nv10_render->buffer); +	nv10_render->buffer = winsys->buffer_create(winsys, 64, PIPE_BUFFER_USAGE_VERTEX, size); + +	nv10->dirty |= NV10_NEW_VTXARRAYS; + +	return winsys->buffer_map(winsys,  +			nv10_render->buffer,  +			PIPE_BUFFER_USAGE_CPU_WRITE); +} + + +static void  +nv10_vbuf_render_set_primitive( struct vbuf_render *render,  +		unsigned prim ) +{ +	struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); +	nv10_render->hwprim = prim + 1; +} + + +static void  +nv10_vbuf_render_draw( struct vbuf_render *render, +		const ushort *indices, +		uint nr_indices) +{ +	struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); +	struct nv10_context *nv10 = nv10_render->nv10; +	int push, i; + +	nv10_emit_hw_state(nv10); + +	BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1); +	OUT_RELOCl(nv10_render->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); + +	BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); +	OUT_RING(nv10_render->hwprim); + +	if (nr_indices & 1) { +		BEGIN_RING(celsius, NV10TCL_VB_ELEMENT_U32, 1); +		OUT_RING  (indices[0]); +		indices++; nr_indices--; +	} + +	while (nr_indices) { +		// XXX too big/small ? check the size +		push = MIN2(nr_indices, 1200 * 2); + +		BEGIN_RING_NI(celsius, NV10TCL_VB_ELEMENT_U16, push >> 1); +		for (i = 0; i < push; i+=2) +			OUT_RING((indices[i+1] << 16) | indices[i]); + +		nr_indices -= push; +		indices  += push; +	} + +	BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); +	OUT_RING  (0); +} + + +static void +nv10_vbuf_render_release_vertices( struct vbuf_render *render, +		void *vertices,  +		unsigned vertex_size, +		unsigned vertices_used ) +{ +	struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); +	struct nv10_context *nv10 = nv10_render->nv10; +	struct pipe_winsys *winsys = nv10->pipe.winsys; + +	assert(nv10_render->buffer); +	winsys->buffer_unmap(winsys, nv10_render->buffer); +	pipe_buffer_reference(winsys, &nv10_render->buffer, NULL); +} + + +static void +nv10_vbuf_render_destroy( struct vbuf_render *render ) +{ +	struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); +	FREE(nv10_render); +} + + +/** + * Create a new primitive render. + */ +static struct vbuf_render * +nv10_vbuf_render_create( struct nv10_context *nv10 ) +{ +	struct nv10_vbuf_render *nv10_render = CALLOC_STRUCT(nv10_vbuf_render); + +	nv10_render->nv10 = nv10; + +	nv10_render->base.max_vertex_buffer_bytes = 16*1024; +	nv10_render->base.max_indices = 1024; +	nv10_render->base.get_vertex_info = nv10_vbuf_render_get_vertex_info; +	nv10_render->base.allocate_vertices = nv10_vbuf_render_allocate_vertices; +	nv10_render->base.set_primitive = nv10_vbuf_render_set_primitive; +	nv10_render->base.draw = nv10_vbuf_render_draw; +	nv10_render->base.release_vertices = nv10_vbuf_render_release_vertices; +	nv10_render->base.destroy = nv10_vbuf_render_destroy; + +	return &nv10_render->base; +} + + +/** + * Create a new primitive vbuf/render stage. + */ +struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 ) +{ +	struct vbuf_render *render; +	struct draw_stage *stage; + +	render = nv10_vbuf_render_create(nv10); +	if(!render) +		return NULL; + +	stage = draw_vbuf_stage( nv10->draw, render ); +	if(!stage) { +		render->destroy(render); +		return NULL; +	} + +	return stage; +} diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c new file mode 100644 index 0000000000..403f7b98cd --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -0,0 +1,209 @@ +#include "pipe/p_screen.h" +#include "pipe/p_util.h" + +#include "nv10_context.h" +#include "nv10_screen.h" + +static const char * +nv10_screen_get_name(struct pipe_screen *screen) +{ +	struct nv10_screen *nv10screen = nv10_screen(screen); +	struct nouveau_device *dev = nv10screen->nvws->channel->device; +	static char buffer[128]; + +	snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); +	return buffer; +} + +static const char * +nv10_screen_get_vendor(struct pipe_screen *screen) +{ +	return "nouveau"; +} + +static int +nv10_screen_get_param(struct pipe_screen *screen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: +		return 2; +	case PIPE_CAP_NPOT_TEXTURES: +		return 0; +	case PIPE_CAP_TWO_SIDED_STENCIL: +		return 0; +	case PIPE_CAP_GLSL: +		return 0; +	case PIPE_CAP_S3TC: +		return 0; +	case PIPE_CAP_ANISOTROPIC_FILTER: +		return 1; +	case PIPE_CAP_POINT_SPRITE: +		return 0; +	case PIPE_CAP_MAX_RENDER_TARGETS: +		return 1; +	case PIPE_CAP_OCCLUSION_QUERY: +		return 0; +	case PIPE_CAP_TEXTURE_SHADOW_MAP: +		return 0; +	case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: +		return 12; +	case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: +		return 0; +	case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: +		return 12; +	case NOUVEAU_CAP_HW_VTXBUF: +	case NOUVEAU_CAP_HW_IDXBUF: +		return 0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0; +	} +} + +static float +nv10_screen_get_paramf(struct pipe_screen *screen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_LINE_WIDTH: +	case PIPE_CAP_MAX_LINE_WIDTH_AA: +		return 10.0; +	case PIPE_CAP_MAX_POINT_WIDTH: +	case PIPE_CAP_MAX_POINT_WIDTH_AA: +		return 64.0; +	case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: +		return 2.0; +	case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: +		return 4.0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0.0; +	} +} + +static boolean +nv10_screen_is_format_supported(struct pipe_screen *screen, +				enum pipe_format format, +				enum pipe_texture_target target, +				unsigned tex_usage, unsigned geom_flags) +{ +	if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM:  +		case PIPE_FORMAT_Z24S8_UNORM: +		case PIPE_FORMAT_Z16_UNORM: +			return TRUE; +		default: +			break; +		} +	} else { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_A1R5G5B5_UNORM: +		case PIPE_FORMAT_A4R4G4B4_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM:  +		case PIPE_FORMAT_L8_UNORM: +		case PIPE_FORMAT_A8_UNORM: +		case PIPE_FORMAT_I8_UNORM: +			return TRUE; +		default: +			break; +		} +	} + +	return FALSE; +} + +static void * +nv10_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, +		 unsigned flags ) +{ +	struct pipe_winsys *ws = screen->winsys; +	void *map; + +	map = ws->buffer_map(ws, surface->buffer, flags); +	if (!map) +		return NULL; + +	return map + surface->offset; +} + +static void +nv10_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) +{ +	struct pipe_winsys *ws = screen->winsys; + +	ws->buffer_unmap(ws, surface->buffer); +} + +static void +nv10_screen_destroy(struct pipe_screen *pscreen) +{ +	struct nv10_screen *screen = nv10_screen(pscreen); +	struct nouveau_winsys *nvws = screen->nvws; + +	nvws->notifier_free(&screen->sync); +	nvws->grobj_free(&screen->celsius); + +	FREE(pscreen); +} + +struct pipe_screen * +nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +{ +	struct nv10_screen *screen = CALLOC_STRUCT(nv10_screen); +	unsigned celsius_class; +	unsigned chipset = nvws->channel->device->chipset; +	int ret; + +	if (!screen) +		return NULL; +	screen->nvws = nvws; + +	/* 3D object */ +	if (chipset>=0x20) +		celsius_class=NV11TCL; +	else if (chipset>=0x17) +		celsius_class=NV17TCL; +	else if (chipset>=0x11) +		celsius_class=NV11TCL; +	else +		celsius_class=NV10TCL; + +	if (!celsius_class) { +		NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", chipset); +		return NULL; +	} + +	ret = nvws->grobj_alloc(nvws, celsius_class, &screen->celsius); +	if (ret) { +		NOUVEAU_ERR("Error creating 3D object: %d\n", ret); +		return FALSE; +	} + +	/* Notifier for sync purposes */ +	ret = nvws->notifier_alloc(nvws, 1, &screen->sync); +	if (ret) { +		NOUVEAU_ERR("Error creating notifier object: %d\n", ret); +		nv10_screen_destroy(&screen->pipe); +		return NULL; +	} + +	screen->pipe.winsys = ws; +	screen->pipe.destroy = nv10_screen_destroy; + +	screen->pipe.get_name = nv10_screen_get_name; +	screen->pipe.get_vendor = nv10_screen_get_vendor; +	screen->pipe.get_param = nv10_screen_get_param; +	screen->pipe.get_paramf = nv10_screen_get_paramf; + +	screen->pipe.is_format_supported = nv10_screen_is_format_supported; + +	screen->pipe.surface_map = nv10_surface_map; +	screen->pipe.surface_unmap = nv10_surface_unmap; + +	nv10_screen_init_miptree_functions(&screen->pipe); + +	return &screen->pipe; +} + diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h new file mode 100644 index 0000000000..3f8750a13f --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -0,0 +1,22 @@ +#ifndef __NV10_SCREEN_H__ +#define __NV10_SCREEN_H__ + +#include "pipe/p_screen.h" + +struct nv10_screen { +	struct pipe_screen pipe; + +	struct nouveau_winsys *nvws; + +	/* HW graphics objects */ +	struct nouveau_grobj *celsius; +	struct nouveau_notifier *sync; +}; + +static INLINE struct nv10_screen * +nv10_screen(struct pipe_screen *screen) +{ +	return (struct nv10_screen *)screen; +} + +#endif diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c new file mode 100644 index 0000000000..f902fd54b6 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_state.c @@ -0,0 +1,589 @@ +#include "draw/draw_context.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_shader_tokens.h" + +#include "tgsi/tgsi_parse.h" + +#include "nv10_context.h" +#include "nv10_state.h" + +static void * +nv10_blend_state_create(struct pipe_context *pipe, +			const struct pipe_blend_state *cso) +{ +	struct nv10_blend_state *cb; + +	cb = MALLOC(sizeof(struct nv10_blend_state)); + +	cb->b_enable = cso->blend_enable ? 1 : 0; +	cb->b_srcfunc = ((nvgl_blend_func(cso->alpha_src_factor)<<16) | +			 (nvgl_blend_func(cso->rgb_src_factor))); +	cb->b_dstfunc = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) | +			 (nvgl_blend_func(cso->rgb_dst_factor))); + +	cb->c_mask = (((cso->colormask & PIPE_MASK_A) ? (0x01<<24) : 0) | +		      ((cso->colormask & PIPE_MASK_R) ? (0x01<<16) : 0) | +		      ((cso->colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) | +		      ((cso->colormask & PIPE_MASK_B) ? (0x01<< 0) : 0)); + +	cb->d_enable = cso->dither ? 1 : 0; + +	return (void *)cb; +} + +static void +nv10_blend_state_bind(struct pipe_context *pipe, void *blend) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	nv10->blend = (struct nv10_blend_state*)blend; + +	nv10->dirty |= NV10_NEW_BLEND; +} + +static void +nv10_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + + +static INLINE unsigned +wrap_mode(unsigned wrap) { +	unsigned ret; + +	switch (wrap) { +	case PIPE_TEX_WRAP_REPEAT: +		ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT; +		break; +	case PIPE_TEX_WRAP_MIRROR_REPEAT: +		ret = NV10TCL_TX_FORMAT_WRAP_S_MIRRORED_REPEAT; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_EDGE: +		ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_BORDER: +		ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_BORDER; +		break; +	case PIPE_TEX_WRAP_CLAMP: +		ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP; +		break; +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: +	case PIPE_TEX_WRAP_MIRROR_CLAMP: +	default: +		NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); +		ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT; +		break; +	} + +	return ret >> NV10TCL_TX_FORMAT_WRAP_S_SHIFT; +} + +static void * +nv10_sampler_state_create(struct pipe_context *pipe, +			  const struct pipe_sampler_state *cso) +{ +	struct nv10_sampler_state *ps; +	uint32_t filter = 0; + +	ps = MALLOC(sizeof(struct nv10_sampler_state)); + +	ps->wrap = ((wrap_mode(cso->wrap_s) << NV10TCL_TX_FORMAT_WRAP_S_SHIFT) | +		    (wrap_mode(cso->wrap_t) << NV10TCL_TX_FORMAT_WRAP_T_SHIFT)); + +	ps->en = 0; +	if (cso->max_anisotropy > 1.0) { +		/* no idea, binary driver sets it, works without it.. meh.. */ +		ps->wrap |= (1 << 5); + +/*		if (cso->max_anisotropy >= 16.0) { +			ps->en |= NV10TCL_TX_ENABLE_ANISO_16X; +		} else +		if (cso->max_anisotropy >= 12.0) { +			ps->en |= NV10TCL_TX_ENABLE_ANISO_12X; +		} else +		if (cso->max_anisotropy >= 10.0) { +			ps->en |= NV10TCL_TX_ENABLE_ANISO_10X; +		} else +		if (cso->max_anisotropy >= 8.0) { +			ps->en |= NV10TCL_TX_ENABLE_ANISO_8X; +		} else +		if (cso->max_anisotropy >= 6.0) { +			ps->en |= NV10TCL_TX_ENABLE_ANISO_6X; +		} else +		if (cso->max_anisotropy >= 4.0) { +			ps->en |= NV10TCL_TX_ENABLE_ANISO_4X; +		} else { +			ps->en |= NV10TCL_TX_ENABLE_ANISO_2X; +		}*/ +	} + +	switch (cso->mag_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		filter |= NV10TCL_TX_FILTER_MAGNIFY_LINEAR; +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		filter |= NV10TCL_TX_FILTER_MAGNIFY_NEAREST; +		break; +	} + +	switch (cso->min_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; +			break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR; +			break; +		} +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; +		break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST; +			break; +		} +		break; +	} + +	ps->filt = filter; + +/*	if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +		switch (cso->compare_func) { +		case PIPE_FUNC_NEVER: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NEVER; +			break; +		case PIPE_FUNC_GREATER: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GREATER; +			break; +		case PIPE_FUNC_EQUAL: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_EQUAL; +			break; +		case PIPE_FUNC_GEQUAL: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GEQUAL; +			break; +		case PIPE_FUNC_LESS: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LESS; +			break; +		case PIPE_FUNC_NOTEQUAL: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NOTEQUAL; +			break; +		case PIPE_FUNC_LEQUAL: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LEQUAL; +			break; +		case PIPE_FUNC_ALWAYS: +			ps->wrap |= NV10TCL_TX_WRAP_RCOMP_ALWAYS; +			break; +		default: +			break; +		} +	}*/ + +	ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | +		    (float_to_ubyte(cso->border_color[0]) << 16) | +		    (float_to_ubyte(cso->border_color[1]) <<  8) | +		    (float_to_ubyte(cso->border_color[2]) <<  0)); + +	return (void *)ps; +} + +static void +nv10_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ +	struct nv10_context *nv10 = nv10_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv10->tex_sampler[unit] = sampler[unit]; +		nv10->dirty_samplers |= (1 << unit); +	} +} + +static void +nv10_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void +nv10_set_sampler_texture(struct pipe_context *pipe, unsigned nr, +			 struct pipe_texture **miptree) +{ +	struct nv10_context *nv10 = nv10_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv10->tex_miptree[unit] = (struct nv10_miptree *)miptree[unit]; +		nv10->dirty_samplers |= (1 << unit); +	} +} + +static void * +nv10_rasterizer_state_create(struct pipe_context *pipe, +			     const struct pipe_rasterizer_state *cso) +{ +	struct nv10_rasterizer_state *rs; +	int i; + +	/*XXX: ignored: +	 * 	light_twoside +	 * 	offset_cw/ccw -nohw +	 * 	scissor +	 * 	point_smooth -nohw +	 * 	multisample +	 * 	offset_units / offset_scale +	 */ +	rs = MALLOC(sizeof(struct nv10_rasterizer_state)); + +	rs->templ = cso; +	 +	rs->shade_model = cso->flatshade ? 0x1d00 : 0x1d01; + +	rs->line_width = (unsigned char)(cso->line_width * 8.0) & 0xff; +	rs->line_smooth_en = cso->line_smooth ? 1 : 0; + +	rs->point_size = *(uint32_t*)&cso->point_size; + +	rs->poly_smooth_en = cso->poly_smooth ? 1 : 0; + +	if (cso->front_winding == PIPE_WINDING_CCW) { +		rs->front_face = NV10TCL_FRONT_FACE_CCW; +		rs->poly_mode_front = nvgl_polygon_mode(cso->fill_ccw); +		rs->poly_mode_back  = nvgl_polygon_mode(cso->fill_cw); +	} else { +		rs->front_face = NV10TCL_FRONT_FACE_CW; +		rs->poly_mode_front = nvgl_polygon_mode(cso->fill_cw); +		rs->poly_mode_back  = nvgl_polygon_mode(cso->fill_ccw); +	} + +	switch (cso->cull_mode) { +	case PIPE_WINDING_CCW: +		rs->cull_face_en = 1; +		if (cso->front_winding == PIPE_WINDING_CCW) +			rs->cull_face    = NV10TCL_CULL_FACE_FRONT; +		else +			rs->cull_face    = NV10TCL_CULL_FACE_BACK; +		break; +	case PIPE_WINDING_CW: +		rs->cull_face_en = 1; +		if (cso->front_winding == PIPE_WINDING_CW) +			rs->cull_face    = NV10TCL_CULL_FACE_FRONT; +		else +			rs->cull_face    = NV10TCL_CULL_FACE_BACK; +		break; +	case PIPE_WINDING_BOTH: +		rs->cull_face_en = 1; +		rs->cull_face    = NV10TCL_CULL_FACE_FRONT_AND_BACK; +		break; +	case PIPE_WINDING_NONE: +	default: +		rs->cull_face_en = 0; +		rs->cull_face    = 0; +		break; +	} + +	if (cso->point_sprite) { +		rs->point_sprite = (1 << 0); +		for (i = 0; i < 8; i++) { +			if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE) +				rs->point_sprite |= (1 << (8 + i)); +		} +	} else { +		rs->point_sprite = 0; +	} + +	return (void *)rs; +} + +static void +nv10_rasterizer_state_bind(struct pipe_context *pipe, void *rast) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	nv10->rast = (struct nv10_rasterizer_state*)rast; + +	draw_set_rasterizer_state(nv10->draw, (nv10->rast ? nv10->rast->templ : NULL)); + +	nv10->dirty |= NV10_NEW_RAST; +} + +static void +nv10_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void * +nv10_depth_stencil_alpha_state_create(struct pipe_context *pipe, +			const struct pipe_depth_stencil_alpha_state *cso) +{ +	struct nv10_depth_stencil_alpha_state *hw; + +	hw = MALLOC(sizeof(struct nv10_depth_stencil_alpha_state)); + +	hw->depth.func		= nvgl_comparison_op(cso->depth.func); +	hw->depth.write_enable	= cso->depth.writemask ? 1 : 0; +	hw->depth.test_enable	= cso->depth.enabled ? 1 : 0; + +	hw->stencil.enable = cso->stencil[0].enabled ? 1 : 0; +	hw->stencil.wmask = cso->stencil[0].write_mask; +	hw->stencil.func = nvgl_comparison_op(cso->stencil[0].func); +	hw->stencil.ref	= cso->stencil[0].ref_value; +	hw->stencil.vmask = cso->stencil[0].value_mask; +	hw->stencil.fail = nvgl_stencil_op(cso->stencil[0].fail_op); +	hw->stencil.zfail = nvgl_stencil_op(cso->stencil[0].zfail_op); +	hw->stencil.zpass = nvgl_stencil_op(cso->stencil[0].zpass_op); + +	hw->alpha.enabled = cso->alpha.enabled ? 1 : 0; +	hw->alpha.func = nvgl_comparison_op(cso->alpha.func); +	hw->alpha.ref  = float_to_ubyte(cso->alpha.ref); + +	return (void *)hw; +} + +static void +nv10_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *dsa) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	nv10->dsa = (struct nv10_depth_stencil_alpha_state*)dsa; + +	nv10->dirty |= NV10_NEW_DSA; +} + +static void +nv10_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void * +nv10_vp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *templ) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	return draw_create_vertex_shader(nv10->draw, templ); +} + +static void +nv10_vp_state_bind(struct pipe_context *pipe, void *shader) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	draw_bind_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader); + +	nv10->dirty |= NV10_NEW_VERTPROG; +} + +static void +nv10_vp_state_delete(struct pipe_context *pipe, void *shader) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	draw_delete_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader); +} + +static void * +nv10_fp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv10_fragment_program *fp; + +	fp = CALLOC(1, sizeof(struct nv10_fragment_program)); +	fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); +	 +	tgsi_scan_shader(cso->tokens, &fp->info); + +	return (void *)fp; +} + +static void +nv10_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv10_context *nv10 = nv10_context(pipe); +	struct nv10_fragment_program *fp = hwcso; + +	nv10->fragprog.current = fp; +	nv10->dirty |= NV10_NEW_FRAGPROG; +} + +static void +nv10_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv10_context *nv10 = nv10_context(pipe); +	struct nv10_fragment_program *fp = hwcso; + +	nv10_fragprog_destroy(nv10, fp); +	FREE((void*)fp->pipe.tokens); +	FREE(fp); +} + +static void +nv10_set_blend_color(struct pipe_context *pipe, +		     const struct pipe_blend_color *bcol) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	nv10->blend_color = (struct pipe_blend_color*)bcol; + +	nv10->dirty |= NV10_NEW_BLENDCOL; +} + +static void +nv10_set_clip_state(struct pipe_context *pipe, +		    const struct pipe_clip_state *clip) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	draw_set_clip_state(nv10->draw, clip); +} + +static void +nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, +			 const struct pipe_constant_buffer *buf ) +{ +	struct nv10_context *nv10 = nv10_context(pipe); +	struct pipe_winsys *ws = pipe->winsys; + +	assert(shader < PIPE_SHADER_TYPES); +	assert(index == 0); + +	if (buf) { +		void *mapped; +		if (buf->size && (mapped = ws->buffer_map(ws, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) +		{ +			memcpy(nv10->constbuf[shader], mapped, buf->size); +			nv10->constbuf_nr[shader] = +				buf->size / (4 * sizeof(float)); +			ws->buffer_unmap(ws, buf->buffer); +		} +	} +} + +static void +nv10_set_framebuffer_state(struct pipe_context *pipe, +			   const struct pipe_framebuffer_state *fb) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	nv10->framebuffer = (struct pipe_framebuffer_state*)fb; + +	nv10->dirty |= NV10_NEW_FRAMEBUFFER; +} + +static void +nv10_set_polygon_stipple(struct pipe_context *pipe, +			 const struct pipe_poly_stipple *stipple) +{ +	NOUVEAU_ERR("line stipple hahaha\n"); +} + +static void +nv10_set_scissor_state(struct pipe_context *pipe, +		       const struct pipe_scissor_state *s) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	nv10->scissor = (struct pipe_scissor_state*)s; + +	nv10->dirty |= NV10_NEW_SCISSOR; +} + +static void +nv10_set_viewport_state(struct pipe_context *pipe, +			const struct pipe_viewport_state *vpt) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	nv10->viewport = (struct pipe_viewport_state*)vpt; + +	draw_set_viewport_state(nv10->draw, nv10->viewport); + +	nv10->dirty |= NV10_NEW_VIEWPORT; +} + +static void +nv10_set_vertex_buffers(struct pipe_context *pipe, unsigned count, +			const struct pipe_vertex_buffer *vb) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	memcpy(nv10->vtxbuf, vb, sizeof(*vb) * count); +	nv10->dirty |= NV10_NEW_VTXARRAYS; + +	draw_set_vertex_buffers(nv10->draw, count, vb); +} + +static void +nv10_set_vertex_elements(struct pipe_context *pipe, unsigned count, +			 const struct pipe_vertex_element *ve) +{ +	struct nv10_context *nv10 = nv10_context(pipe); + +	memcpy(nv10->vtxelt, ve, sizeof(*ve) * count); +	nv10->dirty |= NV10_NEW_VTXARRAYS; + +	draw_set_vertex_elements(nv10->draw, count, ve); +} + +void +nv10_init_state_functions(struct nv10_context *nv10) +{ +	nv10->pipe.create_blend_state = nv10_blend_state_create; +	nv10->pipe.bind_blend_state = nv10_blend_state_bind; +	nv10->pipe.delete_blend_state = nv10_blend_state_delete; + +	nv10->pipe.create_sampler_state = nv10_sampler_state_create; +	nv10->pipe.bind_sampler_states = nv10_sampler_state_bind; +	nv10->pipe.delete_sampler_state = nv10_sampler_state_delete; +	nv10->pipe.set_sampler_textures = nv10_set_sampler_texture; + +	nv10->pipe.create_rasterizer_state = nv10_rasterizer_state_create; +	nv10->pipe.bind_rasterizer_state = nv10_rasterizer_state_bind; +	nv10->pipe.delete_rasterizer_state = nv10_rasterizer_state_delete; + +	nv10->pipe.create_depth_stencil_alpha_state = +		nv10_depth_stencil_alpha_state_create; +	nv10->pipe.bind_depth_stencil_alpha_state = +		nv10_depth_stencil_alpha_state_bind; +	nv10->pipe.delete_depth_stencil_alpha_state = +		nv10_depth_stencil_alpha_state_delete; + +	nv10->pipe.create_vs_state = nv10_vp_state_create; +	nv10->pipe.bind_vs_state = nv10_vp_state_bind; +	nv10->pipe.delete_vs_state = nv10_vp_state_delete; + +	nv10->pipe.create_fs_state = nv10_fp_state_create; +	nv10->pipe.bind_fs_state = nv10_fp_state_bind; +	nv10->pipe.delete_fs_state = nv10_fp_state_delete; + +	nv10->pipe.set_blend_color = nv10_set_blend_color; +	nv10->pipe.set_clip_state = nv10_set_clip_state; +	nv10->pipe.set_constant_buffer = nv10_set_constant_buffer; +	nv10->pipe.set_framebuffer_state = nv10_set_framebuffer_state; +	nv10->pipe.set_polygon_stipple = nv10_set_polygon_stipple; +	nv10->pipe.set_scissor_state = nv10_set_scissor_state; +	nv10->pipe.set_viewport_state = nv10_set_viewport_state; + +	nv10->pipe.set_vertex_buffers = nv10_set_vertex_buffers; +	nv10->pipe.set_vertex_elements = nv10_set_vertex_elements; +} + diff --git a/src/gallium/drivers/nv10/nv10_state.h b/src/gallium/drivers/nv10/nv10_state.h new file mode 100644 index 0000000000..3a3fd0d4f4 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_state.h @@ -0,0 +1,139 @@ +#ifndef __NV10_STATE_H__ +#define __NV10_STATE_H__ + +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" + +struct nv10_blend_state { +	uint32_t b_enable; +	uint32_t b_srcfunc; +	uint32_t b_dstfunc; + +	uint32_t c_mask; + +	uint32_t d_enable; +}; + +struct nv10_sampler_state { +	uint32_t wrap; +	uint32_t en; +	uint32_t filt; +	uint32_t bcol; +}; + +struct nv10_rasterizer_state { +	uint32_t shade_model; + +	uint32_t line_width; +	uint32_t line_smooth_en; + +	uint32_t point_size; + +	uint32_t poly_smooth_en; +	 +	uint32_t poly_mode_front; +	uint32_t poly_mode_back; + +	uint32_t front_face; +	uint32_t cull_face; +	uint32_t cull_face_en; + +	uint32_t point_sprite; + +	const struct pipe_rasterizer_state *templ; +}; + +struct nv10_vertex_program_exec { +	uint32_t data[4]; +	boolean has_branch_offset; +	int const_index; +}; + +struct nv10_vertex_program_data { +	int index; /* immediates == -1 */ +	float value[4]; +}; + +struct nv10_vertex_program { +	const struct pipe_shader_state *pipe; + +	boolean translated; +	struct nv10_vertex_program_exec *insns; +	unsigned nr_insns; +	struct nv10_vertex_program_data *consts; +	unsigned nr_consts; + +	struct nouveau_resource *exec; +	unsigned exec_start; +	struct nouveau_resource *data; +	unsigned data_start; +	unsigned data_start_min; + +	uint32_t ir; +	uint32_t or; +}; + +struct nv10_fragment_program_data { +	unsigned offset; +	unsigned index; +}; + +struct nv10_fragment_program { +	struct pipe_shader_state pipe; +	struct tgsi_shader_info info; + +	boolean translated; +	boolean on_hw; +	unsigned samplers; + +	uint32_t *insn; +	int       insn_len; + +	struct nv10_fragment_program_data *consts; +	unsigned nr_consts; + +	struct pipe_buffer *buffer; + +	uint32_t fp_control; +	uint32_t fp_reg_control; +}; + + +struct nv10_depth_stencil_alpha_state { +	struct { +		uint32_t func; +		uint32_t write_enable; +		uint32_t test_enable; +	} depth; + +	struct { +		uint32_t enable; +		uint32_t wmask; +		uint32_t func; +		uint32_t ref; +		uint32_t vmask; +		uint32_t fail; +		uint32_t zfail; +		uint32_t zpass; +	} stencil; + +	struct { +		uint32_t enabled; +		uint32_t func; +		uint32_t ref; +	} alpha; +}; + +struct nv10_miptree { +	struct pipe_texture base; + +	struct pipe_buffer *buffer; +	uint total_size; + +	struct { +		uint pitch; +		uint *image_offset; +	} level[PIPE_MAX_TEXTURE_LEVELS]; +}; + +#endif diff --git a/src/gallium/drivers/nv10/nv10_state_emit.c b/src/gallium/drivers/nv10/nv10_state_emit.c new file mode 100644 index 0000000000..d21368d33f --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_state_emit.c @@ -0,0 +1,305 @@ +#include "pipe/p_util.h" + +#include "nv10_context.h" +#include "nv10_state.h" + +static void nv10_state_emit_blend(struct nv10_context* nv10) +{ +	struct nv10_blend_state *b = nv10->blend; + +	BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 1); +	OUT_RING  (b->d_enable); + +	BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 3); +	OUT_RING  (b->b_enable); +	OUT_RING  (b->b_srcfunc); +	OUT_RING  (b->b_dstfunc); + +	BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1); +	OUT_RING  (b->c_mask); +} + +static void nv10_state_emit_blend_color(struct nv10_context* nv10) +{ +	struct pipe_blend_color *c = nv10->blend_color; + +	BEGIN_RING(celsius, NV10TCL_BLEND_COLOR, 1); +	OUT_RING  ((float_to_ubyte(c->color[3]) << 24)| +		   (float_to_ubyte(c->color[0]) << 16)| +		   (float_to_ubyte(c->color[1]) << 8) | +		   (float_to_ubyte(c->color[2]) << 0)); +} + +static void nv10_state_emit_rast(struct nv10_context* nv10) +{ +	struct nv10_rasterizer_state *r = nv10->rast; + +	BEGIN_RING(celsius, NV10TCL_SHADE_MODEL, 2); +	OUT_RING  (r->shade_model); +	OUT_RING  (r->line_width); + + +	BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1); +	OUT_RING  (r->point_size); + +	BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2); +	OUT_RING  (r->poly_mode_front); +	OUT_RING  (r->poly_mode_back); + + +	BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2); +	OUT_RING  (r->cull_face); +	OUT_RING  (r->front_face); + +	BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 2); +	OUT_RING  (r->line_smooth_en); +	OUT_RING  (r->poly_smooth_en); + +	BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1); +	OUT_RING  (r->cull_face_en); +} + +static void nv10_state_emit_dsa(struct nv10_context* nv10) +{ +	struct nv10_depth_stencil_alpha_state *d = nv10->dsa; + +	BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1); +	OUT_RING (d->depth.func); + +	BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1); +	OUT_RING (d->depth.write_enable); + +	BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1); +	OUT_RING (d->depth.test_enable); + +#if 0 +	BEGIN_RING(celsius, NV10TCL_STENCIL_ENABLE, 1); +	OUT_RING (d->stencil.enable); +	BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 7); +	OUT_RINGp ((uint32_t *)&(d->stencil.wmask), 7); +#endif + +	BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1); +	OUT_RING (d->alpha.enabled); + +	BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 1); +	OUT_RING (d->alpha.func); + +	BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_REF, 1); +	OUT_RING (d->alpha.ref); +} + +static void nv10_state_emit_viewport(struct nv10_context* nv10) +{ +} + +static void nv10_state_emit_scissor(struct nv10_context* nv10) +{ +	// XXX this is so not working +/*	struct pipe_scissor_state *s = nv10->scissor; +	BEGIN_RING(celsius, NV10TCL_SCISSOR_HORIZ, 2); +	OUT_RING  (((s->maxx - s->minx) << 16) | s->minx); +	OUT_RING  (((s->maxy - s->miny) << 16) | s->miny);*/ +} + +static void nv10_state_emit_framebuffer(struct nv10_context* nv10) +{ +	struct pipe_framebuffer_state* fb = nv10->framebuffer; +	struct pipe_surface *rt, *zeta = NULL; +	uint32_t rt_format, w, h; +	int colour_format = 0, zeta_format = 0; + +	w = fb->cbufs[0]->width; +	h = fb->cbufs[0]->height; +	colour_format = fb->cbufs[0]->format; +	rt = fb->cbufs[0]; + +	if (fb->zsbuf) { +		if (colour_format) { +			assert(w == fb->zsbuf->width); +			assert(h == fb->zsbuf->height); +		} else { +			w = fb->zsbuf->width; +			h = fb->zsbuf->height; +		} + +		zeta_format = fb->zsbuf->format; +		zeta = fb->zsbuf; +	} + +	rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR; + +	switch (colour_format) { +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case 0: +		rt_format |= NV10TCL_RT_FORMAT_COLOR_A8R8G8B8; +		break; +	case PIPE_FORMAT_R5G6B5_UNORM: +		rt_format |= NV10TCL_RT_FORMAT_COLOR_R5G6B5; +		break; +	default: +		assert(0); +	} + +	if (zeta) { +		BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); +		OUT_RING  (rt->stride | (zeta->stride << 16)); +	} else { +		BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); +		OUT_RING  (rt->stride | (rt->stride << 16)); +	} + +	nv10->rt[0] = rt->buffer; + +	if (zeta_format) +	{ +		nv10->zeta = zeta->buffer; +	} + +	BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 3); +	OUT_RING  ((w << 16) | 0); +	OUT_RING  ((h << 16) | 0); +	OUT_RING  (rt_format); +	BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 2); +	OUT_RING  (((w - 1) << 16) | 0 | 0x08000800); +	OUT_RING  (((h - 1) << 16) | 0 | 0x08000800); +} + +static void nv10_vertex_layout(struct nv10_context *nv10) +{ +	struct nv10_fragment_program *fp = nv10->fragprog.current; +	uint32_t src = 0; +	int i; +	struct vertex_info vinfo; + +	memset(&vinfo, 0, sizeof(vinfo)); + +	for (i = 0; i < fp->info.num_inputs; i++) { +		switch (fp->info.input_semantic_name[i]) { +			case TGSI_SEMANTIC_POSITION: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); +				break; +			case TGSI_SEMANTIC_COLOR: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); +				break; +			default: +			case TGSI_SEMANTIC_GENERIC: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); +				break; +			case TGSI_SEMANTIC_FOG: +				draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); +				break; +		} +	} +	draw_compute_vertex_size(&vinfo); +} + +void +nv10_emit_hw_state(struct nv10_context *nv10) +{ +	int i; + +	if (nv10->dirty & NV10_NEW_VERTPROG) { +		//nv10_vertprog_bind(nv10, nv10->vertprog.current); +		nv10->dirty &= ~NV10_NEW_VERTPROG; +	} + +	if (nv10->dirty & NV10_NEW_FRAGPROG) { +		nv10_fragprog_bind(nv10, nv10->fragprog.current); +		/*XXX: clear NV10_NEW_FRAGPROG if no new program uploaded */ +		nv10->dirty_samplers |= (1<<10); +		nv10->dirty_samplers = 0; +	} + +	if (nv10->dirty_samplers || (nv10->dirty & NV10_NEW_FRAGPROG)) { +		nv10_fragtex_bind(nv10); +		nv10->dirty &= ~NV10_NEW_FRAGPROG; +	} + +	if (nv10->dirty & NV10_NEW_VTXARRAYS) { +		nv10->dirty &= ~NV10_NEW_VTXARRAYS; +		nv10_vertex_layout(nv10); +		nv10_vtxbuf_bind(nv10); +	} + +	if (nv10->dirty & NV10_NEW_BLEND) { +		nv10->dirty &= ~NV10_NEW_BLEND; +		nv10_state_emit_blend(nv10); +	} + +	if (nv10->dirty & NV10_NEW_BLENDCOL) { +		nv10->dirty &= ~NV10_NEW_BLENDCOL; +		nv10_state_emit_blend_color(nv10); +	} + +	if (nv10->dirty & NV10_NEW_RAST) { +		nv10->dirty &= ~NV10_NEW_RAST; +		nv10_state_emit_rast(nv10); +	} + +	if (nv10->dirty & NV10_NEW_DSA) { +		nv10->dirty &= ~NV10_NEW_DSA; +		nv10_state_emit_dsa(nv10); +	} + + 	if (nv10->dirty & NV10_NEW_VIEWPORT) { +		nv10->dirty &= ~NV10_NEW_VIEWPORT; +		nv10_state_emit_viewport(nv10); +	} + + 	if (nv10->dirty & NV10_NEW_SCISSOR) { +		nv10->dirty &= ~NV10_NEW_SCISSOR; +		nv10_state_emit_scissor(nv10); +	} + + 	if (nv10->dirty & NV10_NEW_FRAMEBUFFER) { +		nv10->dirty &= ~NV10_NEW_FRAMEBUFFER; +		nv10_state_emit_framebuffer(nv10); +	} + +	/* Emit relocs for every referenced buffer. +	 * This is to ensure the bufmgr has an accurate idea of how +	 * the buffer is used.  This isn't very efficient, but we don't +	 * seem to take a significant performance hit.  Will be improved +	 * at some point.  Vertex arrays are emitted by nv10_vbo.c +	 */ + +	/* Render target */ +// XXX figre out who's who for NV10TCL_DMA_* and fill accordingly +//	BEGIN_RING(celsius, NV10TCL_DMA_COLOR0, 1); +//	OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1); +	OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	if (nv10->zeta) { +// XXX +//		BEGIN_RING(celsius, NV10TCL_DMA_ZETA, 1); +//		OUT_RELOCo(nv10->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +		BEGIN_RING(celsius, NV10TCL_ZETA_OFFSET, 1); +		OUT_RELOCl(nv10->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +		/* XXX for when we allocate LMA on nv17 */ +/*		BEGIN_RING(celsius, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1); +		OUT_RELOCl(nv10->zeta + lma_offset);*/ +	} + +	/* Vertex buffer */ +	BEGIN_RING(celsius, NV10TCL_DMA_VTXBUF0, 1); +	OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1); +	OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	/* Texture images */ +	for (i = 0; i < 2; i++) { +		if (!(nv10->fp_samplers & (1 << i))) +			continue; +		BEGIN_RING(celsius, NV10TCL_TX_OFFSET(i), 1); +		OUT_RELOCl(nv10->tex[i].buffer, 0, NOUVEAU_BO_VRAM | +			   NOUVEAU_BO_GART | NOUVEAU_BO_RD); +		BEGIN_RING(celsius, NV10TCL_TX_FORMAT(i), 1); +		OUT_RELOCd(nv10->tex[i].buffer, nv10->tex[i].format, +			   NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | +			   NOUVEAU_BO_OR, NV10TCL_TX_FORMAT_DMA0, +			   NV10TCL_TX_FORMAT_DMA1); +	} +} + diff --git a/src/gallium/drivers/nv10/nv10_surface.c b/src/gallium/drivers/nv10/nv10_surface.c new file mode 100644 index 0000000000..2e230ebbec --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_surface.c @@ -0,0 +1,65 @@ + +/************************************************************************** + *  + * Copyright 2003 Tungsten Graphics, 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, 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 TUNGSTEN GRAPHICS 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. + *  + **************************************************************************/ + +#include "nv10_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_winsys.h" +#include "pipe/p_inlines.h" +#include "util/p_tile.h" + +static void +nv10_surface_copy(struct pipe_context *pipe, unsigned do_flip, +		  struct pipe_surface *dest, unsigned destx, unsigned desty, +		  struct pipe_surface *src, unsigned srcx, unsigned srcy, +		  unsigned width, unsigned height) +{ +	struct nv10_context *nv10 = nv10_context(pipe); +	struct nouveau_winsys *nvws = nv10->nvws; + +	nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, +			   width, height); +} + +static void +nv10_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +		  unsigned destx, unsigned desty, unsigned width, +		  unsigned height, unsigned value) +{ +	struct nv10_context *nv10 = nv10_context(pipe); +	struct nouveau_winsys *nvws = nv10->nvws; + +	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +} + +void +nv10_init_surface_functions(struct nv10_context *nv10) +{ +	nv10->pipe.surface_copy = nv10_surface_copy; +	nv10->pipe.surface_fill = nv10_surface_fill; +} diff --git a/src/gallium/drivers/nv10/nv10_vbo.c b/src/gallium/drivers/nv10/nv10_vbo.c new file mode 100644 index 0000000000..f024f53420 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_vbo.c @@ -0,0 +1,78 @@ +#include "draw/draw_context.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" + +#include "nv10_context.h" +#include "nv10_state.h" + +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_pushbuf.h" + +boolean nv10_draw_elements( struct pipe_context *pipe, +                    struct pipe_buffer *indexBuffer, +                    unsigned indexSize, +                    unsigned prim, unsigned start, unsigned count) +{ +	struct nv10_context *nv10 = nv10_context( pipe ); +	struct draw_context *draw = nv10->draw; +	unsigned i; + +	nv10_emit_hw_state(nv10); + +	/* +	 * Map vertex buffers +	 */ +	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { +		if (nv10->vtxbuf[i].buffer) { +			void *buf +				= pipe->winsys->buffer_map(pipe->winsys, +						nv10->vtxbuf[i].buffer, +						PIPE_BUFFER_USAGE_CPU_READ); +			draw_set_mapped_vertex_buffer(draw, i, buf); +		} +	} +	/* Map index buffer, if present */ +	if (indexBuffer) { +		void *mapped_indexes +			= pipe->winsys->buffer_map(pipe->winsys, indexBuffer, +					PIPE_BUFFER_USAGE_CPU_READ); +		draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); +	} +	else { +		/* no index/element buffer */ +		draw_set_mapped_element_buffer(draw, 0, NULL); +	} + +	draw_set_mapped_constant_buffer(draw, +					nv10->constbuf[PIPE_SHADER_VERTEX], +					nv10->constbuf_nr[PIPE_SHADER_VERTEX]); + +	/* draw! */ +	draw_arrays(nv10->draw, prim, start, count); + +	/* +	 * unmap vertex/index buffers +	 */ +	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { +		if (nv10->vtxbuf[i].buffer) { +			pipe->winsys->buffer_unmap(pipe->winsys, nv10->vtxbuf[i].buffer); +			draw_set_mapped_vertex_buffer(draw, i, NULL); +		} +	} +	if (indexBuffer) { +		pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer); +		draw_set_mapped_element_buffer(draw, 0, NULL); +	} + +	return TRUE; +} + +boolean nv10_draw_arrays( struct pipe_context *pipe, +				 unsigned prim, unsigned start, unsigned count) +{ +	return nv10_draw_elements(pipe, NULL, 0, prim, start, count); +} + + + diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile new file mode 100644 index 0000000000..69f2790dfe --- /dev/null +++ b/src/gallium/drivers/nv30/Makefile @@ -0,0 +1,37 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nv30 + +DRIVER_SOURCES = \ +	nv30_clear.c \ +	nv30_context.c \ +	nv30_draw.c \ +	nv30_fragprog.c \ +	nv30_fragtex.c \ +	nv30_miptree.c \ +	nv30_query.c \ +	nv30_screen.c \ +	nv30_state.c \ +	nv30_state_blend.c \ +	nv30_state_emit.c \ +	nv30_state_fb.c \ +	nv30_state_rasterizer.c \ +	nv30_state_scissor.c \ +	nv30_state_stipple.c \ +	nv30_state_viewport.c \ +	nv30_state_zsa.c \ +	nv30_surface.c \ +	nv30_vbo.c \ +	nv30_vertprog.c + +C_SOURCES = \ +	$(COMMON_SOURCES) \ +	$(DRIVER_SOURCES) + +ASM_SOURCES =  + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c new file mode 100644 index 0000000000..8c3ca204d5 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_clear.c @@ -0,0 +1,13 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "nv30_context.h" + +void +nv30_clear(struct pipe_context *pipe, struct pipe_surface *ps, +	   unsigned clearValue) +{ +	pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); +	ps->status = PIPE_SURFACE_STATUS_CLEAR; +} diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c new file mode 100644 index 0000000000..eefc614e5b --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_context.c @@ -0,0 +1,73 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" +#include "pipe/p_util.h" + +#include "nv30_context.h" +#include "nv30_screen.h" + +static void +nv30_flush(struct pipe_context *pipe, unsigned flags, +	   struct pipe_fence_handle **fence) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	 +	if (flags & PIPE_FLUSH_TEXTURE_CACHE) { +		BEGIN_RING(rankine, 0x1fd8, 1); +		OUT_RING  (2); +		BEGIN_RING(rankine, 0x1fd8, 1); +		OUT_RING  (1); +	} + +	FIRE_RING(fence); +} + +static void +nv30_destroy(struct pipe_context *pipe) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	if (nv30->draw) +		draw_destroy(nv30->draw); +	FREE(nv30); +} + +struct pipe_context * +nv30_create(struct pipe_screen *pscreen, unsigned pctx_id) +{ +	struct nv30_screen *screen = nv30_screen(pscreen); +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv30_context *nv30; +	struct nouveau_winsys *nvws = screen->nvws; + +	nv30 = CALLOC(1, sizeof(struct nv30_context)); +	if (!nv30) +		return NULL; +	nv30->screen = screen; +	nv30->pctx_id = pctx_id; + +	nv30->nvws = nvws; + +	nv30->pipe.winsys = ws; +	nv30->pipe.screen = pscreen; +	nv30->pipe.destroy = nv30_destroy; +	nv30->pipe.draw_arrays = nv30_draw_arrays; +	nv30->pipe.draw_elements = nv30_draw_elements; +	nv30->pipe.clear = nv30_clear; +	nv30->pipe.flush = nv30_flush; + +	nv30_init_query_functions(nv30); +	nv30_init_surface_functions(nv30); +	nv30_init_state_functions(nv30); + +	/* Create, configure, and install fallback swtnl path */ +	nv30->draw = draw_create(); +	draw_wide_point_threshold(nv30->draw, 9999999.0); +	draw_wide_line_threshold(nv30->draw, 9999999.0); +	draw_enable_line_stipple(nv30->draw, FALSE); +	draw_enable_point_sprites(nv30->draw, FALSE); +	draw_set_rasterize_stage(nv30->draw, nv30_draw_render_stage(nv30)); + +	return &nv30->pipe; +} +	 diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h new file mode 100644 index 0000000000..823b34a7c3 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -0,0 +1,208 @@ +#ifndef __NV30_CONTEXT_H__ +#define __NV30_CONTEXT_H__ + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" + +#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \ +	struct nv30_screen *ctx = nv30->screen +#include "nouveau/nouveau_push.h" +#include "nouveau/nouveau_stateobj.h" + +#include "nv30_state.h" + +#define NOUVEAU_ERR(fmt, args...) \ +	fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ +	fprintf(stderr, "nouveau: "fmt, ##args); + +enum nv30_state_index { +	NV30_STATE_FB = 0, +	NV30_STATE_VIEWPORT = 1, +	NV30_STATE_BLEND = 2, +	NV30_STATE_RAST = 3, +	NV30_STATE_ZSA = 4, +	NV30_STATE_BCOL = 5, +	NV30_STATE_CLIP = 6, +	NV30_STATE_SCISSOR = 7, +	NV30_STATE_STIPPLE = 8, +	NV30_STATE_FRAGPROG = 9, +	NV30_STATE_VERTPROG = 10, +	NV30_STATE_FRAGTEX0 = 11, +	NV30_STATE_FRAGTEX1 = 12, +	NV30_STATE_FRAGTEX2 = 13, +	NV30_STATE_FRAGTEX3 = 14, +	NV30_STATE_FRAGTEX4 = 15, +	NV30_STATE_FRAGTEX5 = 16, +	NV30_STATE_FRAGTEX6 = 17, +	NV30_STATE_FRAGTEX7 = 18, +	NV30_STATE_FRAGTEX8 = 19, +	NV30_STATE_FRAGTEX9 = 20, +	NV30_STATE_FRAGTEX10 = 21, +	NV30_STATE_FRAGTEX11 = 22, +	NV30_STATE_FRAGTEX12 = 23, +	NV30_STATE_FRAGTEX13 = 24, +	NV30_STATE_FRAGTEX14 = 25, +	NV30_STATE_FRAGTEX15 = 26, +	NV30_STATE_VERTTEX0 = 27, +	NV30_STATE_VERTTEX1 = 28, +	NV30_STATE_VERTTEX2 = 29, +	NV30_STATE_VERTTEX3 = 30, +	NV30_STATE_VTXBUF = 31, +	NV30_STATE_VTXFMT = 32, +	NV30_STATE_VTXATTR = 33, +	NV30_STATE_MAX = 34 +}; + +#include "nv30_screen.h" + +#define NV30_NEW_BLEND		(1 <<  0) +#define NV30_NEW_RAST		(1 <<  1) +#define NV30_NEW_ZSA		(1 <<  2) +#define NV30_NEW_SAMPLER	(1 <<  3) +#define NV30_NEW_FB		(1 <<  4) +#define NV30_NEW_STIPPLE	(1 <<  5) +#define NV30_NEW_SCISSOR	(1 <<  6) +#define NV30_NEW_VIEWPORT	(1 <<  7) +#define NV30_NEW_BCOL		(1 <<  8) +#define NV30_NEW_VERTPROG	(1 <<  9) +#define NV30_NEW_FRAGPROG	(1 << 10) +#define NV30_NEW_ARRAYS		(1 << 11) +#define NV30_NEW_UCP		(1 << 12) + +struct nv30_rasterizer_state { +	struct pipe_rasterizer_state pipe; +	struct nouveau_stateobj *so; +}; + +struct nv30_zsa_state { +	struct pipe_depth_stencil_alpha_state pipe; +	struct nouveau_stateobj *so; +}; + +struct nv30_blend_state { +	struct pipe_blend_state pipe; +	struct nouveau_stateobj *so; +}; + + +struct nv30_state { +	unsigned scissor_enabled; +	unsigned stipple_enabled; +	unsigned viewport_bypass; +	unsigned fp_samplers; + +	uint64_t dirty; +	struct nouveau_stateobj *hw[NV30_STATE_MAX]; +}; + +struct nv30_context { +	struct pipe_context pipe; + +	struct nouveau_winsys *nvws; +	struct nv30_screen *screen; +	unsigned pctx_id; + +	struct draw_context *draw; + +	/* HW state derived from pipe states */ +	struct nv30_state state; + +	/* Context state */ +	unsigned dirty; +	struct pipe_scissor_state scissor; +	unsigned stipple[32]; +	struct nv30_vertex_program *vertprog; +	struct nv30_fragment_program *fragprog; +	struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; +	unsigned constbuf_nr[PIPE_SHADER_TYPES]; +	struct nv30_rasterizer_state *rasterizer; +	struct nv30_zsa_state *zsa; +	struct nv30_blend_state *blend; +	struct pipe_blend_color blend_colour; +	struct pipe_viewport_state viewport; +	struct pipe_framebuffer_state framebuffer; +	struct pipe_buffer *idxbuf; +	unsigned idxbuf_format; +	struct nv30_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; +	struct nv30_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; +	unsigned nr_samplers; +	unsigned nr_textures; +	unsigned dirty_samplers; +	struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; +	unsigned vtxbuf_nr; +	struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; +	unsigned vtxelt_nr; +	const unsigned *edgeflags; +}; + +static INLINE struct nv30_context * +nv30_context(struct pipe_context *pipe) +{ +	return (struct nv30_context *)pipe; +} + +struct nv30_state_entry { +	boolean (*validate)(struct nv30_context *nv30); +	struct { +		unsigned pipe; +		unsigned hw; +	} dirty; +}; + +extern void nv30_init_state_functions(struct nv30_context *nv30); +extern void nv30_init_surface_functions(struct nv30_context *nv30); +extern void nv30_init_query_functions(struct nv30_context *nv30); + +extern void nv30_screen_init_miptree_functions(struct pipe_screen *pscreen); + +/* nv30_draw.c */ +extern struct draw_stage *nv30_draw_render_stage(struct nv30_context *nv30); + +/* nv30_vertprog.c */ +extern void nv30_vertprog_destroy(struct nv30_context *, +				  struct nv30_vertex_program *); + +/* nv30_fragprog.c */ +extern void nv30_fragprog_destroy(struct nv30_context *, +				  struct nv30_fragment_program *); + +/* nv30_fragtex.c */ +extern void nv30_fragtex_bind(struct nv30_context *); + +/* nv30_state.c and friends */ +extern boolean nv30_state_validate(struct nv30_context *nv30); +extern void nv30_state_emit(struct nv30_context *nv30); +extern struct nv30_state_entry nv30_state_rasterizer; +extern struct nv30_state_entry nv30_state_scissor; +extern struct nv30_state_entry nv30_state_stipple; +extern struct nv30_state_entry nv30_state_fragprog; +extern struct nv30_state_entry nv30_state_vertprog; +extern struct nv30_state_entry nv30_state_blend; +extern struct nv30_state_entry nv30_state_blend_colour; +extern struct nv30_state_entry nv30_state_zsa; +extern struct nv30_state_entry nv30_state_viewport; +extern struct nv30_state_entry nv30_state_framebuffer; +extern struct nv30_state_entry nv30_state_fragtex; +extern struct nv30_state_entry nv30_state_vbo; + +/* nv30_vbo.c */ +extern boolean nv30_draw_arrays(struct pipe_context *, unsigned mode, +				unsigned start, unsigned count); +extern boolean nv30_draw_elements(struct pipe_context *pipe, +				  struct pipe_buffer *indexBuffer, +				  unsigned indexSize, +				  unsigned mode, unsigned start, +				  unsigned count); + +/* nv30_clear.c */ +extern void nv30_clear(struct pipe_context *pipe, struct pipe_surface *ps, +		       unsigned clearValue); + +#endif diff --git a/src/gallium/drivers/nv30/nv30_draw.c b/src/gallium/drivers/nv30/nv30_draw.c new file mode 100644 index 0000000000..aeeaf58f20 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_draw.c @@ -0,0 +1,62 @@ +#include "draw/draw_pipe.h" +#include "pipe/p_util.h" + +#include "nv30_context.h" + +struct nv30_draw_stage { +	struct draw_stage draw; +	struct nv30_context *nv30; +}; + +static void +nv30_draw_point(struct draw_stage *draw, struct prim_header *prim) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv30_draw_line(struct draw_stage *draw, struct prim_header *prim) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv30_draw_tri(struct draw_stage *draw, struct prim_header *prim) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv30_draw_flush(struct draw_stage *draw, unsigned flags) +{ +} + +static void +nv30_draw_reset_stipple_counter(struct draw_stage *draw) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv30_draw_destroy(struct draw_stage *draw) +{ +	FREE(draw); +} + +struct draw_stage * +nv30_draw_render_stage(struct nv30_context *nv30) +{ +	struct nv30_draw_stage *nv30draw = CALLOC_STRUCT(nv30_draw_stage); + +	nv30draw->nv30 = nv30; +	nv30draw->draw.draw = nv30->draw; +	nv30draw->draw.point = nv30_draw_point; +	nv30draw->draw.line = nv30_draw_line; +	nv30draw->draw.tri = nv30_draw_tri; +	nv30draw->draw.flush = nv30_draw_flush; +	nv30draw->draw.reset_stipple_counter = nv30_draw_reset_stipple_counter; +	nv30draw->draw.destroy = nv30_draw_destroy; + +	return &nv30draw->draw; +} + diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c new file mode 100644 index 0000000000..68058264e3 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_fragprog.c @@ -0,0 +1,898 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" + +#include "nv30_context.h" + +#define SWZ_X 0 +#define SWZ_Y 1 +#define SWZ_Z 2 +#define SWZ_W 3 +#define MASK_X 1 +#define MASK_Y 2 +#define MASK_Z 4 +#define MASK_W 8 +#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) +#define DEF_SCALE NV30_FP_OP_DST_SCALE_1X +#define DEF_CTEST NV30_FP_OP_COND_TR +#include "nv30_shader.h" + +#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) +#define neg(s) nv30_sr_neg((s)) +#define abs(s) nv30_sr_abs((s)) +#define scale(s,v) nv30_sr_scale((s), NV30_FP_OP_DST_SCALE_##v) + +#define MAX_CONSTS 128 +#define MAX_IMM 32 +struct nv30_fpc { +	struct nv30_fragment_program *fp; + +	uint attrib_map[PIPE_MAX_SHADER_INPUTS]; + +	int high_temp; +	int temp_temp_count; +	int num_regs; + +	uint depth_id; +	uint colour_id; + +	unsigned inst_offset; + +	struct { +		int pipe; +		float vals[4]; +	} consts[MAX_CONSTS]; +	int nr_consts; + +	struct nv30_sreg imm[MAX_IMM]; +	unsigned nr_imm; +}; + +static INLINE struct nv30_sreg +temp(struct nv30_fpc *fpc) +{ +	int idx; + +	idx  = fpc->temp_temp_count++; +	idx += fpc->high_temp + 1; +	return nv30_sr(NV30SR_TEMP, idx); +} + +static INLINE struct nv30_sreg +constant(struct nv30_fpc *fpc, int pipe, float vals[4]) +{ +	int idx; + +	if (fpc->nr_consts == MAX_CONSTS) +		assert(0); +	idx = fpc->nr_consts++; + +	fpc->consts[idx].pipe = pipe; +	if (pipe == -1) +		memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float)); +	return nv30_sr(NV30SR_CONST, idx); +} + +#define arith(cc,s,o,d,m,s0,s1,s2) \ +	nv30_fp_arith((cc), (s), NV30_FP_OP_OPCODE_##o, \ +			(d), (m), (s0), (s1), (s2)) +#define tex(cc,s,o,u,d,m,s0,s1,s2) \ +	nv30_fp_tex((cc), (s), NV30_FP_OP_OPCODE_##o, (u), \ +		    (d), (m), (s0), none, none) + +static void +grow_insns(struct nv30_fpc *fpc, int size) +{ +	struct nv30_fragment_program *fp = fpc->fp; + +	fp->insn_len += size; +	fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len); +} + +static void +emit_src(struct nv30_fpc *fpc, int pos, struct nv30_sreg src) +{ +	struct nv30_fragment_program *fp = fpc->fp; +	uint32_t *hw = &fp->insn[fpc->inst_offset]; +	uint32_t sr = 0; + +	switch (src.type) { +	case NV30SR_INPUT: +		sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT); +		hw[0] |= (src.index << NV30_FP_OP_INPUT_SRC_SHIFT); +		break; +	case NV30SR_OUTPUT: +		sr |= NV30_FP_REG_SRC_HALF; +		/* fall-through */ +	case NV30SR_TEMP: +		sr |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT); +		sr |= (src.index << NV30_FP_REG_SRC_SHIFT); +		break; +	case NV30SR_CONST: +		grow_insns(fpc, 4); +		hw = &fp->insn[fpc->inst_offset]; +		if (fpc->consts[src.index].pipe >= 0) { +			struct nv30_fragment_program_data *fpd; + +			fp->consts = realloc(fp->consts, ++fp->nr_consts * +					     sizeof(*fpd)); +			fpd = &fp->consts[fp->nr_consts - 1]; +			fpd->offset = fpc->inst_offset + 4; +			fpd->index = fpc->consts[src.index].pipe; +			memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4); +		} else { +			memcpy(&fp->insn[fpc->inst_offset + 4], +				fpc->consts[src.index].vals, +				sizeof(uint32_t) * 4); +		} + +		sr |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT);	 +		break; +	case NV30SR_NONE: +		sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT); +		break; +	default: +		assert(0); +	} + +	if (src.negate) +		sr |= NV30_FP_REG_NEGATE; + +	if (src.abs) +		hw[1] |= (1 << (29 + pos)); + +	sr |= ((src.swz[0] << NV30_FP_REG_SWZ_X_SHIFT) | +	       (src.swz[1] << NV30_FP_REG_SWZ_Y_SHIFT) | +	       (src.swz[2] << NV30_FP_REG_SWZ_Z_SHIFT) | +	       (src.swz[3] << NV30_FP_REG_SWZ_W_SHIFT)); + +	hw[pos + 1] |= sr; +} + +static void +emit_dst(struct nv30_fpc *fpc, struct nv30_sreg dst) +{ +	struct nv30_fragment_program *fp = fpc->fp; +	uint32_t *hw = &fp->insn[fpc->inst_offset]; + +	switch (dst.type) { +	case NV30SR_TEMP: +		if (fpc->num_regs < (dst.index + 1)) +			fpc->num_regs = dst.index + 1; +		break; +	case NV30SR_OUTPUT: +		if (dst.index == 1) { +			fp->fp_control |= 0xe; +		} else { +			hw[0] |= NV30_FP_OP_OUT_REG_HALF; +		} +		break; +	case NV30SR_NONE: +		hw[0] |= (1 << 30); +		break; +	default: +		assert(0); +	} + +	hw[0] |= (dst.index << NV30_FP_OP_OUT_REG_SHIFT); +} + +static void +nv30_fp_arith(struct nv30_fpc *fpc, int sat, int op, +	      struct nv30_sreg dst, int mask, +	      struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2) +{ +	struct nv30_fragment_program *fp = fpc->fp; +	uint32_t *hw; + +	fpc->inst_offset = fp->insn_len; +	grow_insns(fpc, 4); +	hw = &fp->insn[fpc->inst_offset]; +	memset(hw, 0, sizeof(uint32_t) * 4); + +	if (op == NV30_FP_OP_OPCODE_KIL) +		fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL; +	hw[0] |= (op << NV30_FP_OP_OPCODE_SHIFT); +	hw[0] |= (mask << NV30_FP_OP_OUTMASK_SHIFT); +	hw[2] |= (dst.dst_scale << NV30_FP_OP_DST_SCALE_SHIFT); + +	if (sat) +		hw[0] |= NV30_FP_OP_OUT_SAT; + +	if (dst.cc_update) +		hw[0] |= NV30_FP_OP_COND_WRITE_ENABLE; +	hw[1] |= (dst.cc_test << NV30_FP_OP_COND_SHIFT); +	hw[1] |= ((dst.cc_swz[0] << NV30_FP_OP_COND_SWZ_X_SHIFT) | +		  (dst.cc_swz[1] << NV30_FP_OP_COND_SWZ_Y_SHIFT) | +		  (dst.cc_swz[2] << NV30_FP_OP_COND_SWZ_Z_SHIFT) | +		  (dst.cc_swz[3] << NV30_FP_OP_COND_SWZ_W_SHIFT)); + +	emit_dst(fpc, dst); +	emit_src(fpc, 0, s0); +	emit_src(fpc, 1, s1); +	emit_src(fpc, 2, s2); +} + +static void +nv30_fp_tex(struct nv30_fpc *fpc, int sat, int op, int unit, +	    struct nv30_sreg dst, int mask, +	    struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2) +{ +	struct nv30_fragment_program *fp = fpc->fp; + +	nv30_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); + +	fp->insn[fpc->inst_offset] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT); +	fp->samplers |= (1 << unit); +} + +static INLINE struct nv30_sreg +tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc) +{ +	struct nv30_sreg src; + +	switch (fsrc->SrcRegister.File) { +	case TGSI_FILE_INPUT: +		src = nv30_sr(NV30SR_INPUT, +			      fpc->attrib_map[fsrc->SrcRegister.Index]); +		break; +	case TGSI_FILE_CONSTANT: +		src = constant(fpc, fsrc->SrcRegister.Index, NULL); +		break; +	case TGSI_FILE_IMMEDIATE: +		assert(fsrc->SrcRegister.Index < fpc->nr_imm); +		src = fpc->imm[fsrc->SrcRegister.Index]; +		break; +	case TGSI_FILE_TEMPORARY: +		src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index + 1); +		if (fpc->high_temp < src.index) +			fpc->high_temp = src.index; +		break; +	/* This is clearly insane, but gallium hands us shaders like this. +	 * Luckily fragprog results are just temp regs.. +	 */ +	case TGSI_FILE_OUTPUT: +		if (fsrc->SrcRegister.Index == fpc->colour_id) +			return nv30_sr(NV30SR_OUTPUT, 0); +		else +			return nv30_sr(NV30SR_OUTPUT, 1); +		break; +	default: +		NOUVEAU_ERR("bad src file\n"); +		break; +	} + +	src.abs = fsrc->SrcRegisterExtMod.Absolute; +	src.negate = fsrc->SrcRegister.Negate; +	src.swz[0] = fsrc->SrcRegister.SwizzleX; +	src.swz[1] = fsrc->SrcRegister.SwizzleY; +	src.swz[2] = fsrc->SrcRegister.SwizzleZ; +	src.swz[3] = fsrc->SrcRegister.SwizzleW; +	return src; +} + +static INLINE struct nv30_sreg +tgsi_dst(struct nv30_fpc *fpc, const struct tgsi_full_dst_register *fdst) { +	int idx; + +	switch (fdst->DstRegister.File) { +	case TGSI_FILE_OUTPUT: +		if (fdst->DstRegister.Index == fpc->colour_id) +			return nv30_sr(NV30SR_OUTPUT, 0); +		else +			return nv30_sr(NV30SR_OUTPUT, 1); +		break; +	case TGSI_FILE_TEMPORARY: +		idx = fdst->DstRegister.Index + 1; +		if (fpc->high_temp < idx) +			fpc->high_temp = idx; +		return nv30_sr(NV30SR_TEMP, idx); +	case TGSI_FILE_NULL: +		return nv30_sr(NV30SR_NONE, 0); +	default: +		NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File); +		return nv30_sr(NV30SR_NONE, 0); +	} +} + +static INLINE int +tgsi_mask(uint tgsi) +{ +	int mask = 0; + +	if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; +	if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; +	if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; +	if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; +	return mask; +} + +static boolean +src_native_swz(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc, +	       struct nv30_sreg *src) +{ +	const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); +	struct nv30_sreg tgsi = tgsi_src(fpc, fsrc); +	uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0; +	uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX, +			fsrc->SrcRegisterExtSwz.NegateY, +			fsrc->SrcRegisterExtSwz.NegateZ, +			fsrc->SrcRegisterExtSwz.NegateW }; +	uint c; + +	for (c = 0; c < 4; c++) { +		switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) { +		case TGSI_EXTSWIZZLE_X: +		case TGSI_EXTSWIZZLE_Y: +		case TGSI_EXTSWIZZLE_Z: +		case TGSI_EXTSWIZZLE_W: +			mask |= (1 << c); +			break; +		case TGSI_EXTSWIZZLE_ZERO: +			zero_mask |= (1 << c); +			tgsi.swz[c] = SWZ_X; +			break; +		case TGSI_EXTSWIZZLE_ONE: +			one_mask |= (1 << c); +			tgsi.swz[c] = SWZ_X; +			break; +		default: +			assert(0); +		} + +		if (!tgsi.negate && neg[c]) +			neg_mask |= (1 << c); +	} + +	if (mask == MASK_ALL && !neg_mask) +		return TRUE; + +	*src = temp(fpc); + +	if (mask) +		arith(fpc, 0, MOV, *src, mask, tgsi, none, none); + +	if (zero_mask) +		arith(fpc, 0, SFL, *src, zero_mask, *src, none, none); + +	if (one_mask) +		arith(fpc, 0, STR, *src, one_mask, *src, none, none); + +	if (neg_mask) { +		struct nv30_sreg one = temp(fpc); +		arith(fpc, 0, STR, one, neg_mask, one, none, none); +		arith(fpc, 0, MUL, *src, neg_mask, *src, neg(one), none); +	} + +	return FALSE; +} + +static boolean +nv30_fragprog_parse_instruction(struct nv30_fpc *fpc, +				const struct tgsi_full_instruction *finst) +{ +	const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); +	struct nv30_sreg src[3], dst, tmp; +	int mask, sat, unit = 0; +	int ai = -1, ci = -1; +	int i; + +	if (finst->Instruction.Opcode == TGSI_OPCODE_END) +		return TRUE; + +	fpc->temp_temp_count = 0; +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; +		if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) { +			src[i] = tgsi_src(fpc, fsrc); +		} +	} + +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; + +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +		case TGSI_FILE_CONSTANT: +		case TGSI_FILE_TEMPORARY: +			if (!src_native_swz(fpc, fsrc, &src[i])) +				continue; +			break; +		default: +			break; +		} + +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +			if (ai == -1 || ai == fsrc->SrcRegister.Index) { +				ai = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(fpc, fsrc); +			} else { +				NOUVEAU_MSG("extra src attr %d\n", +					 fsrc->SrcRegister.Index); +				src[i] = temp(fpc); +				arith(fpc, 0, MOV, src[i], MASK_ALL, +				      tgsi_src(fpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_CONSTANT: +		case TGSI_FILE_IMMEDIATE: +			if (ci == -1 || ci == fsrc->SrcRegister.Index) { +				ci = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(fpc, fsrc); +			} else { +				src[i] = temp(fpc); +				arith(fpc, 0, MOV, src[i], MASK_ALL, +				      tgsi_src(fpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_TEMPORARY: +			/* handled above */ +			break; +		case TGSI_FILE_SAMPLER: +			unit = fsrc->SrcRegister.Index; +			break; +		case TGSI_FILE_OUTPUT: +			break; +		default: +			NOUVEAU_ERR("bad src file\n"); +			return FALSE; +		} +	} + +	dst  = tgsi_dst(fpc, &finst->FullDstRegisters[0]); +	mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask); +	sat  = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE); + +	switch (finst->Instruction.Opcode) { +	case TGSI_OPCODE_ABS: +		arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none); +		break; +	case TGSI_OPCODE_ADD: +		arith(fpc, sat, ADD, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_CMP: +		tmp = temp(fpc); +		arith(fpc, sat, MOV, dst, mask, src[2], none, none); +		tmp.cc_update = 1; +		arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none); +		dst.cc_test = NV30_VP_INST_COND_LT; +		arith(fpc, sat, MOV, dst, mask, src[1], none, none); +		break; +	case TGSI_OPCODE_COS: +		arith(fpc, sat, COS, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_DP3: +		arith(fpc, sat, DP3, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DP4: +		arith(fpc, sat, DP4, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DPH: +		tmp = temp(fpc); +		arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none); +		arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X), +		      swz(src[1], W, W, W, W), none); +		break; +	case TGSI_OPCODE_DST: +		arith(fpc, sat, DST, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_EX2: +		arith(fpc, sat, EX2, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_FLR: +		arith(fpc, sat, FLR, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_FRC: +		arith(fpc, sat, FRC, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_KIL: +		arith(fpc, 0, KIL, none, 0, none, none, none); +		break; +	case TGSI_OPCODE_KILP: +		dst = nv30_sr(NV30SR_NONE, 0); +		dst.cc_update = 1; +		arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none); +		dst.cc_update = 0; dst.cc_test = NV30_FP_OP_COND_LT; +		arith(fpc, 0, KIL, dst, 0, none, none, none); +		break; +	case TGSI_OPCODE_LG2: +		arith(fpc, sat, LG2, dst, mask, src[0], none, none); +		break; +//	case TGSI_OPCODE_LIT: +	case TGSI_OPCODE_LRP: +		arith(fpc, sat, LRP, dst, mask, src[0], src[1], src[2]); +		break; +	case TGSI_OPCODE_MAD: +		arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]); +		break; +	case TGSI_OPCODE_MAX: +		arith(fpc, sat, MAX, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MIN: +		arith(fpc, sat, MIN, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MOV: +		arith(fpc, sat, MOV, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_MUL: +		arith(fpc, sat, MUL, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_POW: +		arith(fpc, sat, POW, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_RCP: +		arith(fpc, sat, RCP, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_RET: +		assert(0); +		break; +	case TGSI_OPCODE_RFL: +		arith(fpc, 0, RFL, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_RSQ: +		arith(fpc, sat, RSQ, dst, mask, abs(swz(src[0], X, X, X, X)), none, none); +		break; +	case TGSI_OPCODE_SCS: +		if (mask & MASK_X) { +			arith(fpc, sat, COS, dst, MASK_X, +			      swz(src[0], X, X, X, X), none, none); +		} +		if (mask & MASK_Y) { +			arith(fpc, sat, SIN, dst, MASK_Y, +			      swz(src[0], X, X, X, X), none, none); +		} +		break; +	case TGSI_OPCODE_SIN: +		arith(fpc, sat, SIN, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_SGE: +		arith(fpc, sat, SGE, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SLT: +		arith(fpc, sat, SLT, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SUB: +		arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none); +		break; +	case TGSI_OPCODE_TEX: +		tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_TXB: +		tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_TXP: +		tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_XPD: +		tmp = temp(fpc); +		arith(fpc, 0, MUL, tmp, mask, +		      swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); +		arith(fpc, sat, MAD, dst, (mask & ~MASK_W), +		      swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), +		      neg(tmp)); +		break; +	default: +		NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); +		return FALSE; +	} + +	return TRUE; +} + +static boolean +nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc, +				const struct tgsi_full_declaration *fdec) +{ +	int hw; + +	switch (fdec->Semantic.SemanticName) { +	case TGSI_SEMANTIC_POSITION: +		hw = NV30_FP_OP_INPUT_SRC_POSITION; +		break; +	case TGSI_SEMANTIC_COLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV30_FP_OP_INPUT_SRC_COL0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV30_FP_OP_INPUT_SRC_COL1; +		} else { +			NOUVEAU_ERR("bad colour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_FOG: +		hw = NV30_FP_OP_INPUT_SRC_FOGC; +		break; +	case TGSI_SEMANTIC_GENERIC: +		if (fdec->Semantic.SemanticIndex <= 7) { +			hw = NV30_FP_OP_INPUT_SRC_TC(fdec->Semantic. +						     SemanticIndex); +		} else { +			NOUVEAU_ERR("bad generic semantic index\n"); +			return FALSE; +		} +		break; +	default: +		NOUVEAU_ERR("bad input semantic\n"); +		return FALSE; +	} + +	fpc->attrib_map[fdec->DeclarationRange.First] = hw; +	return TRUE; +} + +static boolean +nv30_fragprog_parse_decl_output(struct nv30_fpc *fpc, +				const struct tgsi_full_declaration *fdec) +{ +	switch (fdec->Semantic.SemanticName) { +	case TGSI_SEMANTIC_POSITION: +		fpc->depth_id = fdec->DeclarationRange.First; +		break; +	case TGSI_SEMANTIC_COLOR: +		fpc->colour_id = fdec->DeclarationRange.First; +		break; +	default: +		NOUVEAU_ERR("bad output semantic\n"); +		return FALSE; +	} + +	return TRUE; +} + +static boolean +nv30_fragprog_prepare(struct nv30_fpc *fpc) +{ +	struct tgsi_parse_context p; +	/*int high_temp = -1, i;*/ + +	tgsi_parse_init(&p, fpc->fp->pipe.tokens); +	while (!tgsi_parse_end_of_tokens(&p)) { +		const union tgsi_full_token *tok = &p.FullToken; + +		tgsi_parse_token(&p); +		switch(tok->Token.Type) { +		case TGSI_TOKEN_TYPE_DECLARATION: +		{ +			const struct tgsi_full_declaration *fdec; +			fdec = &p.FullToken.FullDeclaration; +			switch (fdec->Declaration.File) { +			case TGSI_FILE_INPUT: +				if (!nv30_fragprog_parse_decl_attrib(fpc, fdec)) +					goto out_err; +				break; +			case TGSI_FILE_OUTPUT: +				if (!nv30_fragprog_parse_decl_output(fpc, fdec)) +					goto out_err; +				break; +			/*case TGSI_FILE_TEMPORARY: +				if (fdec->DeclarationRange.Last > high_temp) { +					high_temp = +						fdec->DeclarationRange.Last; +				} +				break;*/ +			default: +				break; +			} +		} +			break; +		case TGSI_TOKEN_TYPE_IMMEDIATE: +		{ +			struct tgsi_full_immediate *imm; +			float vals[4]; +			 +			imm = &p.FullToken.FullImmediate; +			assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); +			assert(fpc->nr_imm < MAX_IMM); + +			vals[0] = imm->u.ImmediateFloat32[0].Float; +			vals[1] = imm->u.ImmediateFloat32[1].Float; +			vals[2] = imm->u.ImmediateFloat32[2].Float; +			vals[3] = imm->u.ImmediateFloat32[3].Float; +			fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals); +		} +			break; +		default: +			break; +		} +	} +	tgsi_parse_free(&p); + +	/*if (++high_temp) { +		fpc->r_temp = CALLOC(high_temp, sizeof(struct nv30_sreg)); +		for (i = 0; i < high_temp; i++) +			fpc->r_temp[i] = temp(fpc); +		fpc->r_temps_discard = 0; +	}*/ + +	return TRUE; + +out_err: +	/*if (fpc->r_temp) +		FREE(fpc->r_temp);*/ +	tgsi_parse_free(&p); +	return FALSE; +} + +static void +nv30_fragprog_translate(struct nv30_context *nv30, +			struct nv30_fragment_program *fp) +{ +	struct tgsi_parse_context parse; +	struct nv30_fpc *fpc = NULL; + +	fpc = CALLOC(1, sizeof(struct nv30_fpc)); +	if (!fpc) +		return; +	fpc->fp = fp; +	fpc->high_temp = -1; +	fpc->num_regs = 2; + +	if (!nv30_fragprog_prepare(fpc)) { +		FREE(fpc); +		return; +	} + +	tgsi_parse_init(&parse, fp->pipe.tokens); + +	while (!tgsi_parse_end_of_tokens(&parse)) { +		tgsi_parse_token(&parse); + +		switch (parse.FullToken.Token.Type) { +		case TGSI_TOKEN_TYPE_INSTRUCTION: +		{ +			const struct tgsi_full_instruction *finst; + +			finst = &parse.FullToken.FullInstruction; +			if (!nv30_fragprog_parse_instruction(fpc, finst)) +				goto out_err; +		} +			break; +		default: +			break; +		} +	} + +	fp->fp_control |= (fpc->num_regs-1)/2; +	fp->fp_reg_control = (1<<16)|0x4; + +	/* Terminate final instruction */ +	fp->insn[fpc->inst_offset] |= 0x00000001; + +	/* Append NOP + END instruction, may or may not be necessary. */ +	fpc->inst_offset = fp->insn_len; +	grow_insns(fpc, 4); +	fp->insn[fpc->inst_offset + 0] = 0x00000001; +	fp->insn[fpc->inst_offset + 1] = 0x00000000; +	fp->insn[fpc->inst_offset + 2] = 0x00000000; +	fp->insn[fpc->inst_offset + 3] = 0x00000000; +	 +	fp->translated = TRUE; +	fp->on_hw = FALSE; +out_err: +	tgsi_parse_free(&parse); +	FREE(fpc); +} + +static void +nv30_fragprog_upload(struct nv30_context *nv30, +		     struct nv30_fragment_program *fp) +{ +	struct pipe_winsys *ws = nv30->pipe.winsys; +	const uint32_t le = 1; +	uint32_t *map; +	int i; + +	map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); + +#if 0 +	for (i = 0; i < fp->insn_len; i++) { +		fflush(stdout); fflush(stderr); +		NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]); +		fflush(stdout); fflush(stderr); +	} +#endif + +	if ((*(const uint8_t *)&le)) { +		for (i = 0; i < fp->insn_len; i++) { +			map[i] = fp->insn[i]; +		} +	} else { +		/* Weird swapping for big-endian chips */ +		for (i = 0; i < fp->insn_len; i++) { +			map[i] = ((fp->insn[i] & 0xffff) << 16) | +				  ((fp->insn[i] >> 16) & 0xffff); +		} +	} + +	ws->buffer_unmap(ws, fp->buffer); +} + +static boolean +nv30_fragprog_validate(struct nv30_context *nv30) +{ +	struct nv30_fragment_program *fp = nv30->fragprog; +	struct pipe_buffer *constbuf = +		nv30->constbuf[PIPE_SHADER_FRAGMENT]; +	struct pipe_winsys *ws = nv30->pipe.winsys; +	struct nouveau_stateobj *so; +	boolean new_consts = FALSE; +	int i; + +	if (fp->translated) +		goto update_constants; + +	/*nv30->fallback_swrast &= ~NV30_NEW_FRAGPROG;*/ +	nv30_fragprog_translate(nv30, fp); +	if (!fp->translated) { +		/*nv30->fallback_swrast |= NV30_NEW_FRAGPROG;*/ +		return FALSE; +	} + +	fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4); +	nv30_fragprog_upload(nv30, fp); + +	so = so_new(6, 1); +	so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1); +	so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | +		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, +		  NV34TCL_FP_ACTIVE_PROGRAM_DMA0, NV34TCL_FP_ACTIVE_PROGRAM_DMA1); +	so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1); +	so_data  (so, fp->fp_control); +	so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1); +	so_data  (so, fp->fp_reg_control); +	so_ref(so, &fp->so); + +update_constants: +	if (fp->nr_consts) { +		float *map; +		 +		map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ); +		for (i = 0; i < fp->nr_consts; i++) { +			struct nv30_fragment_program_data *fpd = &fp->consts[i]; +			uint32_t *p = &fp->insn[fpd->offset]; +			uint32_t *cb = (uint32_t *)&map[fpd->index * 4]; + +			if (!memcmp(p, cb, 4 * sizeof(float))) +				continue; +			memcpy(p, cb, 4 * sizeof(float)); +			new_consts = TRUE; +		} +		ws->buffer_unmap(ws, constbuf); + +		if (new_consts) +			nv30_fragprog_upload(nv30, fp); +	} + +	if (new_consts || fp->so != nv30->state.hw[NV30_STATE_FRAGPROG]) { +		so_ref(fp->so, &nv30->state.hw[NV30_STATE_FRAGPROG]); +		return TRUE; +	} + +	return FALSE; +} + +void +nv30_fragprog_destroy(struct nv30_context *nv30, +		      struct nv30_fragment_program *fp) +{ +	if (fp->insn_len) +		FREE(fp->insn); +} + +struct nv30_state_entry nv30_state_fragprog = { +	.validate = nv30_fragprog_validate, +	.dirty = { +		.pipe = NV30_NEW_FRAGPROG, +		.hw = NV30_STATE_FRAGPROG +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c new file mode 100644 index 0000000000..4242f86f76 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_fragtex.c @@ -0,0 +1,183 @@ +#include "nv30_context.h" + +static INLINE int log2i(int i) +{ +	int r = 0; + +	if (i & 0xffff0000) { +		i >>= 16; +		r += 16; +	} +	if (i & 0x0000ff00) { +		i >>= 8; +		r += 8; +	} +	if (i & 0x000000f0) { +		i >>= 4; +		r += 4; +	} +	if (i & 0x0000000c) { +		i >>= 2; +		r += 2; +	} +	if (i & 0x00000002) { +		r += 1; +	} +	return r; +} + +#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)                        \ +{                                                                              \ +  TRUE,                                                                        \ +  PIPE_FORMAT_##m,                                                             \ +  NV34TCL_TX_FORMAT_FORMAT_##tf,                                               \ +  (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y |           \ +   NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w |           \ +   NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y |           \ +   NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w),           \ +} + +struct nv30_texture_format { +	boolean defined; +	uint	pipe; +	int     format; +	int     swizzle; +}; + +static struct nv30_texture_format +nv30_texture_formats[] = { +	_(A8R8G8B8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W), +	_(A1R5G5B5_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W), +	_(A4R4G4B4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W), +	_(R5G6B5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W), +	_(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X), +	_(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X), +	_(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X), +	_(A8L8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y), +//	_(Z16_UNORM     , Z16     ,   S1,   S1,   S1,  ONE, X, X, X, X), +//	_(Z24S8_UNORM   , Z24     ,   S1,   S1,   S1,  ONE, X, X, X, X), +	_(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W), +	_(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W), +	_(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W), +	_(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W), +	{}, +}; + +static struct nv30_texture_format * +nv30_fragtex_format(uint pipe_format) +{ +	struct nv30_texture_format *tf = nv30_texture_formats; +	char fs[128]; + +	while (tf->defined) { +		if (tf->pipe == pipe_format) +			return tf; +		tf++; +	} + +	pf_sprint_name(fs, pipe_format); +	NOUVEAU_ERR("unknown texture format %s\n", fs); +	return NULL; +} + + +static struct nouveau_stateobj * +nv30_fragtex_build(struct nv30_context *nv30, int unit) +{ +	struct nv30_sampler_state *ps = nv30->tex_sampler[unit]; +	struct nv30_miptree *nv30mt = nv30->tex_miptree[unit]; +	struct pipe_texture *pt = &nv30mt->base; +	struct nv30_texture_format *tf; +	struct nouveau_stateobj *so; +	uint32_t txf, txs /*, txp*/; +	/*int swizzled = 0;*/ /*XXX: implement in region code? */ +	unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + +	tf = nv30_fragtex_format(pt->format); +	if (!tf) +		assert(0); + +	txf  = tf->format; +	txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0); +	txf |= log2i(pt->width[0]) << 20; +	txf |= log2i(pt->height[0]) << 24; +	txf |= log2i(pt->depth[0]) << 28; +	txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000; + +	switch (pt->target) { +	case PIPE_TEXTURE_CUBE: +		txf |= NV34TCL_TX_FORMAT_CUBIC; +		/* fall-through */ +	case PIPE_TEXTURE_2D: +		txf |= NV34TCL_TX_FORMAT_DIMS_2D; +		break; +	case PIPE_TEXTURE_3D: +		txf |= NV34TCL_TX_FORMAT_DIMS_3D; +		break; +	case PIPE_TEXTURE_1D: +		txf |= NV34TCL_TX_FORMAT_DIMS_1D; +		break; +	default: +		NOUVEAU_ERR("Unknown target %d\n", pt->target); +		return NULL; +	} + +	txs = tf->swizzle; + +	so = so_new(16, 2); +	so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8); +	so_reloc (so, nv30mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); +	so_reloc (so, nv30mt->buffer, txf, tex_flags | NOUVEAU_BO_OR, +		  NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); +	so_data  (so, ps->wrap); +	so_data  (so, NV34TCL_TX_ENABLE_ENABLE | ps->en); +	so_data  (so, txs); +	so_data  (so, ps->filt | 0x2000 /*voodoo*/); +	so_data  (so, (pt->width[0] << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | +		       pt->height[0]); +	so_data  (so, ps->bcol); + +	return so; +} + +static boolean +nv30_fragtex_validate(struct nv30_context *nv30) +{ +	struct nv30_fragment_program *fp = nv30->fragprog; +	struct nv30_state *state = &nv30->state; +	struct nouveau_stateobj *so; +	unsigned samplers, unit; + +	samplers = state->fp_samplers & ~fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		so = so_new(2, 0); +		so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1); +		so_data  (so, 0); +		so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]); +		state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit)); +	} + +	samplers = nv30->dirty_samplers & fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		so = nv30_fragtex_build(nv30, unit); +		so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]); +		state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit)); +	} + +	nv30->state.fp_samplers = fp->samplers; +	return FALSE; +} + +struct nv30_state_entry nv30_state_fragtex = { +	.validate = nv30_fragtex_validate, +	.dirty = { +		.pipe = NV30_NEW_SAMPLER | NV30_NEW_FRAGPROG, +		.hw = 0 +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c new file mode 100644 index 0000000000..a0e488c09b --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_miptree.c @@ -0,0 +1,163 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "nv30_context.h" + +static void +nv30_miptree_layout(struct nv30_miptree *nv30mt) +{ +	struct pipe_texture *pt = &nv30mt->base; +	boolean swizzled = FALSE; +	uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0]; +	uint offset = 0; +	int nr_faces, l, f, pitch; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		nr_faces = 6; +	} else +	if (pt->target == PIPE_TEXTURE_3D) { +		nr_faces = pt->depth[0]; +	} else { +		nr_faces = 1; +	} +	 +	pitch = pt->width[0]; +	for (l = 0; l <= pt->last_level; l++) { +		pt->width[l] = width; +		pt->height[l] = height; +		pt->depth[l] = depth; +		pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); +		pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); + +		if (swizzled) +			pitch = pt->nblocksx[l]; +		pitch = align_int(pitch, 64); + +		nv30mt->level[l].pitch = pitch * pt->block.size; +		nv30mt->level[l].image_offset = +			CALLOC(nr_faces, sizeof(unsigned)); + +		width  = MAX2(1, width  >> 1); +		height = MAX2(1, height >> 1); +		depth  = MAX2(1, depth  >> 1); +	} + +	for (f = 0; f < nr_faces; f++) { +		for (l = 0; l <= pt->last_level; l++) { +			nv30mt->level[l].image_offset[f] = offset; +			offset += nv30mt->level[l].pitch * pt->height[l]; +		} +	} + +	nv30mt->total_size = offset; +} + +static struct pipe_texture * +nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv30_miptree *mt; + +	mt = MALLOC(sizeof(struct nv30_miptree)); +	if (!mt) +		return NULL; +	mt->base = *pt; +	mt->base.refcount = 1; +	mt->base.screen = pscreen; + +	nv30_miptree_layout(mt); + +	mt->buffer = ws->buffer_create(ws, 256, +				       PIPE_BUFFER_USAGE_PIXEL | +				       NOUVEAU_BUFFER_USAGE_TEXTURE, +				       mt->total_size); +	if (!mt->buffer) { +		FREE(mt); +		return NULL; +	} + +	return &mt->base; +} + +static void +nv30_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **pt) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct pipe_texture *mt = *pt; + +	*pt = NULL; +	if (--mt->refcount <= 0) { +		struct nv30_miptree *nv30mt = (struct nv30_miptree *)mt; +		int l; + +		pipe_buffer_reference(ws, &nv30mt->buffer, NULL); +		for (l = 0; l <= mt->last_level; l++) { +			if (nv30mt->level[l].image_offset) +				FREE(nv30mt->level[l].image_offset); +		} +		FREE(nv30mt); +	} +} + +static struct pipe_surface * +nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +			 unsigned face, unsigned level, unsigned zslice, +			 unsigned flags) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv30_miptree *nv30mt = (struct nv30_miptree *)pt; +	struct pipe_surface *ps; + +	ps = CALLOC_STRUCT(pipe_surface); +	if (!ps) +		return NULL; +	pipe_texture_reference(&ps->texture, pt); +	pipe_buffer_reference(ws, &ps->buffer, nv30mt->buffer); +	ps->format = pt->format; +	ps->width = pt->width[level]; +	ps->height = pt->height[level]; +	ps->block = pt->block; +	ps->nblocksx = pt->nblocksx[level]; +	ps->nblocksy = pt->nblocksy[level]; +	ps->stride = nv30mt->level[level].pitch; +	ps->usage = flags; +	ps->status = PIPE_SURFACE_STATUS_DEFINED; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		ps->offset = nv30mt->level[level].image_offset[face]; +	} else +	if (pt->target == PIPE_TEXTURE_3D) { +		ps->offset = nv30mt->level[level].image_offset[zslice]; +	} else { +		ps->offset = nv30mt->level[level].image_offset[0]; +	} + +	return ps; +} + +static void +nv30_miptree_surface_del(struct pipe_screen *pscreen, +			 struct pipe_surface **psurface) +{ +	struct pipe_surface *ps = *psurface; + +	*psurface = NULL; +	if (--ps->refcount > 0) +		return; + +	pipe_texture_reference(&ps->texture, NULL); +	pipe_buffer_reference(pscreen->winsys, &ps->buffer, NULL); +	FREE(ps); +} + +void +nv30_screen_init_miptree_functions(struct pipe_screen *pscreen) +{ +	pscreen->texture_create = nv30_miptree_create; +	pscreen->texture_release = nv30_miptree_release; +	pscreen->get_tex_surface = nv30_miptree_surface_new; +	pscreen->tex_surface_release = nv30_miptree_surface_del; +} + diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c new file mode 100644 index 0000000000..d40d75f264 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_query.c @@ -0,0 +1,122 @@ +#include "pipe/p_context.h" + +#include "nv30_context.h" + +struct nv30_query { +	struct nouveau_resource *object; +	unsigned type; +	boolean ready; +	uint64_t result; +}; + +static INLINE struct nv30_query * +nv30_query(struct pipe_query *pipe) +{ +	return (struct nv30_query *)pipe; +} + +static struct pipe_query * +nv30_query_create(struct pipe_context *pipe, unsigned query_type) +{ +	struct nv30_query *q; + +	q = CALLOC(1, sizeof(struct nv30_query)); +	q->type = query_type; + +	return (struct pipe_query *)q; +} + +static void +nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_query *q = nv30_query(pq); + +	if (q->object) +		nv30->nvws->res_free(&q->object); +	FREE(q); +} + +static void +nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_query *q = nv30_query(pq); + +	assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); + +	/* Happens when end_query() is called, then another begin_query() +	 * without querying the result in-between.  For now we'll wait for +	 * the existing query to notify completion, but it could be better. +	 */ +	if (q->object) { +		uint64 tmp; +		pipe->get_query_result(pipe, pq, 1, &tmp); +	} + +	if (nv30->nvws->res_alloc(nv30->screen->query_heap, 1, NULL, &q->object)) +		assert(0); +	nv30->nvws->notifier_reset(nv30->screen->query, q->object->start); + +	BEGIN_RING(rankine, NV34TCL_QUERY_RESET, 1); +	OUT_RING  (1); +	BEGIN_RING(rankine, NV34TCL_QUERY_UNK17CC, 1); +	OUT_RING  (1); + +	q->ready = FALSE; +} + +static void +nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_query *q = nv30_query(pq); + +	BEGIN_RING(rankine, NV34TCL_QUERY_GET, 1); +	OUT_RING  ((0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) | +		   ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT)); +	FIRE_RING(NULL); +} + +static boolean +nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq, +		  boolean wait, uint64 *result) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_query *q = nv30_query(pq); +	struct nouveau_winsys *nvws = nv30->nvws; + +	assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); + +	if (!q->ready) { +		unsigned status; + +		status = nvws->notifier_status(nv30->screen->query, +					       q->object->start); +		if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { +			if (wait == FALSE) +				return FALSE; +			nvws->notifier_wait(nv30->screen->query, q->object->start, +					    NV_NOTIFY_STATE_STATUS_COMPLETED, +					    0); +		} + +		q->result = nvws->notifier_retval(nv30->screen->query, +						  q->object->start); +		q->ready = TRUE; +		nvws->res_free(&q->object); +	} + +	*result = q->result; +	return TRUE; +} + +void +nv30_init_query_functions(struct nv30_context *nv30) +{ +	nv30->pipe.create_query = nv30_query_create; +	nv30->pipe.destroy_query = nv30_query_destroy; +	nv30->pipe.begin_query = nv30_query_begin; +	nv30->pipe.end_query = nv30_query_end; +	nv30->pipe.get_query_result = nv30_query_result; +} diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c new file mode 100644 index 0000000000..0ffcd77235 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -0,0 +1,329 @@ +#include "pipe/p_screen.h" +#include "pipe/p_util.h" + +#include "nv30_context.h" +#include "nv30_screen.h" + +#define NV30TCL_CHIPSET_3X_MASK 0x00000003 +#define NV34TCL_CHIPSET_3X_MASK 0x00000010 +#define NV35TCL_CHIPSET_3X_MASK 0x000001e0 + +static const char * +nv30_screen_get_name(struct pipe_screen *pscreen) +{ +	struct nv30_screen *screen = nv30_screen(pscreen); +	struct nouveau_device *dev = screen->nvws->channel->device; +	static char buffer[128]; + +	snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); +	return buffer; +} + +static const char * +nv30_screen_get_vendor(struct pipe_screen *pscreen) +{ +	return "nouveau"; +} + +static int +nv30_screen_get_param(struct pipe_screen *pscreen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: +		return 16; +	case PIPE_CAP_NPOT_TEXTURES: +		return 0; +	case PIPE_CAP_TWO_SIDED_STENCIL: +		return 1; +	case PIPE_CAP_GLSL: +		return 0; +	case PIPE_CAP_S3TC: +		return 0; +	case PIPE_CAP_ANISOTROPIC_FILTER: +		return 1; +	case PIPE_CAP_POINT_SPRITE: +		return 1; +	case PIPE_CAP_MAX_RENDER_TARGETS: +		return 2; +	case PIPE_CAP_OCCLUSION_QUERY: +		return 1; +	case PIPE_CAP_TEXTURE_SHADOW_MAP: +		return 1; +	case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: +		return 13; +	case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: +		return 10; +	case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: +		return 13; +	case NOUVEAU_CAP_HW_VTXBUF: +	case NOUVEAU_CAP_HW_IDXBUF: +		return 1; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0; +	} +} + +static float +nv30_screen_get_paramf(struct pipe_screen *pscreen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_LINE_WIDTH: +	case PIPE_CAP_MAX_LINE_WIDTH_AA: +		return 10.0; +	case PIPE_CAP_MAX_POINT_WIDTH: +	case PIPE_CAP_MAX_POINT_WIDTH_AA: +		return 64.0; +	case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: +		return 8.0; +	case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: +		return 4.0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0.0; +	} +} + +static boolean +nv30_screen_surface_format_supported(struct pipe_screen *pscreen, +				     enum pipe_format format, +				     enum pipe_texture_target target, +				     unsigned tex_usage, unsigned geom_flags) +{ +	if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM:  +		case PIPE_FORMAT_Z24S8_UNORM: +		case PIPE_FORMAT_Z16_UNORM: +			return TRUE; +		default: +			break; +		} +	} else { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_A1R5G5B5_UNORM: +		case PIPE_FORMAT_A4R4G4B4_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM:  +		case PIPE_FORMAT_L8_UNORM: +		case PIPE_FORMAT_A8_UNORM: +		case PIPE_FORMAT_I8_UNORM: +		case PIPE_FORMAT_A8L8_UNORM: +		case PIPE_FORMAT_Z16_UNORM: +		case PIPE_FORMAT_Z24S8_UNORM: +			return TRUE; +		default: +			break; +		} +	} + +	return FALSE; +} + +static void * +nv30_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, +		 unsigned flags ) +{ +	struct pipe_winsys *ws = screen->winsys; +	void *map; + +	map = ws->buffer_map(ws, surface->buffer, flags); +	if (!map) +		return NULL; + +	return map + surface->offset; +} + +static void +nv30_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) +{ +	struct pipe_winsys *ws = screen->winsys; + +	ws->buffer_unmap(ws, surface->buffer); +} + +static void +nv30_screen_destroy(struct pipe_screen *pscreen) +{ +	struct nv30_screen *screen = nv30_screen(pscreen); +	struct nouveau_winsys *nvws = screen->nvws; + +	nvws->res_free(&screen->vp_exec_heap); +	nvws->res_free(&screen->vp_data_heap); +	nvws->res_free(&screen->query_heap); +	nvws->notifier_free(&screen->query); +	nvws->notifier_free(&screen->sync); +	nvws->grobj_free(&screen->rankine); + +	FREE(pscreen); +} + +struct pipe_screen * +nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +{ +	struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen); +	struct nouveau_stateobj *so; +	unsigned rankine_class = 0; +	unsigned chipset = nvws->channel->device->chipset; +	int ret, i; + +	if (!screen) +		return NULL; +	screen->nvws = nvws; + +	/* 3D object */ +	switch (chipset & 0xf0) { +	case 0x30: +		if (NV30TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) +			rankine_class = 0x0397; +		else +		if (NV34TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) +			rankine_class = 0x0697; +		else +		if (NV35TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) +			rankine_class = 0x0497; +		break; +	default: +		break; +	} + +	if (!rankine_class) { +		NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", chipset); +		return NULL; +	} + +	ret = nvws->grobj_alloc(nvws, rankine_class, &screen->rankine); +	if (ret) { +		NOUVEAU_ERR("Error creating 3D object: %d\n", ret); +		return FALSE; +	} + +	/* Notifier for sync purposes */ +	ret = nvws->notifier_alloc(nvws, 1, &screen->sync); +	if (ret) { +		NOUVEAU_ERR("Error creating notifier object: %d\n", ret); +		nv30_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Query objects */ +	ret = nvws->notifier_alloc(nvws, 32, &screen->query); +	if (ret) { +		NOUVEAU_ERR("Error initialising query objects: %d\n", ret); +		nv30_screen_destroy(&screen->pipe); +		return NULL; +	} + +	ret = nvws->res_init(&screen->query_heap, 0, 32); +	if (ret) { +		NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); +		nv30_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Vtxprog resources */ +	if (nvws->res_init(&screen->vp_exec_heap, 0, 256) || +	    nvws->res_init(&screen->vp_data_heap, 0, 256)) { +		nv30_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Static rankine initialisation */ +	so = so_new(128, 0); +	so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1); +	so_data  (so, screen->sync->handle); +	so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->gart->handle); +	so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1); +	so_data  (so, nvws->channel->vram->handle); +	so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->vram->handle); +	so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->gart->handle); +/*	so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2); +	so_data  (so, 0); +	so_data  (so, screen->query->handle);*/ +	so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1); +	so_data  (so, nvws->channel->vram->handle); +	so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1); +	so_data  (so, nvws->channel->vram->handle); + +	for (i=1; i<8; i++) { +		so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1); +		so_data  (so, 0); +		so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1); +		so_data  (so, 0); +	} + +	so_method(so, screen->rankine, 0x220, 1); +	so_data  (so, 1); + +	so_method(so, screen->rankine, 0x03b0, 1); +	so_data  (so, 0x00100000); +	so_method(so, screen->rankine, 0x1454, 1); +	so_data  (so, 0); +	so_method(so, screen->rankine, 0x1d80, 1); +	so_data  (so, 3); +	so_method(so, screen->rankine, 0x1450, 1); +	so_data  (so, 0x00030004); +	 +	/* NEW */ +	so_method(so, screen->rankine, 0x1e98, 1); +	so_data  (so, 0); +	so_method(so, screen->rankine, 0x17e0, 3); +	so_data  (so, fui(0.0)); +	so_data  (so, fui(0.0)); +	so_data  (so, fui(1.0)); +	so_method(so, screen->rankine, 0x1f80, 16); +	for (i=0; i<16; i++) { +		so_data  (so, (i==8) ? 0x0000ffff : 0); +	} + +	so_method(so, screen->rankine, 0x120, 3); +	so_data  (so, 0); +	so_data  (so, 1); +	so_data  (so, 2); + +	so_method(so, screen->rankine, 0x1d88, 1); +	so_data  (so, 0x00001200); + +	so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1); +	so_data  (so, 0); + +	so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2); +	so_data  (so, fui(0.0)); +	so_data  (so, fui(1.0)); + +	so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1); +	so_data  (so, 0xffff0000); + +	/* enables use of vp rather than fixed-function somehow */ +	so_method(so, screen->rankine, 0x1e94, 1); +	so_data  (so, 0x13); + +	so_emit(nvws, so); +	so_ref(NULL, &so); +	nvws->push_flush(nvws, 0, NULL); + +	screen->pipe.winsys = ws; +	screen->pipe.destroy = nv30_screen_destroy; + +	screen->pipe.get_name = nv30_screen_get_name; +	screen->pipe.get_vendor = nv30_screen_get_vendor; +	screen->pipe.get_param = nv30_screen_get_param; +	screen->pipe.get_paramf = nv30_screen_get_paramf; + +	screen->pipe.is_format_supported = nv30_screen_surface_format_supported; + +	screen->pipe.surface_map = nv30_surface_map; +	screen->pipe.surface_unmap = nv30_surface_unmap; + +	nv30_screen_init_miptree_functions(&screen->pipe); + +	return &screen->pipe; +} + diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h new file mode 100644 index 0000000000..b7ddc2a959 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -0,0 +1,35 @@ +#ifndef __NV30_SCREEN_H__ +#define __NV30_SCREEN_H__ + +#include "pipe/p_screen.h" + +struct nv30_screen { +	struct pipe_screen pipe; + +	struct nouveau_winsys *nvws; + +	unsigned cur_pctx; + +	/* HW graphics objects */ +	struct nouveau_grobj *rankine; +	struct nouveau_notifier *sync; + +	/* Query object resources */ +	struct nouveau_notifier *query; +	struct nouveau_resource *query_heap; + +	/* Vtxprog resources */ +	struct nouveau_resource *vp_exec_heap; +	struct nouveau_resource *vp_data_heap; + +	/* Current 3D state of channel */ +	struct nouveau_stateobj *state[NV30_STATE_MAX]; +}; + +static INLINE struct nv30_screen * +nv30_screen(struct pipe_screen *screen) +{ +	return (struct nv30_screen *)screen; +} + +#endif diff --git a/src/gallium/drivers/nv30/nv30_shader.h b/src/gallium/drivers/nv30/nv30_shader.h new file mode 100644 index 0000000000..dd3a36f78f --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_shader.h @@ -0,0 +1,490 @@ +#ifndef __NV30_SHADER_H__ +#define __NV30_SHADER_H__ + +/* Vertex programs instruction set + * + * 128bit opcodes, split into 4 32-bit ones for ease of use. + * + * Non-native instructions + *   ABS - MOV + NV40_VP_INST0_DEST_ABS + *   POW - EX2 + MUL + LG2 + *   SUB - ADD, second source negated + *   SWZ - MOV + *   XPD -   + * + * Register access + *   - Only one INPUT can be accessed per-instruction (move extras into TEMPs) + *   - Only one CONST can be accessed per-instruction (move extras into TEMPs) + * + * Relative Addressing + *   According to the value returned for + *   MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB + * + *   there are only two address registers available.  The destination in the + *   ARL instruction is set to TEMP <n> (The temp isn't actually written). + * + *   When using vanilla ARB_v_p, the proprietary driver will squish both the + *   available ADDRESS regs into the first hardware reg in the X and Y + *   components. + * + *   To use an address reg as an index into consts, the CONST_SRC is set to + *   (const_base + offset) and INDEX_CONST is set. + * + *   To access the second address reg use ADDR_REG_SELECT_1. A particular + *   component of the address regs is selected with ADDR_SWZ. + * + *   Only one address register can be accessed per instruction. + * + * Conditional execution (see NV_vertex_program{2,3} for details) Conditional + * execution of an instruction is enabled by setting COND_TEST_ENABLE, and + * selecting the condition which will allow the test to pass with + * COND_{FL,LT,...}.  It is possible to swizzle the values in the condition + * register, which allows for testing against an individual component. + * + * Branching: + * + *   The BRA/CAL instructions seem to follow a slightly different opcode + *   layout.  The destination instruction ID (IADDR) overlaps a source field. + *   Instruction ID's seem to be numbered based on the UPLOAD_FROM_ID FIFO + *   command, and is incremented automatically on each UPLOAD_INST FIFO + *   command. + * + *   Conditional branching is achieved by using the condition tests described + *   above.  There doesn't appear to be dedicated looping instructions, but + *   this can be done using a temp reg + conditional branching. + * + *   Subroutines may be uploaded before the main program itself, but the first + *   executed instruction is determined by the PROGRAM_START_ID FIFO command. + * + */ + +/* DWORD 0 */ + +#define NV30_VP_INST_ADDR_REG_SELECT_1        (1 << 24) +#define NV30_VP_INST_SRC2_ABS           (1 << 23) /* guess */ +#define NV30_VP_INST_SRC1_ABS           (1 << 22) /* guess */ +#define NV30_VP_INST_SRC0_ABS           (1 << 21) /* guess */ +#define NV30_VP_INST_VEC_RESULT         (1 << 20) +#define NV30_VP_INST_DEST_TEMP_ID_SHIFT        16 +#define NV30_VP_INST_DEST_TEMP_ID_MASK        (0x0F << 16) +#define NV30_VP_INST_COND_UPDATE_ENABLE        (1<<15) +#define NV30_VP_INST_VEC_DEST_TEMP_MASK      (0xF << 16) +#define NV30_VP_INST_COND_TEST_ENABLE        (1<<14) +#define NV30_VP_INST_COND_SHIFT          11 +#define NV30_VP_INST_COND_MASK          (0x07 << 11) +#  define NV30_VP_INST_COND_FL  0 /* guess */   +#  define NV30_VP_INST_COND_LT  1   +#  define NV30_VP_INST_COND_EQ  2 +#  define NV30_VP_INST_COND_LE  3 +#  define NV30_VP_INST_COND_GT  4 +#  define NV30_VP_INST_COND_NE  5 +#  define NV30_VP_INST_COND_GE  6 +#  define NV30_VP_INST_COND_TR  7 /* guess */ +#define NV30_VP_INST_COND_SWZ_X_SHIFT        9 +#define NV30_VP_INST_COND_SWZ_X_MASK        (0x03 <<  9) +#define NV30_VP_INST_COND_SWZ_Y_SHIFT        7 +#define NV30_VP_INST_COND_SWZ_Y_MASK        (0x03 <<  7) +#define NV30_VP_INST_COND_SWZ_Z_SHIFT        5 +#define NV30_VP_INST_COND_SWZ_Z_MASK        (0x03 <<  5) +#define NV30_VP_INST_COND_SWZ_W_SHIFT        3 +#define NV30_VP_INST_COND_SWZ_W_MASK        (0x03 <<  3) +#define NV30_VP_INST_COND_SWZ_ALL_SHIFT        3 +#define NV30_VP_INST_COND_SWZ_ALL_MASK        (0xFF <<  3) +#define NV30_VP_INST_ADDR_SWZ_SHIFT        1 +#define NV30_VP_INST_ADDR_SWZ_MASK        (0x03 <<  1) +#define NV30_VP_INST_SCA_OPCODEH_SHIFT        0 +#define NV30_VP_INST_SCA_OPCODEH_MASK        (0x01 <<  0) + +/* DWORD 1 */ +#define NV30_VP_INST_SCA_OPCODEL_SHIFT        28 +#define NV30_VP_INST_SCA_OPCODEL_MASK        (0x0F << 28) +#  define NV30_VP_INST_OP_NOP  0x00 +#  define NV30_VP_INST_OP_RCP  0x02 +#  define NV30_VP_INST_OP_RCC  0x03 +#  define NV30_VP_INST_OP_RSQ  0x04 +#  define NV30_VP_INST_OP_EXP  0x05 +#  define NV30_VP_INST_OP_LOG  0x06 +#  define NV30_VP_INST_OP_LIT  0x07 +#  define NV30_VP_INST_OP_BRA  0x09 +#  define NV30_VP_INST_OP_CAL  0x0B +#  define NV30_VP_INST_OP_RET  0x0C +#  define NV30_VP_INST_OP_LG2  0x0D +#  define NV30_VP_INST_OP_EX2  0x0E +#  define NV30_VP_INST_OP_SIN  0x0F +#  define NV30_VP_INST_OP_COS  0x10 +#define NV30_VP_INST_VEC_OPCODE_SHIFT        23 +#define NV30_VP_INST_VEC_OPCODE_MASK        (0x1F << 23) +#  define NV30_VP_INST_OP_NOPV  0x00 +#  define NV30_VP_INST_OP_MOV  0x01 +#  define NV30_VP_INST_OP_MUL  0x02 +#  define NV30_VP_INST_OP_ADD  0x03 +#  define NV30_VP_INST_OP_MAD  0x04 +#  define NV30_VP_INST_OP_DP3  0x05 +#  define NV30_VP_INST_OP_DP4  0x07 +#  define NV30_VP_INST_OP_DPH  0x06 +#  define NV30_VP_INST_OP_DST  0x08 +#  define NV30_VP_INST_OP_MIN  0x09 +#  define NV30_VP_INST_OP_MAX  0x0A +#  define NV30_VP_INST_OP_SLT  0x0B +#  define NV30_VP_INST_OP_SGE  0x0C +#  define NV30_VP_INST_OP_ARL  0x0D +#  define NV30_VP_INST_OP_FRC  0x0E +#  define NV30_VP_INST_OP_FLR  0x0F +#  define NV30_VP_INST_OP_SEQ  0x10 +#  define NV30_VP_INST_OP_SFL  0x11 +#  define NV30_VP_INST_OP_SGT  0x12 +#  define NV30_VP_INST_OP_SLE  0x13 +#  define NV30_VP_INST_OP_SNE  0x14 +#  define NV30_VP_INST_OP_STR  0x15 +#  define NV30_VP_INST_OP_SSG  0x16 +#  define NV30_VP_INST_OP_ARR  0x17 +#  define NV30_VP_INST_OP_ARA  0x18 +#define NV30_VP_INST_CONST_SRC_SHIFT        14 +#define NV30_VP_INST_CONST_SRC_MASK        (0xFF << 14) +#define NV30_VP_INST_INPUT_SRC_SHIFT        9    /*NV20*/ +#define NV30_VP_INST_INPUT_SRC_MASK        (0x0F <<  9)  /*NV20*/ +#  define NV30_VP_INST_IN_POS  0    /* These seem to match the bindings specified in */ +#  define NV30_VP_INST_IN_WEIGHT  1    /* the ARB_v_p spec (2.14.3.1) */ +#  define NV30_VP_INST_IN_NORMAL  2     +#  define NV30_VP_INST_IN_COL0  3    /* Should probably confirm them all though */ +#  define NV30_VP_INST_IN_COL1  4 +#  define NV30_VP_INST_IN_FOGC  5 +#  define NV30_VP_INST_IN_TC0  8 +#  define NV30_VP_INST_IN_TC(n)  (8+n) +#define NV30_VP_INST_SRC0H_SHIFT        0    /*NV20*/ +#define NV30_VP_INST_SRC0H_MASK          (0x1FF << 0)  /*NV20*/ + +/* Please note: the IADDR fields overlap other fields because they are used + * only for branch instructions.  See Branching: label above + * + * DWORD 2 + */ +#define NV30_VP_INST_SRC0L_SHIFT        26    /*NV20*/ +#define NV30_VP_INST_SRC0L_MASK         (0x3F  <<26)  /* NV30_VP_SRC0_LOW_MASK << 26 */ +#define NV30_VP_INST_SRC1_SHIFT         11    /*NV20*/ +#define NV30_VP_INST_SRC1_MASK          (0x7FFF<<11)  /*NV20*/ +#define NV30_VP_INST_SRC2H_SHIFT        0    /*NV20*/ +#define NV30_VP_INST_SRC2H_MASK          (0x7FF << 0)  /* NV30_VP_SRC2_HIGH_MASK >> 4*/ +#define NV30_VP_INST_IADDR_SHIFT        2 +#define NV30_VP_INST_IADDR_MASK          (0xF <<  28)   /* NV30_VP_SRC2_LOW_MASK << 28 */ + +/* DWORD 3 */ +#define NV30_VP_INST_SRC2L_SHIFT        28    /*NV20*/ +#define NV30_VP_INST_SRC2L_MASK          (0x0F  <<28)  /*NV20*/ +#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT      24 +#define NV30_VP_INST_STEMP_WRITEMASK_MASK      (0x0F << 24) +#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT      20 +#define NV30_VP_INST_VTEMP_WRITEMASK_MASK      (0x0F << 20) +#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT      16 +#define NV30_VP_INST_SDEST_WRITEMASK_MASK      (0x0F << 16) +#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT      12    /*NV20*/ +#define NV30_VP_INST_VDEST_WRITEMASK_MASK      (0x0F << 12)  /*NV20*/ +#define NV30_VP_INST_DEST_SHIFT        2 +#define NV30_VP_INST_DEST_MASK        (0x0F <<  2) +#  define NV30_VP_INST_DEST_POS  0 +#  define NV30_VP_INST_DEST_BFC0  1 +#  define NV30_VP_INST_DEST_BFC1  2 +#  define NV30_VP_INST_DEST_COL0  3 +#  define NV30_VP_INST_DEST_COL1  4 +#  define NV30_VP_INST_DEST_FOGC  5 +#  define NV30_VP_INST_DEST_PSZ   6 +#  define NV30_VP_INST_DEST_TC(n)  (8+n) + +#define NV30_VP_INST_LAST                           (1 << 0) + +/* Useful to split the source selection regs into their pieces */ +#define NV30_VP_SRC0_HIGH_SHIFT                                                6 +#define NV30_VP_SRC0_HIGH_MASK                                        0x00007FC0 +#define NV30_VP_SRC0_LOW_MASK                                         0x0000003F +#define NV30_VP_SRC2_HIGH_SHIFT                                                4 +#define NV30_VP_SRC2_HIGH_MASK                                        0x00007FF0 +#define NV30_VP_SRC2_LOW_MASK                                         0x0000000F + + +/* Source-register definition - matches NV20 exactly */ +#define NV30_VP_SRC_NEGATE          (1<<14) +#define NV30_VP_SRC_SWZ_X_SHIFT        12 +#define NV30_VP_SRC_REG_SWZ_X_MASK        (0x03  <<12) +#define NV30_VP_SRC_SWZ_Y_SHIFT        10 +#define NV30_VP_SRC_REG_SWZ_Y_MASK        (0x03  <<10) +#define NV30_VP_SRC_SWZ_Z_SHIFT        8 +#define NV30_VP_SRC_REG_SWZ_Z_MASK        (0x03  << 8) +#define NV30_VP_SRC_SWZ_W_SHIFT        6 +#define NV30_VP_SRC_REG_SWZ_W_MASK        (0x03  << 6) +#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT        6 +#define NV30_VP_SRC_REG_SWZ_ALL_MASK        (0xFF  << 6) +#define NV30_VP_SRC_TEMP_SRC_SHIFT        2 +#define NV30_VP_SRC_REG_TEMP_ID_MASK        (0x0F  << 0) +#define NV30_VP_SRC_REG_TYPE_SHIFT        0 +#define NV30_VP_SRC_REG_TYPE_MASK        (0x03  << 0) +#define NV30_VP_SRC_REG_TYPE_TEMP  1 +#define NV30_VP_SRC_REG_TYPE_INPUT  2 +#define NV30_VP_SRC_REG_TYPE_CONST  3 /* guess */ + +/* + * Each fragment program opcode appears to be comprised of 4 32-bit values. + * + *   0 - Opcode, output reg/mask, ATTRIB source + *   1 - Source 0 + *   2 - Source 1 + *   3 - Source 2 + * + * There appears to be no special difference between result regs and temp regs. + *     result.color == R0.xyzw + *     result.depth == R1.z + * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0 + * otherwise it is set to 1. + * + * Constants are inserted directly after the instruction that uses them. + *  + * It appears that it's not possible to use two input registers in one + * instruction as the input sourcing is done in the instruction dword + * and not the source selection dwords.  As such instructions such as: + *  + *     ADD result.color, fragment.color, fragment.texcoord[0]; + * + * must be split into two MOV's and then an ADD (nvidia does this) but + * I'm not sure why it's not just one MOV and then source the second input + * in the ADD instruction.. + * + * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary + * negation requires multiplication with a const. + * + * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE + * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO + * is implemented simply by not writing to the relevant components of the destination. + * + * Conditional execution + *   TODO + *  + * Non-native instructions: + *   LIT + *   LRP - MAD+MAD + *   SUB - ADD, negate second source + *   RSQ - LG2 + EX2 + *   POW - LG2 + MUL + EX2 + *   SCS - COS + SIN + *   XPD + */ + +//== Opcode / Destination selection == +#define NV30_FP_OP_PROGRAM_END          (1 << 0) +#define NV30_FP_OP_OUT_REG_SHIFT        1 +#define NV30_FP_OP_OUT_REG_MASK          (31 << 1)  /* uncertain */ +/* Needs to be set when writing outputs to get expected result.. */ +#define NV30_FP_OP_OUT_REG_HALF          (1 << 7) +#define NV30_FP_OP_COND_WRITE_ENABLE        (1 << 8) +#define NV30_FP_OP_OUTMASK_SHIFT        9 +#define NV30_FP_OP_OUTMASK_MASK          (0xF << 9) +#  define NV30_FP_OP_OUT_X  (1<<9) +#  define NV30_FP_OP_OUT_Y  (1<<10) +#  define NV30_FP_OP_OUT_Z  (1<<11) +#  define NV30_FP_OP_OUT_W  (1<<12) +/* Uncertain about these, especially the input_src values.. it's possible that + * they can be dynamically changed. + */ +#define NV30_FP_OP_INPUT_SRC_SHIFT        13 +#define NV30_FP_OP_INPUT_SRC_MASK        (15 << 13) +#  define NV30_FP_OP_INPUT_SRC_POSITION  0x0 +#  define NV30_FP_OP_INPUT_SRC_COL0  0x1 +#  define NV30_FP_OP_INPUT_SRC_COL1  0x2 +#  define NV30_FP_OP_INPUT_SRC_FOGC  0x3 +#  define NV30_FP_OP_INPUT_SRC_TC0    0x4 +#  define NV30_FP_OP_INPUT_SRC_TC(n)  (0x4 + n) +#define NV30_FP_OP_TEX_UNIT_SHIFT        17 +#define NV30_FP_OP_TEX_UNIT_MASK        (0xF << 17) /* guess */ +#define NV30_FP_OP_PRECISION_SHIFT        22 +#define NV30_FP_OP_PRECISION_MASK        (3 << 22) +#   define NV30_FP_PRECISION_FP32  0 +#   define NV30_FP_PRECISION_FP16  1 +#   define NV30_FP_PRECISION_FX12  2 +#define NV30_FP_OP_OPCODE_SHIFT          24 +#define NV30_FP_OP_OPCODE_MASK          (0x3F << 24) +#  define NV30_FP_OP_OPCODE_NOP  0x00 +#  define NV30_FP_OP_OPCODE_MOV  0x01 +#  define NV30_FP_OP_OPCODE_MUL  0x02 +#  define NV30_FP_OP_OPCODE_ADD  0x03 +#  define NV30_FP_OP_OPCODE_MAD  0x04 +#  define NV30_FP_OP_OPCODE_DP3  0x05 +#  define NV30_FP_OP_OPCODE_DP4  0x06 +#  define NV30_FP_OP_OPCODE_DST  0x07 +#  define NV30_FP_OP_OPCODE_MIN  0x08 +#  define NV30_FP_OP_OPCODE_MAX  0x09 +#  define NV30_FP_OP_OPCODE_SLT  0x0A +#  define NV30_FP_OP_OPCODE_SGE  0x0B +#  define NV30_FP_OP_OPCODE_SLE  0x0C +#  define NV30_FP_OP_OPCODE_SGT  0x0D +#  define NV30_FP_OP_OPCODE_SNE  0x0E +#  define NV30_FP_OP_OPCODE_SEQ  0x0F +#  define NV30_FP_OP_OPCODE_FRC  0x10 +#  define NV30_FP_OP_OPCODE_FLR  0x11 +#  define NV30_FP_OP_OPCODE_KIL  0x12 +#  define NV30_FP_OP_OPCODE_PK4B   0x13 +#  define NV30_FP_OP_OPCODE_UP4B   0x14 +#  define NV30_FP_OP_OPCODE_DDX  0x15 /* can only write XY */ +#  define NV30_FP_OP_OPCODE_DDY  0x16 /* can only write XY */ +#  define NV30_FP_OP_OPCODE_TEX  0x17 +#  define NV30_FP_OP_OPCODE_TXP  0x18 +#  define NV30_FP_OP_OPCODE_TXD  0x19 +#  define NV30_FP_OP_OPCODE_RCP  0x1A +#  define NV30_FP_OP_OPCODE_RSQ  0x1B +#  define NV30_FP_OP_OPCODE_EX2  0x1C +#  define NV30_FP_OP_OPCODE_LG2  0x1D +#  define NV30_FP_OP_OPCODE_LIT  0x1E +#  define NV30_FP_OP_OPCODE_LRP  0x1F +#  define NV30_FP_OP_OPCODE_STR  0x20  +#  define NV30_FP_OP_OPCODE_SFL  0x21 +#  define NV30_FP_OP_OPCODE_COS  0x22 +#  define NV30_FP_OP_OPCODE_SIN  0x23 +#  define NV30_FP_OP_OPCODE_PK2H   0x24 +#  define NV30_FP_OP_OPCODE_UP2H   0x25 +#  define NV30_FP_OP_OPCODE_POW  0x26 +#  define NV30_FP_OP_OPCODE_PK4UB  0x27 +#  define NV30_FP_OP_OPCODE_UP4UB  0x28 +#  define NV30_FP_OP_OPCODE_PK2US  0x29 +#  define NV30_FP_OP_OPCODE_UP2US  0x2A +#  define NV30_FP_OP_OPCODE_DP2A   0x2E +#  define NV30_FP_OP_OPCODE_TXB  0x31 +#  define NV30_FP_OP_OPCODE_RFL  0x36 +#  define NV30_FP_OP_OPCODE_DIV  0x3A +#define NV30_FP_OP_OUT_SAT          (1 << 31) + +/* high order bits of SRC0 */ +#define NV30_FP_OP_OUT_ABS          (1 << 29) +#define NV30_FP_OP_COND_SWZ_W_SHIFT        27 +#define NV30_FP_OP_COND_SWZ_W_MASK        (3 << 27) +#define NV30_FP_OP_COND_SWZ_Z_SHIFT        25 +#define NV30_FP_OP_COND_SWZ_Z_MASK        (3 << 25) +#define NV30_FP_OP_COND_SWZ_Y_SHIFT        23 +#define NV30_FP_OP_COND_SWZ_Y_MASK        (3 << 23) +#define NV30_FP_OP_COND_SWZ_X_SHIFT        21 +#define NV30_FP_OP_COND_SWZ_X_MASK        (3 << 21) +#define NV30_FP_OP_COND_SWZ_ALL_SHIFT        21 +#define NV30_FP_OP_COND_SWZ_ALL_MASK        (0xFF << 21) +#define NV30_FP_OP_COND_SHIFT          18 +#define NV30_FP_OP_COND_MASK          (0x07 << 18) +#  define NV30_FP_OP_COND_FL  0 +#  define NV30_FP_OP_COND_LT  1 +#  define NV30_FP_OP_COND_EQ  2 +#  define NV30_FP_OP_COND_LE  3 +#  define NV30_FP_OP_COND_GT  4 +#  define NV30_FP_OP_COND_NE  5 +#  define NV30_FP_OP_COND_GE  6 +#  define NV30_FP_OP_COND_TR  7 + +/* high order bits of SRC1 */ +#define NV30_FP_OP_DST_SCALE_SHIFT        28 +#define NV30_FP_OP_DST_SCALE_MASK        (3 << 28) +#define NV30_FP_OP_DST_SCALE_1X                                                0 +#define NV30_FP_OP_DST_SCALE_2X                                                1 +#define NV30_FP_OP_DST_SCALE_4X                                                2 +#define NV30_FP_OP_DST_SCALE_8X                                                3 +#define NV30_FP_OP_DST_SCALE_INV_2X                                            5 +#define NV30_FP_OP_DST_SCALE_INV_4X                                            6 +#define NV30_FP_OP_DST_SCALE_INV_8X                                            7 + + +/* high order bits of SRC2 */ +#define NV30_FP_OP_INDEX_INPUT          (1 << 30) + +//== Register selection == +#define NV30_FP_REG_TYPE_SHIFT          0 +#define NV30_FP_REG_TYPE_MASK          (3 << 0) +#  define NV30_FP_REG_TYPE_TEMP  0 +#  define NV30_FP_REG_TYPE_INPUT  1 +#  define NV30_FP_REG_TYPE_CONST  2 +#define NV30_FP_REG_SRC_SHIFT          2 /* uncertain */ +#define NV30_FP_REG_SRC_MASK          (31 << 2) +#define NV30_FP_REG_SRC_HALF          (1 << 8) +#define NV30_FP_REG_SWZ_ALL_SHIFT        9 +#define NV30_FP_REG_SWZ_ALL_MASK        (255 << 9) +#define NV30_FP_REG_SWZ_X_SHIFT          9 +#define NV30_FP_REG_SWZ_X_MASK          (3 << 9) +#define NV30_FP_REG_SWZ_Y_SHIFT          11 +#define NV30_FP_REG_SWZ_Y_MASK          (3 << 11) +#define NV30_FP_REG_SWZ_Z_SHIFT          13 +#define NV30_FP_REG_SWZ_Z_MASK          (3 << 13) +#define NV30_FP_REG_SWZ_W_SHIFT          15 +#define NV30_FP_REG_SWZ_W_MASK          (3 << 15) +#  define NV30_FP_SWIZZLE_X  0 +#  define NV30_FP_SWIZZLE_Y  1 +#  define NV30_FP_SWIZZLE_Z  2 +#  define NV30_FP_SWIZZLE_W  3 +#define NV30_FP_REG_NEGATE          (1 << 17) + +#define NV30SR_NONE	0 +#define NV30SR_OUTPUT	1 +#define NV30SR_INPUT	2 +#define NV30SR_TEMP	3 +#define NV30SR_CONST	4 + +struct nv30_sreg { +	int type; +	int index; + +	int dst_scale; + +	int negate; +	int abs; +	int swz[4]; + +	int cc_update; +	int cc_update_reg; +	int cc_test; +	int cc_test_reg; +	int cc_swz[4]; +}; + +static INLINE struct nv30_sreg +nv30_sr(int type, int index) +{ +	struct nv30_sreg temp = { +		.type = type, +		.index = index, +		.dst_scale = DEF_SCALE, +		.abs = 0, +		.negate = 0, +		.swz = { 0, 1, 2, 3 }, +		.cc_update = 0, +		.cc_update_reg = 0, +		.cc_test = DEF_CTEST, +		.cc_test_reg = 0, +		.cc_swz = { 0, 1, 2, 3 }, +	}; +	return temp; +} + +static INLINE struct nv30_sreg +nv30_sr_swz(struct nv30_sreg src, int x, int y, int z, int w) +{ +	struct nv30_sreg dst = src; + +	dst.swz[SWZ_X] = src.swz[x]; +	dst.swz[SWZ_Y] = src.swz[y]; +	dst.swz[SWZ_Z] = src.swz[z]; +	dst.swz[SWZ_W] = src.swz[w]; +	return dst; +} + +static INLINE struct nv30_sreg +nv30_sr_neg(struct nv30_sreg src) +{ +	src.negate = !src.negate; +	return src; +} + +static INLINE struct nv30_sreg +nv30_sr_abs(struct nv30_sreg src) +{ +	src.abs = 1; +	return src; +} + +static INLINE struct nv30_sreg +nv30_sr_scale(struct nv30_sreg src, int scale) +{ +	src.dst_scale = scale; +	return src; +} + +#endif diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c new file mode 100644 index 0000000000..8d88d6c806 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state.c @@ -0,0 +1,723 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "tgsi/tgsi_parse.h" + +#include "nv30_context.h" +#include "nv30_state.h" + +static void * +nv30_blend_state_create(struct pipe_context *pipe, +			const struct pipe_blend_state *cso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nouveau_grobj *rankine = nv30->screen->rankine; +	struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso)); +	struct nouveau_stateobj *so = so_new(16, 0); + +	if (cso->blend_enable) { +		so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3); +		so_data  (so, 1); +		so_data  (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) | +			       nvgl_blend_func(cso->rgb_src_factor)); +		so_data  (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 | +			      nvgl_blend_func(cso->rgb_dst_factor)); +		so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1); +		so_data  (so, nvgl_blend_eqn(cso->alpha_func) << 16 | +			      nvgl_blend_eqn(cso->rgb_func)); +	} else { +		so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_method(so, rankine, NV34TCL_COLOR_MASK, 1); +	so_data  (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | +		       ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | +		       ((cso->colormask & PIPE_MASK_G) ? (0x01 <<  8) : 0) | +		       ((cso->colormask & PIPE_MASK_B) ? (0x01 <<  0) : 0))); + +	if (cso->logicop_enable) { +		so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2); +		so_data  (so, 1); +		so_data  (so, nvgl_logicop_func(cso->logicop_func)); +	} else { +		so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_method(so, rankine, NV34TCL_DITHER_ENABLE, 1); +	so_data  (so, cso->dither ? 1 : 0); + +	so_ref(so, &bso->so); +	bso->pipe = *cso; +	return (void *)bso; +} + +static void +nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->blend = hwcso; +	nv30->dirty |= NV30_NEW_BLEND; +} + +static void +nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_blend_state *bso = hwcso; + +	so_ref(NULL, &bso->so); +	FREE(bso); +} + + +static INLINE unsigned +wrap_mode(unsigned wrap) { +	unsigned ret; + +	switch (wrap) { +	case PIPE_TEX_WRAP_REPEAT: +		ret = NV34TCL_TX_WRAP_S_REPEAT; +		break; +	case PIPE_TEX_WRAP_MIRROR_REPEAT: +		ret = NV34TCL_TX_WRAP_S_MIRRORED_REPEAT; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_EDGE: +		ret = NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_BORDER: +		ret = NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER; +		break; +	case PIPE_TEX_WRAP_CLAMP: +		ret = NV34TCL_TX_WRAP_S_CLAMP; +		break; +/*	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: +		ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_EDGE; +		break; +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: +		ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_BORDER; +		break; +	case PIPE_TEX_WRAP_MIRROR_CLAMP: +		ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP; +		break;*/ +	default: +		NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); +		ret = NV34TCL_TX_WRAP_S_REPEAT; +		break; +	} + +	return ret >> NV34TCL_TX_WRAP_S_SHIFT; +} + +static void * +nv30_sampler_state_create(struct pipe_context *pipe, +			  const struct pipe_sampler_state *cso) +{ +	struct nv30_sampler_state *ps; +	uint32_t filter = 0; + +	ps = MALLOC(sizeof(struct nv30_sampler_state)); + +	ps->fmt = 0; +	/* TODO: Not all RECTs formats have this bit set, bits 15-8 of format +	   are the tx format to use. We should store normalized coord flag +	   in sampler state structure, and set appropriate format in +	   nvxx_fragtex_build() +	 */ +	if (!cso->normalized_coords) +		ps->fmt |= (1<<14) /*NV34TCL_TX_FORMAT_RECT*/; + +	ps->wrap = ((wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) | +		    (wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) | +		    (wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT)); + +	ps->en = 0; + +	if (cso->max_anisotropy >= 8.0) { +		ps->en |= NV34TCL_TX_ENABLE_ANISO_8X; +	} else +	if (cso->max_anisotropy >= 4.0) { +		ps->en |= NV34TCL_TX_ENABLE_ANISO_4X; +	} else +	if (cso->max_anisotropy >= 2.0) { +		ps->en |= NV34TCL_TX_ENABLE_ANISO_2X; +	} + +	switch (cso->mag_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		filter |= NV34TCL_TX_FILTER_MAGNIFY_LINEAR; +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		filter |= NV34TCL_TX_FILTER_MAGNIFY_NEAREST; +		break; +	} + +	switch (cso->min_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; +			break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR; +			break; +		} +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; +		break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST; +			break; +		} +		break; +	} + +	ps->filt = filter; + +	{ +		float limit; + +		limit = CLAMP(cso->lod_bias, -16.0, 15.0); +		ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + +		limit = CLAMP(cso->max_lod, 0.0, 15.0); +		ps->en |= (int)(limit * 256.0) << 7; + +		limit = CLAMP(cso->min_lod, 0.0, 15.0); +		ps->en |= (int)(limit * 256.0) << 19; +	} + +	if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +		switch (cso->compare_func) { +		case PIPE_FUNC_NEVER: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NEVER; +			break; +		case PIPE_FUNC_GREATER: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GREATER; +			break; +		case PIPE_FUNC_EQUAL: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_EQUAL; +			break; +		case PIPE_FUNC_GEQUAL: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GEQUAL; +			break; +		case PIPE_FUNC_LESS: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LESS; +			break; +		case PIPE_FUNC_NOTEQUAL: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NOTEQUAL; +			break; +		case PIPE_FUNC_LEQUAL: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LEQUAL; +			break; +		case PIPE_FUNC_ALWAYS: +			ps->wrap |= NV34TCL_TX_WRAP_RCOMP_ALWAYS; +			break; +		default: +			break; +		} +	} + +	ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | +		    (float_to_ubyte(cso->border_color[0]) << 16) | +		    (float_to_ubyte(cso->border_color[1]) <<  8) | +		    (float_to_ubyte(cso->border_color[2]) <<  0)); + +	return (void *)ps; +} + +static void +nv30_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv30->tex_sampler[unit] = sampler[unit]; +		nv30->dirty_samplers |= (1 << unit); +	} + +	for (unit = nr; unit < nv30->nr_samplers; unit++) { +		nv30->tex_sampler[unit] = NULL; +		nv30->dirty_samplers |= (1 << unit); +	} + +	nv30->nr_samplers = nr; +	nv30->dirty |= NV30_NEW_SAMPLER; +} + +static void +nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void +nv30_set_sampler_texture(struct pipe_context *pipe, unsigned nr, +			 struct pipe_texture **miptree) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		pipe_texture_reference((struct pipe_texture **) +				       &nv30->tex_miptree[unit], miptree[unit]); +		nv30->dirty_samplers |= (1 << unit); +	} + +	for (unit = nr; unit < nv30->nr_textures; unit++) { +		pipe_texture_reference((struct pipe_texture **) +				       &nv30->tex_miptree[unit], NULL); +		nv30->dirty_samplers |= (1 << unit); +	} + +	nv30->nr_textures = nr; +	nv30->dirty |= NV30_NEW_SAMPLER; +} + +static void * +nv30_rasterizer_state_create(struct pipe_context *pipe, +			     const struct pipe_rasterizer_state *cso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); +	struct nouveau_stateobj *so = so_new(32, 0); +	struct nouveau_grobj *rankine = nv30->screen->rankine; + +	/*XXX: ignored: +	 * 	light_twoside +	 * 	point_smooth -nohw +	 * 	multisample +	 */ + +	so_method(so, rankine, NV34TCL_SHADE_MODEL, 1); +	so_data  (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT : +				       NV34TCL_SHADE_MODEL_SMOOTH); + +	so_method(so, rankine, NV34TCL_LINE_WIDTH, 2); +	so_data  (so, (unsigned char)(cso->line_width * 8.0) & 0xff); +	so_data  (so, cso->line_smooth ? 1 : 0); +	so_method(so, rankine, NV34TCL_LINE_STIPPLE_ENABLE, 2); +	so_data  (so, cso->line_stipple_enable ? 1 : 0); +	so_data  (so, (cso->line_stipple_pattern << 16) | +		       cso->line_stipple_factor); + +	so_method(so, rankine, NV34TCL_POINT_SIZE, 1); +	so_data  (so, fui(cso->point_size)); + +	so_method(so, rankine, NV34TCL_POLYGON_MODE_FRONT, 6); +	if (cso->front_winding == PIPE_WINDING_CCW) { +		so_data(so, nvgl_polygon_mode(cso->fill_ccw)); +		so_data(so, nvgl_polygon_mode(cso->fill_cw)); +		switch (cso->cull_mode) { +		case PIPE_WINDING_CCW: +			so_data(so, NV34TCL_CULL_FACE_FRONT); +			break; +		case PIPE_WINDING_CW: +			so_data(so, NV34TCL_CULL_FACE_BACK); +			break; +		case PIPE_WINDING_BOTH: +			so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); +			break; +		default: +			so_data(so, NV34TCL_CULL_FACE_BACK); +			break; +		} +		so_data(so, NV34TCL_FRONT_FACE_CCW); +	} else { +		so_data(so, nvgl_polygon_mode(cso->fill_cw)); +		so_data(so, nvgl_polygon_mode(cso->fill_ccw)); +		switch (cso->cull_mode) { +		case PIPE_WINDING_CCW: +			so_data(so, NV34TCL_CULL_FACE_BACK); +			break; +		case PIPE_WINDING_CW: +			so_data(so, NV34TCL_CULL_FACE_FRONT); +			break; +		case PIPE_WINDING_BOTH: +			so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); +			break; +		default: +			so_data(so, NV34TCL_CULL_FACE_BACK); +			break; +		} +		so_data(so, NV34TCL_FRONT_FACE_CW); +	} +	so_data(so, cso->poly_smooth ? 1 : 0); +	so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); + +	so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); +	so_data  (so, cso->poly_stipple_enable ? 1 : 0); + +	so_method(so, rankine, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if (cso->offset_cw || cso->offset_ccw) { +		so_method(so, rankine, NV34TCL_POLYGON_OFFSET_FACTOR, 2); +		so_data  (so, fui(cso->offset_scale)); +		so_data  (so, fui(cso->offset_units * 2)); +	} + +	so_method(so, rankine, NV34TCL_POINT_SPRITE, 1); +	if (cso->point_sprite) { +		unsigned psctl = (1 << 0), i; + +		for (i = 0; i < 8; i++) { +			if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE) +				psctl |= (1 << (8 + i)); +		} + +		so_data(so, psctl); +	} else { +		so_data(so, 0); +	} + +	so_ref(so, &rsso->so); +	rsso->pipe = *cso; +	return (void *)rsso; +} + +static void +nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->rasterizer = hwcso; +	nv30->dirty |= NV30_NEW_RAST; +	/*nv30->draw_dirty |= NV30_NEW_RAST;*/ +} + +static void +nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_rasterizer_state *rsso = hwcso; + +	so_ref(NULL, &rsso->so); +	FREE(rsso); +} + +static void * +nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe, +			const struct pipe_depth_stencil_alpha_state *cso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); +	struct nouveau_stateobj *so = so_new(32, 0); +	struct nouveau_grobj *rankine = nv30->screen->rankine; + +	so_method(so, rankine, NV34TCL_DEPTH_FUNC, 3); +	so_data  (so, nvgl_comparison_op(cso->depth.func)); +	so_data  (so, cso->depth.writemask ? 1 : 0); +	so_data  (so, cso->depth.enabled ? 1 : 0); + +	so_method(so, rankine, NV34TCL_ALPHA_FUNC_ENABLE, 3); +	so_data  (so, cso->alpha.enabled ? 1 : 0); +	so_data  (so, nvgl_comparison_op(cso->alpha.func)); +	so_data  (so, float_to_ubyte(cso->alpha.ref)); + +	if (cso->stencil[0].enabled) { +		so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 8); +		so_data  (so, cso->stencil[0].enabled ? 1 : 0); +		so_data  (so, cso->stencil[0].write_mask); +		so_data  (so, nvgl_comparison_op(cso->stencil[0].func)); +		so_data  (so, cso->stencil[0].ref_value); +		so_data  (so, cso->stencil[0].value_mask); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].fail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); +	} else { +		so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 1); +		so_data  (so, 0); +	} + +	if (cso->stencil[1].enabled) { +		so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 8); +		so_data  (so, cso->stencil[1].enabled ? 1 : 0); +		so_data  (so, cso->stencil[1].write_mask); +		so_data  (so, nvgl_comparison_op(cso->stencil[1].func)); +		so_data  (so, cso->stencil[1].ref_value); +		so_data  (so, cso->stencil[1].value_mask); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].fail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); +	} else { +		so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_ref(so, &zsaso->so); +	zsaso->pipe = *cso; +	return (void *)zsaso; +} + +static void +nv30_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->zsa = hwcso; +	nv30->dirty |= NV30_NEW_ZSA; +} + +static void +nv30_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_zsa_state *zsaso = hwcso; + +	so_ref(NULL, &zsaso->so); +	FREE(zsaso); +} + +static void * +nv30_vp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	/*struct nv30_context *nv30 = nv30_context(pipe);*/ +	struct nv30_vertex_program *vp; + +	vp = CALLOC(1, sizeof(struct nv30_vertex_program)); +	vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); +	/*vp->draw = draw_create_vertex_shader(nv30->draw, &vp->pipe);*/ + +	return (void *)vp; +} + +static void +nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->vertprog = hwcso; +	nv30->dirty |= NV30_NEW_VERTPROG; +	/*nv30->draw_dirty |= NV30_NEW_VERTPROG;*/ +} + +static void +nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_vertex_program *vp = hwcso; + +	/*draw_delete_vertex_shader(nv30->draw, vp->draw);*/ +	nv30_vertprog_destroy(nv30, vp); +	FREE((void*)vp->pipe.tokens); +	FREE(vp); +} + +static void * +nv30_fp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv30_fragment_program *fp; + +	fp = CALLOC(1, sizeof(struct nv30_fragment_program)); +	fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + +	tgsi_scan_shader(fp->pipe.tokens, &fp->info); + +	return (void *)fp; +} + +static void +nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->fragprog = hwcso; +	nv30->dirty |= NV30_NEW_FRAGPROG; +} + +static void +nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nv30_fragment_program *fp = hwcso; + +	nv30_fragprog_destroy(nv30, fp); +	FREE((void*)fp->pipe.tokens); +	FREE(fp); +} + +static void +nv30_set_blend_color(struct pipe_context *pipe, +		     const struct pipe_blend_color *bcol) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->blend_colour = *bcol; +	nv30->dirty |= NV30_NEW_BCOL; +} + +static void +nv30_set_clip_state(struct pipe_context *pipe, +		    const struct pipe_clip_state *clip) +{ +} + +static void +nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, +			 const struct pipe_constant_buffer *buf ) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->constbuf[shader] = buf->buffer; +	nv30->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); + +	if (shader == PIPE_SHADER_VERTEX) { +		nv30->dirty |= NV30_NEW_VERTPROG; +	} else +	if (shader == PIPE_SHADER_FRAGMENT) { +		nv30->dirty |= NV30_NEW_FRAGPROG; +	} +} + +static void +nv30_set_framebuffer_state(struct pipe_context *pipe, +			   const struct pipe_framebuffer_state *fb) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->framebuffer = *fb; +	nv30->dirty |= NV30_NEW_FB; +} + +static void +nv30_set_polygon_stipple(struct pipe_context *pipe, +			 const struct pipe_poly_stipple *stipple) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	memcpy(nv30->stipple, stipple->stipple, 4 * 32); +	nv30->dirty |= NV30_NEW_STIPPLE; +} + +static void +nv30_set_scissor_state(struct pipe_context *pipe, +		       const struct pipe_scissor_state *s) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->scissor = *s; +	nv30->dirty |= NV30_NEW_SCISSOR; +} + +static void +nv30_set_viewport_state(struct pipe_context *pipe, +			const struct pipe_viewport_state *vpt) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->viewport = *vpt; +	nv30->dirty |= NV30_NEW_VIEWPORT; +	/*nv30->draw_dirty |= NV30_NEW_VIEWPORT;*/ +} + +static void +nv30_set_vertex_buffers(struct pipe_context *pipe, unsigned count, +			const struct pipe_vertex_buffer *vb) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count); +	nv30->vtxbuf_nr = count; + +	nv30->dirty |= NV30_NEW_ARRAYS; +	/*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ +} + +static void +nv30_set_vertex_elements(struct pipe_context *pipe, unsigned count, +			 const struct pipe_vertex_element *ve) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	memcpy(nv30->vtxelt, ve, sizeof(*ve) * count); +	nv30->vtxelt_nr = count; + +	nv30->dirty |= NV30_NEW_ARRAYS; +	/*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ +} + +static void +nv30_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) +{ +	struct nv30_context *nv30 = nv30_context(pipe); + +	nv30->edgeflags = bitfield; +	nv30->dirty |= NV30_NEW_ARRAYS; +	/*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ +} + +void +nv30_init_state_functions(struct nv30_context *nv30) +{ +	nv30->pipe.create_blend_state = nv30_blend_state_create; +	nv30->pipe.bind_blend_state = nv30_blend_state_bind; +	nv30->pipe.delete_blend_state = nv30_blend_state_delete; + +	nv30->pipe.create_sampler_state = nv30_sampler_state_create; +	nv30->pipe.bind_sampler_states = nv30_sampler_state_bind; +	nv30->pipe.delete_sampler_state = nv30_sampler_state_delete; +	nv30->pipe.set_sampler_textures = nv30_set_sampler_texture; + +	nv30->pipe.create_rasterizer_state = nv30_rasterizer_state_create; +	nv30->pipe.bind_rasterizer_state = nv30_rasterizer_state_bind; +	nv30->pipe.delete_rasterizer_state = nv30_rasterizer_state_delete; + +	nv30->pipe.create_depth_stencil_alpha_state = +		nv30_depth_stencil_alpha_state_create; +	nv30->pipe.bind_depth_stencil_alpha_state = +		nv30_depth_stencil_alpha_state_bind; +	nv30->pipe.delete_depth_stencil_alpha_state = +		nv30_depth_stencil_alpha_state_delete; + +	nv30->pipe.create_vs_state = nv30_vp_state_create; +	nv30->pipe.bind_vs_state = nv30_vp_state_bind; +	nv30->pipe.delete_vs_state = nv30_vp_state_delete; + +	nv30->pipe.create_fs_state = nv30_fp_state_create; +	nv30->pipe.bind_fs_state = nv30_fp_state_bind; +	nv30->pipe.delete_fs_state = nv30_fp_state_delete; + +	nv30->pipe.set_blend_color = nv30_set_blend_color; +	nv30->pipe.set_clip_state = nv30_set_clip_state; +	nv30->pipe.set_constant_buffer = nv30_set_constant_buffer; +	nv30->pipe.set_framebuffer_state = nv30_set_framebuffer_state; +	nv30->pipe.set_polygon_stipple = nv30_set_polygon_stipple; +	nv30->pipe.set_scissor_state = nv30_set_scissor_state; +	nv30->pipe.set_viewport_state = nv30_set_viewport_state; + +	nv30->pipe.set_edgeflags = nv30_set_edgeflags; +	nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers; +	nv30->pipe.set_vertex_elements = nv30_set_vertex_elements; +} + diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h new file mode 100644 index 0000000000..e6f23bf166 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state.h @@ -0,0 +1,85 @@ +#ifndef __NV30_STATE_H__ +#define __NV30_STATE_H__ + +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" + +struct nv30_sampler_state { +	uint32_t fmt; +	uint32_t wrap; +	uint32_t en; +	uint32_t filt; +	uint32_t bcol; +}; + +struct nv30_vertex_program_exec { +	uint32_t data[4]; +	boolean has_branch_offset; +	int const_index; +}; + +struct nv30_vertex_program_data { +	int index; /* immediates == -1 */ +	float value[4]; +}; + +struct nv30_vertex_program { +	struct pipe_shader_state pipe; + +	boolean translated; + +	struct nv30_vertex_program_exec *insns; +	unsigned nr_insns; +	struct nv30_vertex_program_data *consts; +	unsigned nr_consts; + +	struct nouveau_resource *exec; +	unsigned exec_start; +	struct nouveau_resource *data; +	unsigned data_start; +	unsigned data_start_min; + +	uint32_t ir; +	uint32_t or; +	struct nouveau_stateobj *so; +}; + +struct nv30_fragment_program_data { +	unsigned offset; +	unsigned index; +}; + +struct nv30_fragment_program { +	struct pipe_shader_state pipe; +	struct tgsi_shader_info info; + +	boolean translated; +	boolean on_hw; +	unsigned samplers; + +	uint32_t *insn; +	int       insn_len; + +	struct nv30_fragment_program_data *consts; +	unsigned nr_consts; + +	struct pipe_buffer *buffer; + +	uint32_t fp_control; +	uint32_t fp_reg_control; +	struct nouveau_stateobj *so; +}; + +struct nv30_miptree { +	struct pipe_texture base; + +	struct pipe_buffer *buffer; +	uint total_size; + +	struct { +		uint pitch; +		uint *image_offset; +	} level[PIPE_MAX_TEXTURE_LEVELS]; +}; + +#endif diff --git a/src/gallium/drivers/nv30/nv30_state_blend.c b/src/gallium/drivers/nv30/nv30_state_blend.c new file mode 100644 index 0000000000..44d43e132a --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_blend.c @@ -0,0 +1,40 @@ +#include "nv30_context.h" + +static boolean +nv30_state_blend_validate(struct nv30_context *nv30) +{ +	so_ref(nv30->blend->so, &nv30->state.hw[NV30_STATE_BLEND]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_blend = { +	.validate = nv30_state_blend_validate, +	.dirty = { +		.pipe = NV30_NEW_BLEND, +		.hw = NV30_STATE_BLEND +	} +}; + +static boolean +nv30_state_blend_colour_validate(struct nv30_context *nv30) +{ +	struct nouveau_stateobj *so = so_new(2, 0); +	struct pipe_blend_color *bcol = &nv30->blend_colour; + +	so_method(so, nv30->screen->rankine, NV34TCL_BLEND_COLOR, 1); +	so_data  (so, ((float_to_ubyte(bcol->color[3]) << 24) | +		       (float_to_ubyte(bcol->color[0]) << 16) | +		       (float_to_ubyte(bcol->color[1]) <<  8) | +		       (float_to_ubyte(bcol->color[2]) <<  0))); + +	so_ref(so, &nv30->state.hw[NV30_STATE_BCOL]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_blend_colour = { +	.validate = nv30_state_blend_colour_validate, +	.dirty = { +		.pipe = NV30_NEW_BCOL, +		.hw = NV30_STATE_BCOL +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c new file mode 100644 index 0000000000..40fed621b2 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_emit.c @@ -0,0 +1,118 @@ +#include "nv30_context.h" +#include "nv30_state.h" + +static struct nv30_state_entry *render_states[] = { +	&nv30_state_framebuffer, +	&nv30_state_rasterizer, +	&nv30_state_scissor, +	&nv30_state_stipple, +	&nv30_state_fragprog, +	&nv30_state_fragtex, +	&nv30_state_vertprog, +	&nv30_state_blend, +	&nv30_state_blend_colour, +	&nv30_state_zsa, +	&nv30_state_viewport, +	&nv30_state_vbo, +	NULL +}; + +static void +nv30_state_do_validate(struct nv30_context *nv30, +		       struct nv30_state_entry **states) +{ +	const struct pipe_framebuffer_state *fb = &nv30->framebuffer; +	unsigned i; + +	for (i = 0; i < fb->num_cbufs; i++) +		fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED; +	if (fb->zsbuf) +		fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED; + +	while (*states) { +		struct nv30_state_entry *e = *states; + +		if (nv30->dirty & e->dirty.pipe) { +			if (e->validate(nv30)) { +				nv30->state.dirty |= (1ULL << e->dirty.hw); +			} +		} + +		states++; +	} +	nv30->dirty = 0; +} + +void +nv30_state_emit(struct nv30_context *nv30) +{ +	struct nv30_state *state = &nv30->state; +	struct nv30_screen *screen = nv30->screen; +	unsigned i, samplers; +	uint64 states; + +	if (nv30->pctx_id != screen->cur_pctx) { +		for (i = 0; i < NV30_STATE_MAX; i++) { +			if (state->hw[i] && screen->state[i] != state->hw[i]) +				state->dirty |= (1ULL << i); +		} + +		screen->cur_pctx = nv30->pctx_id; +	} + +	for (i = 0, states = state->dirty; states; i++) { +		if (!(states & (1ULL << i))) +			continue; +		so_ref (state->hw[i], &nv30->screen->state[i]); +		if (state->hw[i]) +			so_emit(nv30->nvws, nv30->screen->state[i]); +		states &= ~(1ULL << i); +	} + +	state->dirty = 0; + +	so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FB]); +	for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { +		if (!(samplers & (1 << i))) +			continue; +		so_emit_reloc_markers(nv30->nvws, +				      state->hw[NV30_STATE_FRAGTEX0+i]); +		samplers &= ~(1ULL << i); +	} +	so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FRAGPROG]); +	if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/) +		so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_VTXBUF]); +} + +boolean +nv30_state_validate(struct nv30_context *nv30) +{ +#if 0 +	boolean was_sw = nv30->fallback_swtnl ? TRUE : FALSE; + +	if (nv30->render_mode != HW) { +		/* Don't even bother trying to go back to hw if none +		 * of the states that caused swtnl previously have changed. +		 */ +		if ((nv30->fallback_swtnl & nv30->dirty) +				!= nv30->fallback_swtnl) +			return FALSE; + +		/* Attempt to go to hwtnl again */ +		nv30->pipe.flush(&nv30->pipe, 0, NULL); +		nv30->dirty |= (NV30_NEW_VIEWPORT | +				NV30_NEW_VERTPROG | +				NV30_NEW_ARRAYS); +		nv30->render_mode = HW; +	} +#endif +	nv30_state_do_validate(nv30, render_states); +#if 0 +	if (nv30->fallback_swtnl || nv30->fallback_swrast) +		return FALSE; +	 +	if (was_sw) +		NOUVEAU_ERR("swtnl->hw\n"); +#endif +	return TRUE; +} diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c new file mode 100644 index 0000000000..d93e2bb5c8 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_fb.c @@ -0,0 +1,128 @@ +#include "nv30_context.h" + +static boolean +nv30_state_framebuffer_validate(struct nv30_context *nv30) +{ +	struct pipe_framebuffer_state *fb = &nv30->framebuffer; +	struct pipe_surface *rt[2], *zeta = NULL; +	uint32_t rt_enable, rt_format; +	int i, colour_format = 0, zeta_format = 0; +	struct nouveau_stateobj *so = so_new(64, 10); +	unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; +	unsigned w = fb->width; +	unsigned h = fb->height; + +	rt_enable = 0; +	for (i = 0; i < fb->num_cbufs; i++) { +		if (colour_format) { +			assert(colour_format == fb->cbufs[i]->format); +		} else { +			colour_format = fb->cbufs[i]->format; +			rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i); +			rt[i] = fb->cbufs[i]; +		} +	} + +	if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) +		rt_enable |= NV34TCL_RT_ENABLE_MRT; + +	if (fb->zsbuf) { +		zeta_format = fb->zsbuf->format; +		zeta = fb->zsbuf; +	} + +	rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; + +	switch (colour_format) { +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case 0: +		rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8; +		break; +	case PIPE_FORMAT_R5G6B5_UNORM: +		rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5; +		break; +	default: +		assert(0); +	} + +	switch (zeta_format) { +	case PIPE_FORMAT_Z16_UNORM: +		rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16; +		break; +	case PIPE_FORMAT_Z24S8_UNORM: +	case 0: +		rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8; +		break; +	default: +		assert(0); +	} + +	if (rt_enable & NV34TCL_RT_ENABLE_COLOR0) { +		uint32_t pitch = rt[0]->stride; +		if (zeta) { +			pitch |= (zeta->stride << 16); +		} else { +			pitch |= (pitch << 16); +		} + +		so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR0, 1); +		so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv30->nvws->channel->vram->handle, +			  nv30->nvws->channel->gart->handle); +		so_method(so, nv30->screen->rankine, NV34TCL_COLOR0_PITCH, 2); +		so_data  (so, pitch); +		so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +	} + +	if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { +		so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR1, 1); +		so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv30->nvws->channel->vram->handle, +			  nv30->nvws->channel->gart->handle); +		so_method(so, nv30->screen->rankine, NV34TCL_COLOR1_OFFSET, 2); +		so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +		so_data  (so, rt[1]->stride); +	} + +	if (zeta_format) { +		so_method(so, nv30->screen->rankine, NV34TCL_DMA_ZETA, 1); +		so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv30->nvws->channel->vram->handle, +			  nv30->nvws->channel->gart->handle); +		so_method(so, nv30->screen->rankine, NV34TCL_ZETA_OFFSET, 1); +		so_reloc (so, zeta->buffer, zeta->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +		/* TODO: allocate LMA depth buffer */ +	} + +	so_method(so, nv30->screen->rankine, NV34TCL_RT_ENABLE, 1); +	so_data  (so, rt_enable); +	so_method(so, nv30->screen->rankine, NV34TCL_RT_HORIZ, 3); +	so_data  (so, (w << 16) | 0); +	so_data  (so, (h << 16) | 0); +	so_data  (so, rt_format); +	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_HORIZ, 2); +	so_data  (so, (w << 16) | 0); +	so_data  (so, (h << 16) | 0); +	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); +	so_data  (so, ((w - 1) << 16) | 0); +	so_data  (so, ((h - 1) << 16) | 0); +	so_method(so, nv30->screen->rankine, 0x1d88, 1); +	so_data  (so, (1 << 12) | h); +	/* Wonder why this is needed, context should all be set to zero on init */ +	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1); +	so_data  (so, 0); + +	so_ref(so, &nv30->state.hw[NV30_STATE_FB]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_framebuffer = { +	.validate = nv30_state_framebuffer_validate, +	.dirty = { +		.pipe = NV30_NEW_FB, +		.hw = NV30_STATE_FB +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_state_rasterizer.c b/src/gallium/drivers/nv30/nv30_state_rasterizer.c new file mode 100644 index 0000000000..6d1b60e043 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_rasterizer.c @@ -0,0 +1,17 @@ +#include "nv30_context.h" + +static boolean +nv30_state_rasterizer_validate(struct nv30_context *nv30) +{ +	so_ref(nv30->rasterizer->so, +	       &nv30->state.hw[NV30_STATE_RAST]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_rasterizer = { +	.validate = nv30_state_rasterizer_validate, +	.dirty = { +		.pipe = NV30_NEW_RAST, +		.hw = NV30_STATE_RAST +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_state_scissor.c b/src/gallium/drivers/nv30/nv30_state_scissor.c new file mode 100644 index 0000000000..1db9bc1795 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_scissor.c @@ -0,0 +1,35 @@ +#include "nv30_context.h" + +static boolean +nv30_state_scissor_validate(struct nv30_context *nv30) +{ +	struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe; +	struct pipe_scissor_state *s = &nv30->scissor; +	struct nouveau_stateobj *so; + +	if (nv30->state.hw[NV30_STATE_SCISSOR] && +	    (rast->scissor == 0 && nv30->state.scissor_enabled == 0)) +		return FALSE; +	nv30->state.scissor_enabled = rast->scissor; + +	so = so_new(3, 0); +	so_method(so, nv30->screen->rankine, NV34TCL_SCISSOR_HORIZ, 2); +	if (nv30->state.scissor_enabled) { +		so_data  (so, ((s->maxx - s->minx) << 16) | s->minx); +		so_data  (so, ((s->maxy - s->miny) << 16) | s->miny); +	} else { +		so_data  (so, 4096 << 16); +		so_data  (so, 4096 << 16); +	} + +	so_ref(so, &nv30->state.hw[NV30_STATE_SCISSOR]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_scissor = { +	.validate = nv30_state_scissor_validate, +	.dirty = { +		.pipe = NV30_NEW_SCISSOR | NV30_NEW_RAST, +		.hw = NV30_STATE_SCISSOR +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_state_stipple.c b/src/gallium/drivers/nv30/nv30_state_stipple.c new file mode 100644 index 0000000000..41b42813b4 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_stipple.c @@ -0,0 +1,39 @@ +#include "nv30_context.h" + +static boolean +nv30_state_stipple_validate(struct nv30_context *nv30) +{ +	struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe; +	struct nouveau_grobj *rankine = nv30->screen->rankine; +	struct nouveau_stateobj *so; + +	if (nv30->state.hw[NV30_STATE_STIPPLE] && +	   (rast->poly_stipple_enable == 0 && nv30->state.stipple_enabled == 0)) +		return FALSE; + +	if (rast->poly_stipple_enable) { +		unsigned i; + +		so = so_new(35, 0); +		so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); +		so_data  (so, 1); +		so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32); +		for (i = 0; i < 32; i++) +			so_data(so, nv30->stipple[i]); +	} else { +		so = so_new(2, 0); +		so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_ref(so, &nv30->state.hw[NV30_STATE_STIPPLE]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_stipple = { +	.validate = nv30_state_stipple_validate, +	.dirty = { +		.pipe = NV30_NEW_STIPPLE | NV30_NEW_RAST, +		.hw = NV30_STATE_STIPPLE, +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_state_viewport.c b/src/gallium/drivers/nv30/nv30_state_viewport.c new file mode 100644 index 0000000000..951d40ebfd --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_viewport.c @@ -0,0 +1,70 @@ +#include "nv30_context.h" + +static boolean +nv30_state_viewport_validate(struct nv30_context *nv30) +{ +	struct pipe_viewport_state *vpt = &nv30->viewport; +	struct nouveau_stateobj *so; +	unsigned bypass; + +	if (/*nv30->render_mode == HW &&*/ !nv30->rasterizer->pipe.bypass_clipping) +		bypass = 0; +	else +		bypass = 1; + +	if (nv30->state.hw[NV30_STATE_VIEWPORT] && +	    (bypass || !(nv30->dirty & NV30_NEW_VIEWPORT)) && +	    nv30->state.viewport_bypass == bypass) +		return FALSE; +	nv30->state.viewport_bypass = bypass; + +	so = so_new(11, 0); +	if (!bypass) { +		so_method(so, nv30->screen->rankine, +			  NV34TCL_VIEWPORT_TRANSLATE_X, 8); +		so_data  (so, fui(vpt->translate[0])); +		so_data  (so, fui(vpt->translate[1])); +		so_data  (so, fui(vpt->translate[2])); +		so_data  (so, fui(vpt->translate[3])); +		so_data  (so, fui(vpt->scale[0])); +		so_data  (so, fui(vpt->scale[1])); +		so_data  (so, fui(vpt->scale[2])); +		so_data  (so, fui(vpt->scale[3])); +/*		so_method(so, nv30->screen->rankine, 0x1d78, 1); +		so_data  (so, 1); +*/	} else { +		so_method(so, nv30->screen->rankine, +			  NV34TCL_VIEWPORT_TRANSLATE_X, 8); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(1.0)); +		so_data  (so, fui(1.0)); +		so_data  (so, fui(1.0)); +		so_data  (so, fui(0.0)); +		/* Not entirely certain what this is yet.  The DDX uses this +		 * value also as it fixes rendering when you pass +		 * pre-transformed vertices to the GPU.  My best gusss is that +		 * this bypasses some culling/clipping stage.  Might be worth +		 * noting that points/lines are uneffected by whatever this +		 * value fixes, only filled polygons are effected. +		 */ +/*		so_method(so, nv30->screen->rankine, 0x1d78, 1); +		so_data  (so, 0x110); +*/	} +	/* TODO/FIXME: never saw value 0x0110 in renouveau dumps, only 0x0001 */ +	so_method(so, nv30->screen->rankine, 0x1d78, 1); +	so_data  (so, 1); + +	so_ref(so, &nv30->state.hw[NV30_STATE_VIEWPORT]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_viewport = { +	.validate = nv30_state_viewport_validate, +	.dirty = { +		.pipe = NV30_NEW_VIEWPORT | NV30_NEW_RAST, +		.hw = NV30_STATE_VIEWPORT +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_state_zsa.c b/src/gallium/drivers/nv30/nv30_state_zsa.c new file mode 100644 index 0000000000..0940b7269b --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_state_zsa.c @@ -0,0 +1,17 @@ +#include "nv30_context.h" + +static boolean +nv30_state_zsa_validate(struct nv30_context *nv30) +{ +	so_ref(nv30->zsa->so, +	       &nv30->state.hw[NV30_STATE_ZSA]); +	return TRUE; +} + +struct nv30_state_entry nv30_state_zsa = { +	.validate = nv30_state_zsa_validate, +	.dirty = { +		.pipe = NV30_NEW_ZSA, +		.hw = NV30_STATE_ZSA +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nv30/nv30_surface.c new file mode 100644 index 0000000000..b22211ac86 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_surface.c @@ -0,0 +1,77 @@ + +/************************************************************************** + *  + * Copyright 2003 Tungsten Graphics, 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, 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 TUNGSTEN GRAPHICS 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. + *  + **************************************************************************/ + +#include "nv30_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_winsys.h" +#include "pipe/p_inlines.h" +#include "util/p_tile.h" + +static void +nv30_surface_copy(struct pipe_context *pipe, unsigned do_flip, +		  struct pipe_surface *dest, unsigned destx, unsigned desty, +		  struct pipe_surface *src, unsigned srcx, unsigned srcy, +		  unsigned width, unsigned height) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nouveau_winsys *nvws = nv30->nvws; + +	if (do_flip) { +		/*XXX: This dodgyness will do for now for correctness.  But, +		 *     need to investigate whether the 2D engine is able to +		 *     manage a flip (perhaps SIFM?), if not, use the 3D engine +		 */ +		desty += height; +		while (height--) { +			nvws->surface_copy(nvws, dest, destx, desty--, src, +					   srcx, srcy++, width, 1); +		} +	} else { +		nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, +				   width, height); +	} +} + +static void +nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +		  unsigned destx, unsigned desty, unsigned width, +		  unsigned height, unsigned value) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nouveau_winsys *nvws = nv30->nvws; + +	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +} + +void +nv30_init_surface_functions(struct nv30_context *nv30) +{ +	nv30->pipe.surface_copy = nv30_surface_copy; +	nv30->pipe.surface_fill = nv30_surface_fill; +} diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c new file mode 100644 index 0000000000..d930557f6b --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_vbo.c @@ -0,0 +1,561 @@ +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" + +#include "nv30_context.h" +#include "nv30_state.h" + +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_pushbuf.h" +#include "nouveau/nouveau_util.h" + +#define FORCE_SWTNL 0 + +static INLINE int +nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) +{ +	char fs[128]; + +	switch (pipe) { +	case PIPE_FORMAT_R32_FLOAT: +	case PIPE_FORMAT_R32G32_FLOAT: +	case PIPE_FORMAT_R32G32B32_FLOAT: +	case PIPE_FORMAT_R32G32B32A32_FLOAT: +		*fmt = NV34TCL_VTXFMT_TYPE_FLOAT; +		break; +	case PIPE_FORMAT_R8_UNORM: +	case PIPE_FORMAT_R8G8_UNORM: +	case PIPE_FORMAT_R8G8B8_UNORM: +	case PIPE_FORMAT_R8G8B8A8_UNORM: +		*fmt = NV34TCL_VTXFMT_TYPE_UBYTE; +		break; +	case PIPE_FORMAT_R16_SSCALED: +	case PIPE_FORMAT_R16G16_SSCALED: +	case PIPE_FORMAT_R16G16B16_SSCALED: +	case PIPE_FORMAT_R16G16B16A16_SSCALED: +		*fmt = NV34TCL_VTXFMT_TYPE_USHORT; +		break; +	default: +		pf_sprint_name(fs, pipe); +		NOUVEAU_ERR("Unknown format %s\n", fs); +		return 1; +	} + +	switch (pipe) { +	case PIPE_FORMAT_R8_UNORM: +	case PIPE_FORMAT_R32_FLOAT: +	case PIPE_FORMAT_R16_SSCALED: +		*ncomp = 1; +		break; +	case PIPE_FORMAT_R8G8_UNORM: +	case PIPE_FORMAT_R32G32_FLOAT: +	case PIPE_FORMAT_R16G16_SSCALED: +		*ncomp = 2; +		break; +	case PIPE_FORMAT_R8G8B8_UNORM: +	case PIPE_FORMAT_R32G32B32_FLOAT: +	case PIPE_FORMAT_R16G16B16_SSCALED: +		*ncomp = 3; +		break; +	case PIPE_FORMAT_R8G8B8A8_UNORM: +	case PIPE_FORMAT_R32G32B32A32_FLOAT: +	case PIPE_FORMAT_R16G16B16A16_SSCALED: +		*ncomp = 4; +		break; +	default: +		pf_sprint_name(fs, pipe); +		NOUVEAU_ERR("Unknown format %s\n", fs); +		return 1; +	} + +	return 0; +} + +static boolean +nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib, +		    unsigned ib_size) +{ +	struct pipe_screen *pscreen = &nv30->screen->pipe; +	unsigned type; + +	if (!ib) { +		nv30->idxbuf = NULL; +		nv30->idxbuf_format = 0xdeadbeef; +		return FALSE; +	} + +	if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) +		return FALSE; + +	switch (ib_size) { +	case 2: +		type = NV34TCL_IDXBUF_FORMAT_TYPE_U16; +		break; +	case 4: +		type = NV34TCL_IDXBUF_FORMAT_TYPE_U32; +		break; +	default: +		return FALSE; +	} + +	if (ib != nv30->idxbuf || +	    type != nv30->idxbuf_format) { +		nv30->dirty |= NV30_NEW_ARRAYS; +		nv30->idxbuf = ib; +		nv30->idxbuf_format = type; +	} + +	return TRUE; +} + +static boolean +nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, +		       int attrib, struct pipe_vertex_element *ve, +		       struct pipe_vertex_buffer *vb) +{ +	struct pipe_winsys *ws = nv30->pipe.winsys; +	struct nouveau_grobj *rankine = nv30->screen->rankine; +	unsigned type, ncomp; +	void *map; + +	if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) +		return FALSE; + +	map  = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); +	map += vb->buffer_offset + ve->src_offset; + +	switch (type) { +	case NV34TCL_VTXFMT_TYPE_FLOAT: +	{ +		float *v = map; + +		switch (ncomp) { +		case 4: +			so_method(so, rankine, NV34TCL_VTX_ATTR_4F_X(attrib), 4); +			so_data  (so, fui(v[0])); +			so_data  (so, fui(v[1])); +			so_data  (so, fui(v[2])); +			so_data  (so, fui(v[3])); +			break; +		case 3: +			so_method(so, rankine, NV34TCL_VTX_ATTR_3F_X(attrib), 3); +			so_data  (so, fui(v[0])); +			so_data  (so, fui(v[1])); +			so_data  (so, fui(v[2])); +			break; +		case 2: +			so_method(so, rankine, NV34TCL_VTX_ATTR_2F_X(attrib), 2); +			so_data  (so, fui(v[0])); +			so_data  (so, fui(v[1])); +			break; +		case 1: +			so_method(so, rankine, NV34TCL_VTX_ATTR_1F(attrib), 1); +			so_data  (so, fui(v[0])); +			break; +		default: +			ws->buffer_unmap(ws, vb->buffer); +			return FALSE; +		} +	} +		break; +	default: +		ws->buffer_unmap(ws, vb->buffer); +		return FALSE; +	} + +	ws->buffer_unmap(ws, vb->buffer); + +	return TRUE; +} + +boolean +nv30_draw_arrays(struct pipe_context *pipe, +		 unsigned mode, unsigned start, unsigned count) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nouveau_channel *chan = nv30->nvws->channel; +	unsigned restart = 0; + +	nv30_vbo_set_idxbuf(nv30, NULL, 0); +	if (FORCE_SWTNL || !nv30_state_validate(nv30)) { +		/*return nv30_draw_elements_swtnl(pipe, NULL, 0, +						mode, start, count);*/ +		return FALSE; +	} + +	while (count) { +		unsigned vc, nr; + +		nv30_state_emit(nv30); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, +					mode, start, count, &restart); +		if (!vc) { +			FIRE_RING(NULL); +			continue; +		} + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		nr = (vc & 0xff); +		if (nr) { +			BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1); +			OUT_RING  (((nr - 1) << 24) | start); +			start += nr; +		} + +		nr = vc >> 8; +		while (nr) { +			unsigned push = nr > 2047 ? 2047 : nr; + +			nr -= push; + +			BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push); +			while (push--) { +				OUT_RING(((0x100 - 1) << 24) | start); +				start += 0x100; +			} +		} + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (0); + +		count -= vc; +		start = restart; +	} + +	pipe->flush(pipe, 0, NULL); +	return TRUE; +} + +static INLINE void +nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nouveau_channel *chan = nv30->nvws->channel; + +	while (count) { +		uint8_t *elts = (uint8_t *)ib + start; +		unsigned vc, push, restart = 0; + +		nv30_state_emit(nv30); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2, +					mode, start, count, &restart); +		if (vc == 0) { +			FIRE_RING(NULL); +			continue; +		} +		count -= vc; + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		if (vc & 1) { +			BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1); +			OUT_RING  (elts[0]); +			elts++; vc--; +		} + +		while (vc) { +			unsigned i; + +			push = MIN2(vc, 2047 * 2); + +			BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); +			for (i = 0; i < push; i+=2) +				OUT_RING((elts[i+1] << 16) | elts[i]); + +			vc -= push; +			elts += push; +		} + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (0); + +		start = restart; +	} +} + +static INLINE void +nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nouveau_channel *chan = nv30->nvws->channel; + +	while (count) { +		uint16_t *elts = (uint16_t *)ib + start; +		unsigned vc, push, restart = 0; + +		nv30_state_emit(nv30); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2, +					mode, start, count, &restart); +		if (vc == 0) { +			FIRE_RING(NULL); +			continue; +		} +		count -= vc; + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		if (vc & 1) { +			BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1); +			OUT_RING  (elts[0]); +			elts++; vc--; +		} + +		while (vc) { +			unsigned i; + +			push = MIN2(vc, 2047 * 2); + +			BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); +			for (i = 0; i < push; i+=2) +				OUT_RING((elts[i+1] << 16) | elts[i]); + +			vc -= push; +			elts += push; +		} + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (0); + +		start = restart; +	} +} + +static INLINE void +nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nouveau_channel *chan = nv30->nvws->channel; + +	while (count) { +		uint32_t *elts = (uint32_t *)ib + start; +		unsigned vc, push, restart = 0; + +		nv30_state_emit(nv30); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1, +					mode, start, count, &restart); +		if (vc == 0) { +			FIRE_RING(NULL); +			continue; +		} +		count -= vc; + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		while (vc) { +			push = MIN2(vc, 2047); + +			BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push); +			OUT_RINGp    (elts, push); + +			vc -= push; +			elts += push; +		} + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (0); + +		start = restart; +	} +} + +static boolean +nv30_draw_elements_inline(struct pipe_context *pipe, +			  struct pipe_buffer *ib, unsigned ib_size, +			  unsigned mode, unsigned start, unsigned count) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct pipe_winsys *ws = pipe->winsys; +	void *map; + +	map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ); +	if (!ib) { +		NOUVEAU_ERR("failed mapping ib\n"); +		return FALSE; +	} + +	switch (ib_size) { +	case 1: +		nv30_draw_elements_u08(nv30, map, mode, start, count); +		break; +	case 2: +		nv30_draw_elements_u16(nv30, map, mode, start, count); +		break; +	case 4: +		nv30_draw_elements_u32(nv30, map, mode, start, count); +		break; +	default: +		NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); +		break; +	} + +	ws->buffer_unmap(ws, ib); +	return TRUE; +} + +static boolean +nv30_draw_elements_vbo(struct pipe_context *pipe, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	struct nouveau_channel *chan = nv30->nvws->channel; +	unsigned restart = 0; + +	while (count) { +		unsigned nr, vc; + +		nv30_state_emit(nv30); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, +					mode, start, count, &restart); +		if (!vc) { +			FIRE_RING(NULL); +			continue; +		} +		 +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		nr = (vc & 0xff); +		if (nr) { +			BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1); +			OUT_RING  (((nr - 1) << 24) | start); +			start += nr; +		} + +		nr = vc >> 8; +		while (nr) { +			unsigned push = nr > 2047 ? 2047 : nr; + +			nr -= push; + +			BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push); +			while (push--) { +				OUT_RING(((0x100 - 1) << 24) | start); +				start += 0x100; +			} +		} + +		BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1); +		OUT_RING  (0); + +		count -= vc; +		start = restart; +	} + +	return TRUE; +} + +boolean +nv30_draw_elements(struct pipe_context *pipe, +		   struct pipe_buffer *indexBuffer, unsigned indexSize, +		   unsigned mode, unsigned start, unsigned count) +{ +	struct nv30_context *nv30 = nv30_context(pipe); +	boolean idxbuf; + +	idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize); +	if (FORCE_SWTNL || !nv30_state_validate(nv30)) { +		/*return nv30_draw_elements_swtnl(pipe, NULL, 0, +						mode, start, count);*/ +		return FALSE;	 +	} + +	if (idxbuf) { +		nv30_draw_elements_vbo(pipe, mode, start, count); +	} else { +		nv30_draw_elements_inline(pipe, indexBuffer, indexSize, +					  mode, start, count); +	} + +	pipe->flush(pipe, 0, NULL); +	return TRUE; +} + +static boolean +nv30_vbo_validate(struct nv30_context *nv30) +{ +	struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; +	struct nouveau_grobj *rankine = nv30->screen->rankine; +	struct pipe_buffer *ib = nv30->idxbuf; +	unsigned ib_format = nv30->idxbuf_format; +	unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; +	int hw; + +	if (nv30->edgeflags) { +		/*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/ +		return FALSE; +	} + +	vtxbuf = so_new(20, 18); +	so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr); +	vtxfmt = so_new(17, 0); +	so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr); + +	for (hw = 0; hw < nv30->vtxelt_nr; hw++) { +		struct pipe_vertex_element *ve; +		struct pipe_vertex_buffer *vb; +		unsigned type, ncomp; + +		ve = &nv30->vtxelt[hw]; +		vb = &nv30->vtxbuf[ve->vertex_buffer_index]; + +		if (!vb->pitch) { +			if (!sattr) +				sattr = so_new(16 * 5, 0); + +			if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) { +				so_data(vtxbuf, 0); +				so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT); +				continue; +			} +		} + +		if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { +			/*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/ +			so_ref(NULL, &vtxbuf); +			so_ref(NULL, &vtxfmt); +			return FALSE; +		} + +		so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset, +			 vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, +			 0, NV34TCL_VTXBUF_ADDRESS_DMA1); +		so_data (vtxfmt, ((vb->pitch << NV34TCL_VTXFMT_STRIDE_SHIFT) | +				  (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); +	} + +	if (ib) { +		so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2); +		so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); +		so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR, +			  0, NV34TCL_IDXBUF_FORMAT_DMA1); +	} + +	so_method(vtxbuf, rankine, 0x1710, 1); +	so_data  (vtxbuf, 0); + +	so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]); +	nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF); +	so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]); +	nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT); +	so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]); +	nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR); +	return FALSE; +} + +struct nv30_state_entry nv30_state_vbo = { +	.validate = nv30_vbo_validate, +	.dirty = { +		.pipe = NV30_NEW_ARRAYS, +		.hw = 0, +	} +}; diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c new file mode 100644 index 0000000000..6c075cdb75 --- /dev/null +++ b/src/gallium/drivers/nv30/nv30_vertprog.c @@ -0,0 +1,832 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" + +#include "nv30_context.h" +#include "nv30_state.h" + +/* TODO (at least...): + *  1. Indexed consts  + ARL + *  2. Arb. swz/negation + *  3. NV_vp11, NV_vp2, NV_vp3 features + *       - extra arith opcodes + *       - branching + *       - texture sampling + *       - indexed attribs + *       - indexed results + *  4. bugs + */ + +#define SWZ_X 0 +#define SWZ_Y 1 +#define SWZ_Z 2 +#define SWZ_W 3 +#define MASK_X 8 +#define MASK_Y 4 +#define MASK_Z 2 +#define MASK_W 1 +#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) +#define DEF_SCALE 0 +#define DEF_CTEST 0 +#include "nv30_shader.h" + +#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) +#define neg(s) nv30_sr_neg((s)) +#define abs(s) nv30_sr_abs((s)) + +struct nv30_vpc { +	struct nv30_vertex_program *vp; + +	struct nv30_vertex_program_exec *vpi; + +	unsigned output_map[PIPE_MAX_SHADER_OUTPUTS]; + +	int high_temp; +	int temp_temp_count; + +	struct nv30_sreg *imm; +	unsigned nr_imm; +}; + +static struct nv30_sreg +temp(struct nv30_vpc *vpc) +{ +	int idx; + +	idx  = vpc->temp_temp_count++; +	idx += vpc->high_temp + 1; +	return nv30_sr(NV30SR_TEMP, idx); +} + +static struct nv30_sreg +constant(struct nv30_vpc *vpc, int pipe, float x, float y, float z, float w) +{ +	struct nv30_vertex_program *vp = vpc->vp; +	struct nv30_vertex_program_data *vpd; +	int idx; + +	if (pipe >= 0) { +		for (idx = 0; idx < vp->nr_consts; idx++) { +			if (vp->consts[idx].index == pipe) +				return nv30_sr(NV30SR_CONST, idx); +		} +	} + +	idx = vp->nr_consts++; +	vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); +	vpd = &vp->consts[idx]; + +	vpd->index = pipe; +	vpd->value[0] = x; +	vpd->value[1] = y; +	vpd->value[2] = z; +	vpd->value[3] = w; +	return nv30_sr(NV30SR_CONST, idx); +} + +#define arith(cc,s,o,d,m,s0,s1,s2) \ +	nv30_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2)) + +static void +emit_src(struct nv30_vpc *vpc, uint32_t *hw, int pos, struct nv30_sreg src) +{ +	struct nv30_vertex_program *vp = vpc->vp; +	uint32_t sr = 0; + +	switch (src.type) { +	case NV30SR_TEMP: +		sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT); +		sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT); +		break; +	case NV30SR_INPUT: +		sr |= (NV30_VP_SRC_REG_TYPE_INPUT << +		       NV30_VP_SRC_REG_TYPE_SHIFT); +		vp->ir |= (1 << src.index); +		hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT); +		break; +	case NV30SR_CONST: +		sr |= (NV30_VP_SRC_REG_TYPE_CONST << +		       NV30_VP_SRC_REG_TYPE_SHIFT); +		assert(vpc->vpi->const_index == -1 || +		       vpc->vpi->const_index == src.index); +		vpc->vpi->const_index = src.index; +		break; +	case NV30SR_NONE: +		sr |= (NV30_VP_SRC_REG_TYPE_INPUT << +		       NV30_VP_SRC_REG_TYPE_SHIFT); +		break; +	default: +		assert(0); +	} + +	if (src.negate) +		sr |= NV30_VP_SRC_NEGATE; + +	if (src.abs) +		hw[0] |= (1 << (21 + pos)); + +	sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) | +	       (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) | +	       (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) | +	       (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT)); + +/* + * |VVV| + * d�.�b + *  \u/ + * + */ + +	switch (pos) { +	case 0: +		hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >> +			  NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT; +		hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) << +			  NV30_VP_INST_SRC0L_SHIFT; +		break; +	case 1: +		hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT; +		break; +	case 2: +		hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >> +			  NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT; +		hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) << +			  NV30_VP_INST_SRC2L_SHIFT; +		break; +	default: +		assert(0); +	} +} + +static void +emit_dst(struct nv30_vpc *vpc, uint32_t *hw, int slot, struct nv30_sreg dst) +{ +	struct nv30_vertex_program *vp = vpc->vp; + +	switch (dst.type) { +	case NV30SR_TEMP: +		hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT); +		break; +	case NV30SR_OUTPUT: +		switch (dst.index) { +		case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; +		case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; +		case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; +		case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; +		case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; +		case NV30_VP_INST_DEST_PSZ  : vp->or |= (1 << 5); break; +		case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; +		case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; +		case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; +		case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; +		case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; +		case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; +		case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; +		case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; +		default: +			break; +		} + +		hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT); +		hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + +		/*XXX: no way this is entirely correct, someone needs to +		 *     figure out what exactly it is. +		 */ +		hw[3] |= 0x800; +		break; +	default: +		assert(0); +	} +} + +static void +nv30_vp_arith(struct nv30_vpc *vpc, int slot, int op, +	      struct nv30_sreg dst, int mask, +	      struct nv30_sreg s0, struct nv30_sreg s1, +	      struct nv30_sreg s2) +{ +	struct nv30_vertex_program *vp = vpc->vp; +	uint32_t *hw; + +	vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); +	vpc->vpi = &vp->insns[vp->nr_insns - 1]; +	memset(vpc->vpi, 0, sizeof(*vpc->vpi)); +	vpc->vpi->const_index = -1; + +	hw = vpc->vpi->data; + +	hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT); +	hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) | +		  (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) | +		  (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) | +		  (3 << NV30_VP_INST_COND_SWZ_W_SHIFT)); + +	hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT); +//	hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK; +//	hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT); + +	if (dst.type == NV30SR_OUTPUT) { +		if (slot) +			hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT); +		else +			hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT); +	} else { +		if (slot) +			hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT); +		else +			hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT); +	} + +	emit_dst(vpc, hw, slot, dst); +	emit_src(vpc, hw, 0, s0); +	emit_src(vpc, hw, 1, s1); +	emit_src(vpc, hw, 2, s2); +} + +static INLINE struct nv30_sreg +tgsi_src(struct nv30_vpc *vpc, const struct tgsi_full_src_register *fsrc) { +	struct nv30_sreg src; + +	switch (fsrc->SrcRegister.File) { +	case TGSI_FILE_INPUT: +		src = nv30_sr(NV30SR_INPUT, fsrc->SrcRegister.Index); +		break; +	case TGSI_FILE_CONSTANT: +		src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0); +		break; +	case TGSI_FILE_IMMEDIATE: +		src = vpc->imm[fsrc->SrcRegister.Index]; +		break; +	case TGSI_FILE_TEMPORARY: +		if (vpc->high_temp < fsrc->SrcRegister.Index) +			vpc->high_temp = fsrc->SrcRegister.Index; +		src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index); +		break; +	default: +		NOUVEAU_ERR("bad src file\n"); +		break; +	} + +	src.abs = fsrc->SrcRegisterExtMod.Absolute; +	src.negate = fsrc->SrcRegister.Negate; +	src.swz[0] = fsrc->SrcRegister.SwizzleX; +	src.swz[1] = fsrc->SrcRegister.SwizzleY; +	src.swz[2] = fsrc->SrcRegister.SwizzleZ; +	src.swz[3] = fsrc->SrcRegister.SwizzleW; +	return src; +} + +static INLINE struct nv30_sreg +tgsi_dst(struct nv30_vpc *vpc, const struct tgsi_full_dst_register *fdst) { +	struct nv30_sreg dst; + +	switch (fdst->DstRegister.File) { +	case TGSI_FILE_OUTPUT: +		dst = nv30_sr(NV30SR_OUTPUT, +			      vpc->output_map[fdst->DstRegister.Index]); + +		break; +	case TGSI_FILE_TEMPORARY: +		dst = nv30_sr(NV30SR_TEMP, fdst->DstRegister.Index); +		if (vpc->high_temp < dst.index) +			vpc->high_temp = dst.index; +		break; +	default: +		NOUVEAU_ERR("bad dst file\n"); +		break; +	} + +	return dst; +} + +static INLINE int +tgsi_mask(uint tgsi) +{ +	int mask = 0; + +	if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; +	if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; +	if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; +	if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; +	return mask; +} + +static boolean +nv30_vertprog_parse_instruction(struct nv30_vpc *vpc, +				const struct tgsi_full_instruction *finst) +{ +	struct nv30_sreg src[3], dst, tmp; +	struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); +	int mask; +	int ai = -1, ci = -1; +	int i; + +	if (finst->Instruction.Opcode == TGSI_OPCODE_END) +		return TRUE; + +	vpc->temp_temp_count = 0; +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; +		if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) { +			src[i] = tgsi_src(vpc, fsrc); +		} +	} + +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +			if (ai == -1 || ai == fsrc->SrcRegister.Index) { +				ai = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(vpc, fsrc); +			} else { +				src[i] = temp(vpc); +				arith(vpc, 0, OP_MOV, src[i], MASK_ALL, +				      tgsi_src(vpc, fsrc), none, none); +			} +			break; +		/*XXX: index comparison is broken now that consts come from +		 *     two different register files. +		 */ +		case TGSI_FILE_CONSTANT: +		case TGSI_FILE_IMMEDIATE: +			if (ci == -1 || ci == fsrc->SrcRegister.Index) { +				ci = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(vpc, fsrc); +			} else { +				src[i] = temp(vpc); +				arith(vpc, 0, OP_MOV, src[i], MASK_ALL, +				      tgsi_src(vpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_TEMPORARY: +			/* handled above */ +			break; +		default: +			NOUVEAU_ERR("bad src file\n"); +			return FALSE; +		} +	} + +	dst  = tgsi_dst(vpc, &finst->FullDstRegisters[0]); +	mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask); + +	switch (finst->Instruction.Opcode) { +	case TGSI_OPCODE_ABS: +		arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); +		break; +	case TGSI_OPCODE_ADD: +		arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); +		break; +	case TGSI_OPCODE_ARL: +		arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_DP3: +		arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DP4: +		arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DPH: +		arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DST: +		arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_EX2: +		arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_EXP: +		arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_FLR: +		arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_FRC: +		arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_LG2: +		arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_LIT: +		arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_LOG: +		arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_MAD: +		arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); +		break; +	case TGSI_OPCODE_MAX: +		arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MIN: +		arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MOV: +		arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_MUL: +		arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_POW: +		tmp = temp(vpc); +		arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, +		      swz(src[0], X, X, X, X)); +		arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), +		      swz(src[1], X, X, X, X), none); +		arith(vpc, 1, OP_EX2, dst, mask, none, none, +		      swz(tmp, X, X, X, X)); +		break; +	case TGSI_OPCODE_RCP: +		arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_RET: +		break; +	case TGSI_OPCODE_RSQ: +		arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_SGE: +		arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SLT: +		arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SUB: +		arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); +		break; +	case TGSI_OPCODE_XPD: +		tmp = temp(vpc); +		arith(vpc, 0, OP_MUL, tmp, mask, +		      swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); +		arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), +		      swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), +		      neg(tmp)); +		break; +	default: +		NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); +		return FALSE; +	} + +	return TRUE; +} + +static boolean +nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc, +				const struct tgsi_full_declaration *fdec) +{ +	int hw; + +	switch (fdec->Semantic.SemanticName) { +	case TGSI_SEMANTIC_POSITION: +		hw = NV30_VP_INST_DEST_POS; +		break; +	case TGSI_SEMANTIC_COLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV30_VP_INST_DEST_COL0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV30_VP_INST_DEST_COL1; +		} else { +			NOUVEAU_ERR("bad colour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_BCOLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV30_VP_INST_DEST_BFC0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV30_VP_INST_DEST_BFC1; +		} else { +			NOUVEAU_ERR("bad bcolour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_FOG: +		hw = NV30_VP_INST_DEST_FOGC; +		break; +	case TGSI_SEMANTIC_PSIZE: +		hw = NV30_VP_INST_DEST_PSZ; +		break; +	case TGSI_SEMANTIC_GENERIC: +		if (fdec->Semantic.SemanticIndex <= 7) { +			hw = NV30_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex); +		} else { +			NOUVEAU_ERR("bad generic semantic index\n"); +			return FALSE; +		} +		break; +	default: +		NOUVEAU_ERR("bad output semantic\n"); +		return FALSE; +	} + +	vpc->output_map[fdec->DeclarationRange.First] = hw; +	return TRUE; +} + +static boolean +nv30_vertprog_prepare(struct nv30_vpc *vpc) +{ +	struct tgsi_parse_context p; +	int nr_imm = 0; + +	tgsi_parse_init(&p, vpc->vp->pipe.tokens); +	while (!tgsi_parse_end_of_tokens(&p)) { +		const union tgsi_full_token *tok = &p.FullToken; + +		tgsi_parse_token(&p); +		switch(tok->Token.Type) { +		case TGSI_TOKEN_TYPE_IMMEDIATE: +			nr_imm++; +			break; +		default: +			break; +		} +	} +	tgsi_parse_free(&p); + +	if (nr_imm) { +		vpc->imm = CALLOC(nr_imm, sizeof(struct nv30_sreg)); +		assert(vpc->imm); +	} + +	return TRUE; +} + +static void +nv30_vertprog_translate(struct nv30_context *nv30, +			struct nv30_vertex_program *vp) +{ +	struct tgsi_parse_context parse; +	struct nv30_vpc *vpc = NULL; + +	vpc = CALLOC(1, sizeof(struct nv30_vpc)); +	if (!vpc) +		return; +	vpc->vp = vp; +	vpc->high_temp = -1; + +	if (!nv30_vertprog_prepare(vpc)) { +		FREE(vpc); +		return; +	} + +	tgsi_parse_init(&parse, vp->pipe.tokens); + +	while (!tgsi_parse_end_of_tokens(&parse)) { +		tgsi_parse_token(&parse); + +		switch (parse.FullToken.Token.Type) { +		case TGSI_TOKEN_TYPE_DECLARATION: +		{ +			const struct tgsi_full_declaration *fdec; +			fdec = &parse.FullToken.FullDeclaration; +			switch (fdec->Declaration.File) { +			case TGSI_FILE_OUTPUT: +				if (!nv30_vertprog_parse_decl_output(vpc, fdec)) +					goto out_err; +				break; +			default: +				break; +			} +		} +			break; +		case TGSI_TOKEN_TYPE_IMMEDIATE: +		{ +			const struct tgsi_full_immediate *imm; + +			imm = &parse.FullToken.FullImmediate; +			assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); +//			assert(imm->Immediate.Size == 4); +			vpc->imm[vpc->nr_imm++] = +				constant(vpc, -1, +					 imm->u.ImmediateFloat32[0].Float, +					 imm->u.ImmediateFloat32[1].Float, +					 imm->u.ImmediateFloat32[2].Float, +					 imm->u.ImmediateFloat32[3].Float); +		} +			break; +		case TGSI_TOKEN_TYPE_INSTRUCTION: +		{ +			const struct tgsi_full_instruction *finst; +			finst = &parse.FullToken.FullInstruction; +			if (!nv30_vertprog_parse_instruction(vpc, finst)) +				goto out_err; +		} +			break; +		default: +			break; +		} +	} + +	vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST; +	vp->translated = TRUE; +out_err: +	tgsi_parse_free(&parse); +	FREE(vpc); +} + +static boolean +nv30_vertprog_validate(struct nv30_context *nv30) +{  +	struct nouveau_winsys *nvws = nv30->nvws; +	struct pipe_winsys *ws = nv30->pipe.winsys; +	struct nouveau_grobj *rankine = nv30->screen->rankine; +	struct nv30_vertex_program *vp; +	struct pipe_buffer *constbuf; +	boolean upload_code = FALSE, upload_data = FALSE; +	int i; + +	vp = nv30->vertprog; +	constbuf = nv30->constbuf[PIPE_SHADER_VERTEX]; + +	/* Translate TGSI shader into hw bytecode */ +	if (!vp->translated) { +		nv30_vertprog_translate(nv30, vp); +		if (!vp->translated) +			return FALSE; +	} + +	/* Allocate hw vtxprog exec slots */ +	if (!vp->exec) { +		struct nouveau_resource *heap = nv30->screen->vp_exec_heap; +		struct nouveau_stateobj *so; +		uint vplen = vp->nr_insns; + +		if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) { +			while (heap->next && heap->size < vplen) { +				struct nv30_vertex_program *evict; +				 +				evict = heap->next->priv; +				nvws->res_free(&evict->exec); +			} + +			if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) +				assert(0); +		} + +		so = so_new(2, 0); +		so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1); +		so_data  (so, vp->exec->start); +		so_ref(so, &vp->so); + +		upload_code = TRUE; +	} + +	/* Allocate hw vtxprog const slots */ +	if (vp->nr_consts && !vp->data) { +		struct nouveau_resource *heap = nv30->screen->vp_data_heap; + +		if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) { +			while (heap->next && heap->size < vp->nr_consts) { +				struct nv30_vertex_program *evict; +				 +				evict = heap->next->priv; +				nvws->res_free(&evict->data); +			} + +			if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) +				assert(0); +		} + +		/*XXX: handle this some day */ +		assert(vp->data->start >= vp->data_start_min); + +		upload_data = TRUE; +		if (vp->data_start != vp->data->start) +			upload_code = TRUE; +	} + +	/* If exec or data segments moved we need to patch the program to +	 * fixup offsets and register IDs. +	 */ +	if (vp->exec_start != vp->exec->start) { +		for (i = 0; i < vp->nr_insns; i++) { +			struct nv30_vertex_program_exec *vpi = &vp->insns[i]; + +			if (vpi->has_branch_offset) { +				assert(0); +			} +		} + +		vp->exec_start = vp->exec->start; +	} + +	if (vp->nr_consts && vp->data_start != vp->data->start) { +		for (i = 0; i < vp->nr_insns; i++) { +			struct nv30_vertex_program_exec *vpi = &vp->insns[i]; + +			if (vpi->const_index >= 0) { +				vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK; +				vpi->data[1] |= +					(vpi->const_index + vp->data->start) << +					NV30_VP_INST_CONST_SRC_SHIFT; + +			} +		} + +		vp->data_start = vp->data->start; +	} + +	/* Update + Upload constant values */ +	if (vp->nr_consts) { +		float *map = NULL; + +		if (constbuf) { +			map = ws->buffer_map(ws, constbuf, +					     PIPE_BUFFER_USAGE_CPU_READ); +		} + +		for (i = 0; i < vp->nr_consts; i++) { +			struct nv30_vertex_program_data *vpd = &vp->consts[i]; + +			if (vpd->index >= 0) { +				if (!upload_data && +				    !memcmp(vpd->value, &map[vpd->index * 4], +					    4 * sizeof(float))) +					continue; +				memcpy(vpd->value, &map[vpd->index * 4], +				       4 * sizeof(float)); +			} + +			BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5); +			OUT_RING  (i + vp->data->start); +			OUT_RINGp ((uint32_t *)vpd->value, 4); +		} + +		if (constbuf) { +			ws->buffer_unmap(ws, constbuf); +		} +	} + +	/* Upload vtxprog */ +	if (upload_code) { +#if 0 +		for (i = 0; i < vp->nr_insns; i++) { +			NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n", +				i, vp->insns[i].data[0], vp->insns[i].data[1], +				vp->insns[i].data[2], vp->insns[i].data[3]); +		} +#endif +		BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1); +		OUT_RING  (vp->exec->start); +		for (i = 0; i < vp->nr_insns; i++) { +			BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_INST(0), 4); +			OUT_RINGp (vp->insns[i].data, 4); +		} +	} + +	if (vp->so != nv30->state.hw[NV30_STATE_VERTPROG]) { +		so_ref(vp->so, &nv30->state.hw[NV30_STATE_VERTPROG]); +		return TRUE; +	} + +	return FALSE; +} + +void +nv30_vertprog_destroy(struct nv30_context *nv30, struct nv30_vertex_program *vp) +{ +	struct nouveau_winsys *nvws = nv30->screen->nvws; + +	vp->translated = FALSE; + +	if (vp->nr_insns) { +		FREE(vp->insns); +		vp->insns = NULL; +		vp->nr_insns = 0; +	} + +	if (vp->nr_consts) { +		FREE(vp->consts); +		vp->consts = NULL; +		vp->nr_consts = 0; +	} + +	nvws->res_free(&vp->exec); +	vp->exec_start = 0; +	nvws->res_free(&vp->data); +	vp->data_start = 0; +	vp->data_start_min = 0; + +	vp->ir = vp->or = 0; +	so_ref(NULL, &vp->so); +} + +struct nv30_state_entry nv30_state_vertprog = { +	.validate = nv30_vertprog_validate, +	.dirty = { +		.pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/, +		.hw = NV30_STATE_VERTPROG, +	} +}; diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile new file mode 100644 index 0000000000..9c8eadf7e4 --- /dev/null +++ b/src/gallium/drivers/nv40/Makefile @@ -0,0 +1,37 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nv40 + +DRIVER_SOURCES = \ +	nv40_clear.c \ +	nv40_context.c \ +	nv40_draw.c \ +	nv40_fragprog.c \ +	nv40_fragtex.c \ +	nv40_miptree.c \ +	nv40_query.c \ +	nv40_screen.c \ +	nv40_state.c \ +	nv40_state_blend.c \ +	nv40_state_emit.c \ +	nv40_state_fb.c \ +	nv40_state_rasterizer.c \ +	nv40_state_scissor.c \ +	nv40_state_stipple.c \ +	nv40_state_viewport.c \ +	nv40_state_zsa.c \ +	nv40_surface.c \ +	nv40_vbo.c \ +	nv40_vertprog.c + +C_SOURCES = \ +	$(COMMON_SOURCES) \ +	$(DRIVER_SOURCES) + +ASM_SOURCES =  + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/drivers/nv40/nv40_clear.c b/src/gallium/drivers/nv40/nv40_clear.c new file mode 100644 index 0000000000..59efd620e3 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_clear.c @@ -0,0 +1,13 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "nv40_context.h" + +void +nv40_clear(struct pipe_context *pipe, struct pipe_surface *ps, +	   unsigned clearValue) +{ +	pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); +	ps->status = PIPE_SURFACE_STATUS_CLEAR; +} diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c new file mode 100644 index 0000000000..a40f14895f --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -0,0 +1,73 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" +#include "pipe/p_util.h" + +#include "nv40_context.h" +#include "nv40_screen.h" + +static void +nv40_flush(struct pipe_context *pipe, unsigned flags, +	   struct pipe_fence_handle **fence) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	 +	if (flags & PIPE_FLUSH_TEXTURE_CACHE) { +		BEGIN_RING(curie, 0x1fd8, 1); +		OUT_RING  (2); +		BEGIN_RING(curie, 0x1fd8, 1); +		OUT_RING  (1); +	} + +	FIRE_RING(fence); +} + +static void +nv40_destroy(struct pipe_context *pipe) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	if (nv40->draw) +		draw_destroy(nv40->draw); +	FREE(nv40); +} + +struct pipe_context * +nv40_create(struct pipe_screen *pscreen, unsigned pctx_id) +{ +	struct nv40_screen *screen = nv40_screen(pscreen); +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv40_context *nv40; +	struct nouveau_winsys *nvws = screen->nvws; + +	nv40 = CALLOC(1, sizeof(struct nv40_context)); +	if (!nv40) +		return NULL; +	nv40->screen = screen; +	nv40->pctx_id = pctx_id; + +	nv40->nvws = nvws; + +	nv40->pipe.winsys = ws; +	nv40->pipe.screen = pscreen; +	nv40->pipe.destroy = nv40_destroy; +	nv40->pipe.draw_arrays = nv40_draw_arrays; +	nv40->pipe.draw_elements = nv40_draw_elements; +	nv40->pipe.clear = nv40_clear; +	nv40->pipe.flush = nv40_flush; + +	nv40_init_query_functions(nv40); +	nv40_init_surface_functions(nv40); +	nv40_init_state_functions(nv40); + +	/* Create, configure, and install fallback swtnl path */ +	nv40->draw = draw_create(); +	draw_wide_point_threshold(nv40->draw, 9999999.0); +	draw_wide_line_threshold(nv40->draw, 9999999.0); +	draw_enable_line_stipple(nv40->draw, FALSE); +	draw_enable_point_sprites(nv40->draw, FALSE); +	draw_set_rasterize_stage(nv40->draw, nv40_draw_render_stage(nv40)); + +	return &nv40->pipe; +} +	 diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h new file mode 100644 index 0000000000..8e60a81e68 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -0,0 +1,229 @@ +#ifndef __NV40_CONTEXT_H__ +#define __NV40_CONTEXT_H__ + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" + +#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \ +	struct nv40_screen *ctx = nv40->screen +#include "nouveau/nouveau_push.h" +#include "nouveau/nouveau_stateobj.h" + +#include "nv40_state.h" + +#define NOUVEAU_ERR(fmt, args...) \ +	fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ +	fprintf(stderr, "nouveau: "fmt, ##args); + +enum nv40_state_index { +	NV40_STATE_FB = 0, +	NV40_STATE_VIEWPORT = 1, +	NV40_STATE_BLEND = 2, +	NV40_STATE_RAST = 3, +	NV40_STATE_ZSA = 4, +	NV40_STATE_BCOL = 5, +	NV40_STATE_CLIP = 6, +	NV40_STATE_SCISSOR = 7, +	NV40_STATE_STIPPLE = 8, +	NV40_STATE_FRAGPROG = 9, +	NV40_STATE_VERTPROG = 10, +	NV40_STATE_FRAGTEX0 = 11, +	NV40_STATE_FRAGTEX1 = 12, +	NV40_STATE_FRAGTEX2 = 13, +	NV40_STATE_FRAGTEX3 = 14, +	NV40_STATE_FRAGTEX4 = 15, +	NV40_STATE_FRAGTEX5 = 16, +	NV40_STATE_FRAGTEX6 = 17, +	NV40_STATE_FRAGTEX7 = 18, +	NV40_STATE_FRAGTEX8 = 19, +	NV40_STATE_FRAGTEX9 = 20, +	NV40_STATE_FRAGTEX10 = 21, +	NV40_STATE_FRAGTEX11 = 22, +	NV40_STATE_FRAGTEX12 = 23, +	NV40_STATE_FRAGTEX13 = 24, +	NV40_STATE_FRAGTEX14 = 25, +	NV40_STATE_FRAGTEX15 = 26, +	NV40_STATE_VERTTEX0 = 27, +	NV40_STATE_VERTTEX1 = 28, +	NV40_STATE_VERTTEX2 = 29, +	NV40_STATE_VERTTEX3 = 30, +	NV40_STATE_VTXBUF = 31, +	NV40_STATE_VTXFMT = 32, +	NV40_STATE_VTXATTR = 33, +	NV40_STATE_MAX = 34 +}; + +#include "nv40_screen.h" + +#define NV40_NEW_BLEND		(1 <<  0) +#define NV40_NEW_RAST		(1 <<  1) +#define NV40_NEW_ZSA		(1 <<  2) +#define NV40_NEW_SAMPLER	(1 <<  3) +#define NV40_NEW_FB		(1 <<  4) +#define NV40_NEW_STIPPLE	(1 <<  5) +#define NV40_NEW_SCISSOR	(1 <<  6) +#define NV40_NEW_VIEWPORT	(1 <<  7) +#define NV40_NEW_BCOL		(1 <<  8) +#define NV40_NEW_VERTPROG	(1 <<  9) +#define NV40_NEW_FRAGPROG	(1 << 10) +#define NV40_NEW_ARRAYS		(1 << 11) +#define NV40_NEW_UCP		(1 << 12) + +struct nv40_rasterizer_state { +	struct pipe_rasterizer_state pipe; +	struct nouveau_stateobj *so; +}; + +struct nv40_zsa_state { +	struct pipe_depth_stencil_alpha_state pipe; +	struct nouveau_stateobj *so; +}; + +struct nv40_blend_state { +	struct pipe_blend_state pipe; +	struct nouveau_stateobj *so; +}; + + +struct nv40_state { +	unsigned scissor_enabled; +	unsigned stipple_enabled; +	unsigned viewport_bypass; +	unsigned fp_samplers; + +	uint64_t dirty; +	struct nouveau_stateobj *hw[NV40_STATE_MAX]; +}; + +struct nv40_context { +	struct pipe_context pipe; + +	struct nouveau_winsys *nvws; +	struct nv40_screen *screen; +	unsigned pctx_id; + +	struct draw_context *draw; + +	/* HW state derived from pipe states */ +	struct nv40_state state; +	struct { +		struct nv40_vertex_program *vertprog; + +		unsigned nr_attribs; +		unsigned hw[PIPE_MAX_SHADER_INPUTS]; +		unsigned draw[PIPE_MAX_SHADER_INPUTS]; +		unsigned emit[PIPE_MAX_SHADER_INPUTS]; +	} swtnl; + +	enum { +		HW, SWTNL, SWRAST +	} render_mode; +	unsigned fallback_swtnl; +	unsigned fallback_swrast; + +	/* Context state */ +	unsigned dirty, draw_dirty; +	struct pipe_scissor_state scissor; +	unsigned stipple[32]; +	struct pipe_clip_state clip; +	struct nv40_vertex_program *vertprog; +	struct nv40_fragment_program *fragprog; +	struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; +	unsigned constbuf_nr[PIPE_SHADER_TYPES]; +	struct nv40_rasterizer_state *rasterizer; +	struct nv40_zsa_state *zsa; +	struct nv40_blend_state *blend; +	struct pipe_blend_color blend_colour; +	struct pipe_viewport_state viewport; +	struct pipe_framebuffer_state framebuffer; +	struct pipe_buffer *idxbuf; +	unsigned idxbuf_format; +	struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; +	struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; +	unsigned nr_samplers; +	unsigned nr_textures; +	unsigned dirty_samplers; +	struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; +	unsigned vtxbuf_nr; +	struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; +	unsigned vtxelt_nr; +	const unsigned *edgeflags; +}; + +static INLINE struct nv40_context * +nv40_context(struct pipe_context *pipe) +{ +	return (struct nv40_context *)pipe; +} + +struct nv40_state_entry { +	boolean (*validate)(struct nv40_context *nv40); +	struct { +		unsigned pipe; +		unsigned hw; +	} dirty; +}; + +extern void nv40_init_state_functions(struct nv40_context *nv40); +extern void nv40_init_surface_functions(struct nv40_context *nv40); +extern void nv40_init_query_functions(struct nv40_context *nv40); + +extern void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen); + +/* nv40_draw.c */ +extern struct draw_stage *nv40_draw_render_stage(struct nv40_context *nv40); +extern boolean nv40_draw_elements_swtnl(struct pipe_context *pipe, +					struct pipe_buffer *idxbuf, +					unsigned ib_size, unsigned mode, +					unsigned start, unsigned count); + +/* nv40_vertprog.c */ +extern void nv40_vertprog_destroy(struct nv40_context *, +				  struct nv40_vertex_program *); + +/* nv40_fragprog.c */ +extern void nv40_fragprog_destroy(struct nv40_context *, +				  struct nv40_fragment_program *); + +/* nv40_fragtex.c */ +extern void nv40_fragtex_bind(struct nv40_context *); + +/* nv40_state.c and friends */ +extern boolean nv40_state_validate(struct nv40_context *nv40); +extern boolean nv40_state_validate_swtnl(struct nv40_context *nv40); +extern void nv40_state_emit(struct nv40_context *nv40); +extern struct nv40_state_entry nv40_state_rasterizer; +extern struct nv40_state_entry nv40_state_scissor; +extern struct nv40_state_entry nv40_state_stipple; +extern struct nv40_state_entry nv40_state_fragprog; +extern struct nv40_state_entry nv40_state_vertprog; +extern struct nv40_state_entry nv40_state_blend; +extern struct nv40_state_entry nv40_state_blend_colour; +extern struct nv40_state_entry nv40_state_zsa; +extern struct nv40_state_entry nv40_state_viewport; +extern struct nv40_state_entry nv40_state_framebuffer; +extern struct nv40_state_entry nv40_state_fragtex; +extern struct nv40_state_entry nv40_state_vbo; +extern struct nv40_state_entry nv40_state_vtxfmt; + +/* nv40_vbo.c */ +extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode, +				unsigned start, unsigned count); +extern boolean nv40_draw_elements(struct pipe_context *pipe, +				  struct pipe_buffer *indexBuffer, +				  unsigned indexSize, +				  unsigned mode, unsigned start, +				  unsigned count); + +/* nv40_clear.c */ +extern void nv40_clear(struct pipe_context *pipe, struct pipe_surface *ps, +		       unsigned clearValue); + +#endif diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c new file mode 100644 index 0000000000..2cf58e2950 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_draw.c @@ -0,0 +1,348 @@ +#include "pipe/p_util.h" +#include "pipe/p_shader_tokens.h" + +#include "draw/draw_context.h" +#include "draw/draw_vertex.h" +#include "draw/draw_pipe.h" + +#include "nv40_context.h" +#define NV40_SHADER_NO_FUCKEDNESS +#include "nv40_shader.h" + +/* Simple, but crappy, swtnl path, hopefully we wont need to hit this very + * often at all.  Uses "quadro style" vertex submission + a fixed vertex + * layout to avoid the need to generate a vertex program or vtxfmt. + */ + +struct nv40_render_stage { +	struct draw_stage stage; +	struct nv40_context *nv40; +	unsigned prim; +}; + +static INLINE struct nv40_render_stage * +nv40_render_stage(struct draw_stage *stage) +{ +	return (struct nv40_render_stage *)stage; +} + +static INLINE void +nv40_render_vertex(struct nv40_context *nv40, const struct vertex_header *v) +{ +	unsigned i; + +	for (i = 0; i < nv40->swtnl.nr_attribs; i++) { +		unsigned idx = nv40->swtnl.draw[i]; +		unsigned hw = nv40->swtnl.hw[i]; + +		switch (nv40->swtnl.emit[i]) { +		case EMIT_OMIT: +			break; +		case EMIT_1F: +			BEGIN_RING(curie, NV40TCL_VTX_ATTR_1F(hw), 1); +			OUT_RING  (fui(v->data[idx][0])); +			break; +		case EMIT_2F: +			BEGIN_RING(curie, NV40TCL_VTX_ATTR_2F_X(hw), 2); +			OUT_RING  (fui(v->data[idx][0])); +			OUT_RING  (fui(v->data[idx][1])); +			break; +		case EMIT_3F: +			BEGIN_RING(curie, NV40TCL_VTX_ATTR_3F_X(hw), 3); +			OUT_RING  (fui(v->data[idx][0])); +			OUT_RING  (fui(v->data[idx][1])); +			OUT_RING  (fui(v->data[idx][2])); +			break; +		case EMIT_4F: +			BEGIN_RING(curie, NV40TCL_VTX_ATTR_4F_X(hw), 4); +			OUT_RING  (fui(v->data[idx][0])); +			OUT_RING  (fui(v->data[idx][1])); +			OUT_RING  (fui(v->data[idx][2])); +			OUT_RING  (fui(v->data[idx][3])); +			break; +		case EMIT_4UB: +			BEGIN_RING(curie, NV40TCL_VTX_ATTR_4UB(hw), 1); +			OUT_RING  (pack_ub4(float_to_ubyte(v->data[idx][0]), +					    float_to_ubyte(v->data[idx][1]), +					    float_to_ubyte(v->data[idx][2]), +					    float_to_ubyte(v->data[idx][3]))); +			break; +		default: +			assert(0); +			break; +		} +	} +} + +static INLINE void +nv40_render_prim(struct draw_stage *stage, struct prim_header *prim, +	       unsigned mode, unsigned count) +{ +	struct nv40_render_stage *rs = nv40_render_stage(stage); +	struct nv40_context *nv40 = rs->nv40; +	struct nouveau_pushbuf *pb = nv40->nvws->channel->pushbuf; +	unsigned i; + +	/* Ensure there's room for 4xfloat32 + potentially 3 begin/end */ +	if (pb->remaining < ((count * 20) + 6)) { +		if (rs->prim != NV40TCL_BEGIN_END_STOP) { +			NOUVEAU_ERR("AIII, missed flush\n"); +			assert(0); +		} +		FIRE_RING(NULL); +		nv40_state_emit(nv40); +	} + +	/* Switch primitive modes if necessary */ +	if (rs->prim != mode) { +		if (rs->prim != NV40TCL_BEGIN_END_STOP) { +			BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +			OUT_RING  (NV40TCL_BEGIN_END_STOP);	 +		} + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (mode); +		rs->prim = mode; +	} + +	/* Emit vertex data */ +	for (i = 0; i < count; i++) +		nv40_render_vertex(nv40, prim->v[i]); + +	/* If it's likely we'll need to empty the push buffer soon, finish +	 * off the primitive now. +	 */ +	if (pb->remaining < ((count * 20) + 6)) { +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (NV40TCL_BEGIN_END_STOP); +		rs->prim = NV40TCL_BEGIN_END_STOP; +	} +} + +static void +nv40_render_point(struct draw_stage *draw, struct prim_header *prim) +{ +	nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_POINTS, 1); +} + +static void +nv40_render_line(struct draw_stage *draw, struct prim_header *prim) +{ +	nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_LINES, 2); +} + +static void +nv40_render_tri(struct draw_stage *draw, struct prim_header *prim) +{ +	nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_TRIANGLES, 3); +} + +static void +nv40_render_flush(struct draw_stage *draw, unsigned flags) +{ +	struct nv40_render_stage *rs = nv40_render_stage(draw); +	struct nv40_context *nv40 = rs->nv40; + +	if (rs->prim != NV40TCL_BEGIN_END_STOP) { +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (NV40TCL_BEGIN_END_STOP); +		rs->prim = NV40TCL_BEGIN_END_STOP; +	} +} + +static void +nv40_render_reset_stipple_counter(struct draw_stage *draw) +{ +} + +static void +nv40_render_destroy(struct draw_stage *draw) +{ +	FREE(draw); +} + +static INLINE void +emit_mov(struct nv40_vertex_program *vp, +	 unsigned dst, unsigned src, unsigned vor, unsigned mask) +{ +	struct nv40_vertex_program_exec *inst; + +	vp->insns = realloc(vp->insns, +			    sizeof(struct nv40_vertex_program_exec) * +			    ++vp->nr_insns); +	inst = &vp->insns[vp->nr_insns - 1]; + +	inst->data[0] = 0x401f9c6c; +	inst->data[1] = 0x0040000d | (src << 8); +	inst->data[2] = 0x8106c083; +	inst->data[3] = 0x6041ff80 | (dst << 2) | (mask << 13); +	inst->const_index = -1; +	inst->has_branch_offset = FALSE; + +	vp->ir |= (1 << src); +	if (vor != ~0) +		vp->or |= (1 << vor); +} + +static struct nv40_vertex_program * +create_drawvp(struct nv40_context *nv40) +{ +	struct nv40_vertex_program *vp = CALLOC_STRUCT(nv40_vertex_program); +	unsigned i; + +	emit_mov(vp, NV40_VP_INST_DEST_POS, 0, ~0, 0xf); +	emit_mov(vp, NV40_VP_INST_DEST_COL0, 3, 0, 0xf); +	emit_mov(vp, NV40_VP_INST_DEST_COL1, 4, 1, 0xf); +	emit_mov(vp, NV40_VP_INST_DEST_BFC0, 3, 2, 0xf); +	emit_mov(vp, NV40_VP_INST_DEST_BFC1, 4, 3, 0xf); +	emit_mov(vp, NV40_VP_INST_DEST_FOGC, 5, 4, 0x8); +	for (i = 0; i < 8; i++) +		emit_mov(vp, NV40_VP_INST_DEST_TC(i), 8 + i, 14 + i, 0xf); + +	vp->insns[vp->nr_insns - 1].data[3] |= 1; +	vp->translated = TRUE; +	return vp; +} + +struct draw_stage * +nv40_draw_render_stage(struct nv40_context *nv40) +{ +	struct nv40_render_stage *render = CALLOC_STRUCT(nv40_render_stage); + +	if (!nv40->swtnl.vertprog) +		nv40->swtnl.vertprog = create_drawvp(nv40); + +	render->nv40 = nv40; +	render->stage.draw = nv40->draw; +	render->stage.point = nv40_render_point; +	render->stage.line = nv40_render_line; +	render->stage.tri = nv40_render_tri; +	render->stage.flush = nv40_render_flush; +	render->stage.reset_stipple_counter = nv40_render_reset_stipple_counter; +	render->stage.destroy = nv40_render_destroy; + +	return &render->stage; +} + +boolean +nv40_draw_elements_swtnl(struct pipe_context *pipe, +			 struct pipe_buffer *idxbuf, unsigned idxbuf_size, +			 unsigned mode, unsigned start, unsigned count) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct pipe_winsys *ws = pipe->winsys; +	unsigned i; +	void *map; + +	if (!nv40_state_validate_swtnl(nv40)) +		return FALSE; +	nv40->state.dirty &= ~(1ULL << NV40_STATE_VTXBUF); +	nv40_state_emit(nv40); + +	for (i = 0; i < nv40->vtxbuf_nr; i++) { +		map = ws->buffer_map(ws, nv40->vtxbuf[i].buffer, +				     PIPE_BUFFER_USAGE_CPU_READ); +		draw_set_mapped_vertex_buffer(nv40->draw, i, map); +	} + +	if (idxbuf) { +		map = ws->buffer_map(ws, idxbuf, PIPE_BUFFER_USAGE_CPU_READ); +		draw_set_mapped_element_buffer(nv40->draw, idxbuf_size, map); +	} else { +		draw_set_mapped_element_buffer(nv40->draw, 0, NULL); +	} + +	if (nv40->constbuf[PIPE_SHADER_VERTEX]) { +		const unsigned nr = nv40->constbuf_nr[PIPE_SHADER_VERTEX]; + +		map = ws->buffer_map(ws, nv40->constbuf[PIPE_SHADER_VERTEX], +				     PIPE_BUFFER_USAGE_CPU_READ); +		draw_set_mapped_constant_buffer(nv40->draw, map, nr); +	} + +	draw_arrays(nv40->draw, mode, start, count); + +	for (i = 0; i < nv40->vtxbuf_nr; i++) +		ws->buffer_unmap(ws, nv40->vtxbuf[i].buffer); + +	if (idxbuf) +		ws->buffer_unmap(ws, idxbuf); + +	if (nv40->constbuf[PIPE_SHADER_VERTEX]) +		ws->buffer_unmap(ws, nv40->constbuf[PIPE_SHADER_VERTEX]); + +	draw_flush(nv40->draw); +	pipe->flush(pipe, 0, NULL); + +	return TRUE; +} + +static INLINE void +emit_attrib(struct nv40_context *nv40, unsigned hw, unsigned emit, +	    unsigned semantic, unsigned index) +{ +	unsigned draw_out = draw_find_vs_output(nv40->draw, semantic, index); +	unsigned a = nv40->swtnl.nr_attribs++; + +	nv40->swtnl.hw[a] = hw; +	nv40->swtnl.emit[a] = emit; +	nv40->swtnl.draw[a] = draw_out; +} + +static boolean +nv40_state_vtxfmt_validate(struct nv40_context *nv40) +{ +	struct nv40_fragment_program *fp = nv40->fragprog; +	unsigned colour = 0, texcoords = 0, fog = 0, i; + +	/* Determine needed fragprog inputs */ +	for (i = 0; i < fp->info.num_inputs; i++) { +		switch (fp->info.input_semantic_name[i]) { +		case TGSI_SEMANTIC_POSITION: +			break; +		case TGSI_SEMANTIC_COLOR: +			colour |= (1 << fp->info.input_semantic_index[i]); +			break; +		case TGSI_SEMANTIC_GENERIC: +			texcoords |= (1 << fp->info.input_semantic_index[i]); +			break; +		case TGSI_SEMANTIC_FOG: +			fog = 1; +			break; +		default: +			assert(0); +		} +	} + +	nv40->swtnl.nr_attribs = 0; + +	/* Map draw vtxprog output to hw attribute IDs */ +	for (i = 0; i < 2; i++) { +		if (!(colour & (1 << i))) +			continue; +		emit_attrib(nv40, 3 + i, EMIT_4UB, TGSI_SEMANTIC_COLOR, i); +	} + +	for (i = 0; i < 8; i++) { +		if (!(texcoords & (1 << i))) +			continue; +		emit_attrib(nv40, 8 + i, EMIT_4F, TGSI_SEMANTIC_GENERIC, i); +	} + +	if (fog) { +		emit_attrib(nv40, 5, EMIT_1F, TGSI_SEMANTIC_FOG, 0); +	} + +	emit_attrib(nv40, 0, EMIT_3F, TGSI_SEMANTIC_POSITION, 0); + +	return FALSE; +} + +struct nv40_state_entry nv40_state_vtxfmt = { +	.validate = nv40_state_vtxfmt_validate, +	.dirty = { +		.pipe = NV40_NEW_ARRAYS | NV40_NEW_FRAGPROG, +		.hw = 0 +	} +}; + diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c new file mode 100644 index 0000000000..a361509e8f --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_fragprog.c @@ -0,0 +1,991 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" + +#include "nv40_context.h" + +#define SWZ_X 0 +#define SWZ_Y 1 +#define SWZ_Z 2 +#define SWZ_W 3 +#define MASK_X 1 +#define MASK_Y 2 +#define MASK_Z 4 +#define MASK_W 8 +#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) +#define DEF_SCALE NV40_FP_OP_DST_SCALE_1X +#define DEF_CTEST NV40_FP_OP_COND_TR +#include "nv40_shader.h" + +#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) +#define neg(s) nv40_sr_neg((s)) +#define abs(s) nv40_sr_abs((s)) +#define scale(s,v) nv40_sr_scale((s), NV40_FP_OP_DST_SCALE_##v) + +#define MAX_CONSTS 128 +#define MAX_IMM 32 +struct nv40_fpc { +	struct nv40_fragment_program *fp; + +	uint attrib_map[PIPE_MAX_SHADER_INPUTS]; + +	unsigned r_temps; +	unsigned r_temps_discard; +	struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; +	struct nv40_sreg *r_temp; + +	int num_regs; + +	unsigned inst_offset; +	unsigned have_const; + +	struct { +		int pipe; +		float vals[4]; +	} consts[MAX_CONSTS]; +	int nr_consts; + +	struct nv40_sreg imm[MAX_IMM]; +	unsigned nr_imm; +}; + +static INLINE struct nv40_sreg +temp(struct nv40_fpc *fpc) +{ +	int idx = ffs(~fpc->r_temps) - 1; + +	if (idx < 0) { +		NOUVEAU_ERR("out of temps!!\n"); +		assert(0); +		return nv40_sr(NV40SR_TEMP, 0); +	} + +	fpc->r_temps |= (1 << idx); +	fpc->r_temps_discard |= (1 << idx); +	return nv40_sr(NV40SR_TEMP, idx); +} + +static INLINE void +release_temps(struct nv40_fpc *fpc) +{ +	fpc->r_temps &= ~fpc->r_temps_discard; +	fpc->r_temps_discard = 0; +} + +static INLINE struct nv40_sreg +constant(struct nv40_fpc *fpc, int pipe, float vals[4]) +{ +	int idx; + +	if (fpc->nr_consts == MAX_CONSTS) +		assert(0); +	idx = fpc->nr_consts++; + +	fpc->consts[idx].pipe = pipe; +	if (pipe == -1) +		memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float)); +	return nv40_sr(NV40SR_CONST, idx); +} + +#define arith(cc,s,o,d,m,s0,s1,s2) \ +	nv40_fp_arith((cc), (s), NV40_FP_OP_OPCODE_##o, \ +			(d), (m), (s0), (s1), (s2)) +#define tex(cc,s,o,u,d,m,s0,s1,s2) \ +	nv40_fp_tex((cc), (s), NV40_FP_OP_OPCODE_##o, (u), \ +		    (d), (m), (s0), none, none) + +static void +grow_insns(struct nv40_fpc *fpc, int size) +{ +	struct nv40_fragment_program *fp = fpc->fp; + +	fp->insn_len += size; +	fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len); +} + +static void +emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src) +{ +	struct nv40_fragment_program *fp = fpc->fp; +	uint32_t *hw = &fp->insn[fpc->inst_offset]; +	uint32_t sr = 0; + +	switch (src.type) { +	case NV40SR_INPUT: +		sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT); +		hw[0] |= (src.index << NV40_FP_OP_INPUT_SRC_SHIFT); +		break; +	case NV40SR_OUTPUT: +		sr |= NV40_FP_REG_SRC_HALF; +		/* fall-through */ +	case NV40SR_TEMP: +		sr |= (NV40_FP_REG_TYPE_TEMP << NV40_FP_REG_TYPE_SHIFT); +		sr |= (src.index << NV40_FP_REG_SRC_SHIFT); +		break; +	case NV40SR_CONST: +		if (!fpc->have_const) { +			grow_insns(fpc, 4); +			fpc->have_const = 1; +		} + +		hw = &fp->insn[fpc->inst_offset]; +		if (fpc->consts[src.index].pipe >= 0) { +			struct nv40_fragment_program_data *fpd; + +			fp->consts = realloc(fp->consts, ++fp->nr_consts * +					     sizeof(*fpd)); +			fpd = &fp->consts[fp->nr_consts - 1]; +			fpd->offset = fpc->inst_offset + 4; +			fpd->index = fpc->consts[src.index].pipe; +			memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4); +		} else { +			memcpy(&fp->insn[fpc->inst_offset + 4], +				fpc->consts[src.index].vals, +				sizeof(uint32_t) * 4); +		} + +		sr |= (NV40_FP_REG_TYPE_CONST << NV40_FP_REG_TYPE_SHIFT);	 +		break; +	case NV40SR_NONE: +		sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT); +		break; +	default: +		assert(0); +	} + +	if (src.negate) +		sr |= NV40_FP_REG_NEGATE; + +	if (src.abs) +		hw[1] |= (1 << (29 + pos)); + +	sr |= ((src.swz[0] << NV40_FP_REG_SWZ_X_SHIFT) | +	       (src.swz[1] << NV40_FP_REG_SWZ_Y_SHIFT) | +	       (src.swz[2] << NV40_FP_REG_SWZ_Z_SHIFT) | +	       (src.swz[3] << NV40_FP_REG_SWZ_W_SHIFT)); + +	hw[pos + 1] |= sr; +} + +static void +emit_dst(struct nv40_fpc *fpc, struct nv40_sreg dst) +{ +	struct nv40_fragment_program *fp = fpc->fp; +	uint32_t *hw = &fp->insn[fpc->inst_offset]; + +	switch (dst.type) { +	case NV40SR_TEMP: +		if (fpc->num_regs < (dst.index + 1)) +			fpc->num_regs = dst.index + 1; +		break; +	case NV40SR_OUTPUT: +		if (dst.index == 1) { +			fp->fp_control |= 0xe; +		} else { +			hw[0] |= NV40_FP_OP_OUT_REG_HALF; +		} +		break; +	case NV40SR_NONE: +		hw[0] |= (1 << 30); +		break; +	default: +		assert(0); +	} + +	hw[0] |= (dst.index << NV40_FP_OP_OUT_REG_SHIFT); +} + +static void +nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op, +	      struct nv40_sreg dst, int mask, +	      struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2) +{ +	struct nv40_fragment_program *fp = fpc->fp; +	uint32_t *hw; + +	fpc->inst_offset = fp->insn_len; +	fpc->have_const = 0; +	grow_insns(fpc, 4); +	hw = &fp->insn[fpc->inst_offset]; +	memset(hw, 0, sizeof(uint32_t) * 4); + +	if (op == NV40_FP_OP_OPCODE_KIL) +		fp->fp_control |= NV40TCL_FP_CONTROL_KIL; +	hw[0] |= (op << NV40_FP_OP_OPCODE_SHIFT); +	hw[0] |= (mask << NV40_FP_OP_OUTMASK_SHIFT); +	hw[2] |= (dst.dst_scale << NV40_FP_OP_DST_SCALE_SHIFT); + +	if (sat) +		hw[0] |= NV40_FP_OP_OUT_SAT; + +	if (dst.cc_update) +		hw[0] |= NV40_FP_OP_COND_WRITE_ENABLE; +	hw[1] |= (dst.cc_test << NV40_FP_OP_COND_SHIFT); +	hw[1] |= ((dst.cc_swz[0] << NV40_FP_OP_COND_SWZ_X_SHIFT) | +		  (dst.cc_swz[1] << NV40_FP_OP_COND_SWZ_Y_SHIFT) | +		  (dst.cc_swz[2] << NV40_FP_OP_COND_SWZ_Z_SHIFT) | +		  (dst.cc_swz[3] << NV40_FP_OP_COND_SWZ_W_SHIFT)); + +	emit_dst(fpc, dst); +	emit_src(fpc, 0, s0); +	emit_src(fpc, 1, s1); +	emit_src(fpc, 2, s2); +} + +static void +nv40_fp_tex(struct nv40_fpc *fpc, int sat, int op, int unit, +	    struct nv40_sreg dst, int mask, +	    struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2) +{ +	struct nv40_fragment_program *fp = fpc->fp; + +	nv40_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); + +	fp->insn[fpc->inst_offset] |= (unit << NV40_FP_OP_TEX_UNIT_SHIFT); +	fp->samplers |= (1 << unit); +} + +static INLINE struct nv40_sreg +tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc) +{ +	struct nv40_sreg src; + +	switch (fsrc->SrcRegister.File) { +	case TGSI_FILE_INPUT: +		src = nv40_sr(NV40SR_INPUT, +			      fpc->attrib_map[fsrc->SrcRegister.Index]); +		break; +	case TGSI_FILE_CONSTANT: +		src = constant(fpc, fsrc->SrcRegister.Index, NULL); +		break; +	case TGSI_FILE_IMMEDIATE: +		assert(fsrc->SrcRegister.Index < fpc->nr_imm); +		src = fpc->imm[fsrc->SrcRegister.Index]; +		break; +	case TGSI_FILE_TEMPORARY: +		src = fpc->r_temp[fsrc->SrcRegister.Index]; +		break; +	/* NV40 fragprog result regs are just temps, so this is simple */ +	case TGSI_FILE_OUTPUT: +		src = fpc->r_result[fsrc->SrcRegister.Index]; +		break; +	default: +		NOUVEAU_ERR("bad src file\n"); +		break; +	} + +	src.abs = fsrc->SrcRegisterExtMod.Absolute; +	src.negate = fsrc->SrcRegister.Negate; +	src.swz[0] = fsrc->SrcRegister.SwizzleX; +	src.swz[1] = fsrc->SrcRegister.SwizzleY; +	src.swz[2] = fsrc->SrcRegister.SwizzleZ; +	src.swz[3] = fsrc->SrcRegister.SwizzleW; +	return src; +} + +static INLINE struct nv40_sreg +tgsi_dst(struct nv40_fpc *fpc, const struct tgsi_full_dst_register *fdst) { +	switch (fdst->DstRegister.File) { +	case TGSI_FILE_OUTPUT: +		return fpc->r_result[fdst->DstRegister.Index]; +	case TGSI_FILE_TEMPORARY: +		return fpc->r_temp[fdst->DstRegister.Index]; +	case TGSI_FILE_NULL: +		return nv40_sr(NV40SR_NONE, 0); +	default: +		NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File); +		return nv40_sr(NV40SR_NONE, 0); +	} +} + +static INLINE int +tgsi_mask(uint tgsi) +{ +	int mask = 0; + +	if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; +	if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; +	if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; +	if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; +	return mask; +} + +static boolean +src_native_swz(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc, +	       struct nv40_sreg *src) +{ +	const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); +	struct nv40_sreg tgsi = tgsi_src(fpc, fsrc); +	uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0; +	uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX, +			fsrc->SrcRegisterExtSwz.NegateY, +			fsrc->SrcRegisterExtSwz.NegateZ, +			fsrc->SrcRegisterExtSwz.NegateW }; +	uint c; + +	for (c = 0; c < 4; c++) { +		switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) { +		case TGSI_EXTSWIZZLE_X: +		case TGSI_EXTSWIZZLE_Y: +		case TGSI_EXTSWIZZLE_Z: +		case TGSI_EXTSWIZZLE_W: +			mask |= (1 << c); +			break; +		case TGSI_EXTSWIZZLE_ZERO: +			zero_mask |= (1 << c); +			tgsi.swz[c] = SWZ_X; +			break; +		case TGSI_EXTSWIZZLE_ONE: +			one_mask |= (1 << c); +			tgsi.swz[c] = SWZ_X; +			break; +		default: +			assert(0); +		} + +		if (!tgsi.negate && neg[c]) +			neg_mask |= (1 << c); +	} + +	if (mask == MASK_ALL && !neg_mask) +		return TRUE; + +	*src = temp(fpc); + +	if (mask) +		arith(fpc, 0, MOV, *src, mask, tgsi, none, none); + +	if (zero_mask) +		arith(fpc, 0, SFL, *src, zero_mask, *src, none, none); + +	if (one_mask) +		arith(fpc, 0, STR, *src, one_mask, *src, none, none); + +	if (neg_mask) { +		struct nv40_sreg one = temp(fpc); +		arith(fpc, 0, STR, one, neg_mask, one, none, none); +		arith(fpc, 0, MUL, *src, neg_mask, *src, neg(one), none); +	} + +	return FALSE; +} + +static boolean +nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, +				const struct tgsi_full_instruction *finst) +{ +	const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); +	struct nv40_sreg src[3], dst, tmp; +	int mask, sat, unit; +	int ai = -1, ci = -1, ii = -1; +	int i; + +	if (finst->Instruction.Opcode == TGSI_OPCODE_END) +		return TRUE; + +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; +		if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) { +			src[i] = tgsi_src(fpc, fsrc); +		} +	} + +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; + +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +		case TGSI_FILE_CONSTANT: +		case TGSI_FILE_TEMPORARY: +			if (!src_native_swz(fpc, fsrc, &src[i])) +				continue; +			break; +		default: +			break; +		} + +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +			if (ai == -1 || ai == fsrc->SrcRegister.Index) { +				ai = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(fpc, fsrc); +			} else { +				src[i] = temp(fpc); +				arith(fpc, 0, MOV, src[i], MASK_ALL, +				      tgsi_src(fpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_CONSTANT: +			if ((ci == -1 && ii == -1) || +			    ci == fsrc->SrcRegister.Index) { +				ci = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(fpc, fsrc); +			} else { +				src[i] = temp(fpc); +				arith(fpc, 0, MOV, src[i], MASK_ALL, +				      tgsi_src(fpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_IMMEDIATE: +			if ((ci == -1 && ii == -1) || +			    ii == fsrc->SrcRegister.Index) { +				ii = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(fpc, fsrc); +			} else { +				src[i] = temp(fpc); +				arith(fpc, 0, MOV, src[i], MASK_ALL, +				      tgsi_src(fpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_TEMPORARY: +			/* handled above */ +			break; +		case TGSI_FILE_SAMPLER: +			unit = fsrc->SrcRegister.Index; +			break; +		case TGSI_FILE_OUTPUT: +			break; +		default: +			NOUVEAU_ERR("bad src file\n"); +			return FALSE; +		} +	} + +	dst  = tgsi_dst(fpc, &finst->FullDstRegisters[0]); +	mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask); +	sat  = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE); + +	switch (finst->Instruction.Opcode) { +	case TGSI_OPCODE_ABS: +		arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none); +		break; +	case TGSI_OPCODE_ADD: +		arith(fpc, sat, ADD, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_CMP: +		tmp = temp(fpc); +		arith(fpc, sat, MOV, dst, mask, src[2], none, none); +		tmp.cc_update = 1; +		arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none); +		dst.cc_test = NV40_VP_INST_COND_LT; +		arith(fpc, sat, MOV, dst, mask, src[1], none, none); +		break; +	case TGSI_OPCODE_COS: +		arith(fpc, sat, COS, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_DDX: +		if (mask & (MASK_Z | MASK_W)) { +			tmp = temp(fpc); +			arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, +			      swz(src[0], Z, W, Z, W), none, none); +			arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W, +			      swz(tmp, X, Y, X, Y), none, none); +			arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, src[0], +			      none, none); +			arith(fpc, 0, MOV, dst, mask, tmp, none, none); +		} else { +			arith(fpc, sat, DDX, dst, mask, src[0], none, none); +		} +		break; +	case TGSI_OPCODE_DDY: +		if (mask & (MASK_Z | MASK_W)) { +			tmp = temp(fpc); +			arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, +			      swz(src[0], Z, W, Z, W), none, none); +			arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W, +			      swz(tmp, X, Y, X, Y), none, none); +			arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, src[0], +			      none, none); +			arith(fpc, 0, MOV, dst, mask, tmp, none, none); +		} else { +			arith(fpc, sat, DDY, dst, mask, src[0], none, none); +		} +		break; +	case TGSI_OPCODE_DP3: +		arith(fpc, sat, DP3, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DP4: +		arith(fpc, sat, DP4, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DPH: +		tmp = temp(fpc); +		arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none); +		arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X), +		      swz(src[1], W, W, W, W), none); +		break; +	case TGSI_OPCODE_DST: +		arith(fpc, sat, DST, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_EX2: +		arith(fpc, sat, EX2, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_FLR: +		arith(fpc, sat, FLR, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_FRC: +		arith(fpc, sat, FRC, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_KIL: +		arith(fpc, 0, KIL, none, 0, none, none, none); +		break; +	case TGSI_OPCODE_KILP: +		dst = nv40_sr(NV40SR_NONE, 0); +		dst.cc_update = 1; +		arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none); +		dst.cc_update = 0; dst.cc_test = NV40_FP_OP_COND_LT; +		arith(fpc, 0, KIL, dst, 0, none, none, none); +		break; +	case TGSI_OPCODE_LG2: +		arith(fpc, sat, LG2, dst, mask, src[0], none, none); +		break; +//	case TGSI_OPCODE_LIT: +	case TGSI_OPCODE_LRP: +		tmp = temp(fpc); +		arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]); +		arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp); +		break; +	case TGSI_OPCODE_MAD: +		arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]); +		break; +	case TGSI_OPCODE_MAX: +		arith(fpc, sat, MAX, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MIN: +		arith(fpc, sat, MIN, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MOV: +		arith(fpc, sat, MOV, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_MUL: +		arith(fpc, sat, MUL, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_NOISE1: +	case TGSI_OPCODE_NOISE2: +	case TGSI_OPCODE_NOISE3: +	case TGSI_OPCODE_NOISE4: +		arith(fpc, sat, SFL, dst, mask, none, none, none); +		break; +	case TGSI_OPCODE_POW: +		tmp = temp(fpc); +		arith(fpc, 0, LG2, tmp, MASK_X, +		      swz(src[0], X, X, X, X), none, none); +		arith(fpc, 0, MUL, tmp, MASK_X, swz(tmp, X, X, X, X), +		      swz(src[1], X, X, X, X), none); +		arith(fpc, sat, EX2, dst, mask, +		      swz(tmp, X, X, X, X), none, none); +		break; +	case TGSI_OPCODE_RCP: +		arith(fpc, sat, RCP, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_RET: +		assert(0); +		break; +	case TGSI_OPCODE_RFL: +		tmp = temp(fpc); +		arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[0], none); +		arith(fpc, 0, DP3, tmp, MASK_Y, src[0], src[1], none); +		arith(fpc, 0, DIV, scale(tmp, 2X), MASK_Z, +		      swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none); +		arith(fpc, sat, MAD, dst, mask, +		      swz(tmp, Z, Z, Z, Z), src[0], neg(src[1])); +		break; +	case TGSI_OPCODE_RSQ: +		tmp = temp(fpc); +		arith(fpc, 0, LG2, scale(tmp, INV_2X), MASK_X, +		      abs(swz(src[0], X, X, X, X)), none, none); +		arith(fpc, sat, EX2, dst, mask, +		      neg(swz(tmp, X, X, X, X)), none, none); +		break; +	case TGSI_OPCODE_SCS: +		if (mask & MASK_X) { +			arith(fpc, sat, COS, dst, MASK_X, +			      swz(src[0], X, X, X, X), none, none); +		} +		if (mask & MASK_Y) { +			arith(fpc, sat, SIN, dst, MASK_Y, +			      swz(src[0], X, X, X, X), none, none); +		} +		break; +	case TGSI_OPCODE_SEQ: +		arith(fpc, sat, SEQ, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SFL: +		arith(fpc, sat, SFL, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SGE: +		arith(fpc, sat, SGE, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SGT: +		arith(fpc, sat, SGT, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SIN: +		arith(fpc, sat, SIN, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_SLE: +		arith(fpc, sat, SLE, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SLT: +		arith(fpc, sat, SLT, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SNE: +		arith(fpc, sat, SNE, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_STR: +		arith(fpc, sat, STR, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SUB: +		arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none); +		break; +	case TGSI_OPCODE_TEX: +		tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_TXB: +		tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_TXP: +		tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_XPD: +		tmp = temp(fpc); +		arith(fpc, 0, MUL, tmp, mask, +		      swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); +		arith(fpc, sat, MAD, dst, (mask & ~MASK_W), +		      swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), +		      neg(tmp)); +		break; +	default: +		NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); +		return FALSE; +	} + +	release_temps(fpc); +	return TRUE; +} + +static boolean +nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc, +				const struct tgsi_full_declaration *fdec) +{ +	int hw; + +	switch (fdec->Semantic.SemanticName) { +	case TGSI_SEMANTIC_POSITION: +		hw = NV40_FP_OP_INPUT_SRC_POSITION; +		break; +	case TGSI_SEMANTIC_COLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV40_FP_OP_INPUT_SRC_COL0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV40_FP_OP_INPUT_SRC_COL1; +		} else { +			NOUVEAU_ERR("bad colour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_FOG: +		hw = NV40_FP_OP_INPUT_SRC_FOGC; +		break; +	case TGSI_SEMANTIC_GENERIC: +		if (fdec->Semantic.SemanticIndex <= 7) { +			hw = NV40_FP_OP_INPUT_SRC_TC(fdec->Semantic. +						     SemanticIndex); +		} else { +			NOUVEAU_ERR("bad generic semantic index\n"); +			return FALSE; +		} +		break; +	default: +		NOUVEAU_ERR("bad input semantic\n"); +		return FALSE; +	} + +	fpc->attrib_map[fdec->DeclarationRange.First] = hw; +	return TRUE; +} + +static boolean +nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc, +				const struct tgsi_full_declaration *fdec) +{ +	unsigned idx = fdec->DeclarationRange.First; +	unsigned hw; + +	switch (fdec->Semantic.SemanticName) { +	case TGSI_SEMANTIC_POSITION: +		hw = 1; +		break; +	case TGSI_SEMANTIC_COLOR: +		switch (fdec->Semantic.SemanticIndex) { +		case 0: hw = 0; break; +		case 1: hw = 2; break; +		case 2: hw = 3; break; +		case 3: hw = 4; break; +		default: +			NOUVEAU_ERR("bad rcol index\n"); +			return FALSE; +		} +		break; +	default: +		NOUVEAU_ERR("bad output semantic\n"); +		return FALSE; +	} + +	fpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw); +	fpc->r_temps |= (1 << hw); +	return TRUE; +} + +static boolean +nv40_fragprog_prepare(struct nv40_fpc *fpc) +{ +	struct tgsi_parse_context p; +	int high_temp = -1, i; + +	tgsi_parse_init(&p, fpc->fp->pipe.tokens); +	while (!tgsi_parse_end_of_tokens(&p)) { +		const union tgsi_full_token *tok = &p.FullToken; + +		tgsi_parse_token(&p); +		switch(tok->Token.Type) { +		case TGSI_TOKEN_TYPE_DECLARATION: +		{ +			const struct tgsi_full_declaration *fdec; +			fdec = &p.FullToken.FullDeclaration; +			switch (fdec->Declaration.File) { +			case TGSI_FILE_INPUT: +				if (!nv40_fragprog_parse_decl_attrib(fpc, fdec)) +					goto out_err; +				break; +			case TGSI_FILE_OUTPUT: +				if (!nv40_fragprog_parse_decl_output(fpc, fdec)) +					goto out_err; +				break; +			case TGSI_FILE_TEMPORARY: +				if (fdec->DeclarationRange.Last > high_temp) { +					high_temp = +						fdec->DeclarationRange.Last; +				} +				break; +			default: +				break; +			} +		} +			break; +		case TGSI_TOKEN_TYPE_IMMEDIATE: +		{ +			struct tgsi_full_immediate *imm; +			float vals[4]; +			 +			imm = &p.FullToken.FullImmediate; +			assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); +			assert(fpc->nr_imm < MAX_IMM); + +			vals[0] = imm->u.ImmediateFloat32[0].Float; +			vals[1] = imm->u.ImmediateFloat32[1].Float; +			vals[2] = imm->u.ImmediateFloat32[2].Float; +			vals[3] = imm->u.ImmediateFloat32[3].Float; +			fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals); +		} +			break; +		default: +			break; +		} +	} +	tgsi_parse_free(&p); + +	if (++high_temp) { +		fpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg)); +		for (i = 0; i < high_temp; i++) +			fpc->r_temp[i] = temp(fpc); +		fpc->r_temps_discard = 0; +	} + +	return TRUE; + +out_err: +	if (fpc->r_temp) +		FREE(fpc->r_temp); +	tgsi_parse_free(&p); +	return FALSE; +} + +static void +nv40_fragprog_translate(struct nv40_context *nv40, +			struct nv40_fragment_program *fp) +{ +	struct tgsi_parse_context parse; +	struct nv40_fpc *fpc = NULL; + +	fpc = CALLOC(1, sizeof(struct nv40_fpc)); +	if (!fpc) +		return; +	fpc->fp = fp; +	fpc->num_regs = 2; + +	if (!nv40_fragprog_prepare(fpc)) { +		FREE(fpc); +		return; +	} + +	tgsi_parse_init(&parse, fp->pipe.tokens); + +	while (!tgsi_parse_end_of_tokens(&parse)) { +		tgsi_parse_token(&parse); + +		switch (parse.FullToken.Token.Type) { +		case TGSI_TOKEN_TYPE_INSTRUCTION: +		{ +			const struct tgsi_full_instruction *finst; + +			finst = &parse.FullToken.FullInstruction; +			if (!nv40_fragprog_parse_instruction(fpc, finst)) +				goto out_err; +		} +			break; +		default: +			break; +		} +	} + +	fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT; + +	/* Terminate final instruction */ +	fp->insn[fpc->inst_offset] |= 0x00000001; + +	/* Append NOP + END instruction, may or may not be necessary. */ +	fpc->inst_offset = fp->insn_len; +	grow_insns(fpc, 4); +	fp->insn[fpc->inst_offset + 0] = 0x00000001; +	fp->insn[fpc->inst_offset + 1] = 0x00000000; +	fp->insn[fpc->inst_offset + 2] = 0x00000000; +	fp->insn[fpc->inst_offset + 3] = 0x00000000; +	 +	fp->translated = TRUE; +out_err: +	tgsi_parse_free(&parse); +	if (fpc->r_temp) +		FREE(fpc->r_temp); +	FREE(fpc); +} + +static void +nv40_fragprog_upload(struct nv40_context *nv40, +		     struct nv40_fragment_program *fp) +{ +	struct pipe_winsys *ws = nv40->pipe.winsys; +	const uint32_t le = 1; +	uint32_t *map; +	int i; + +	map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); + +#if 0 +	for (i = 0; i < fp->insn_len; i++) { +		fflush(stdout); fflush(stderr); +		NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]); +		fflush(stdout); fflush(stderr); +	} +#endif + +	if ((*(const uint8_t *)&le)) { +		for (i = 0; i < fp->insn_len; i++) { +			map[i] = fp->insn[i]; +		} +	} else { +		/* Weird swapping for big-endian chips */ +		for (i = 0; i < fp->insn_len; i++) { +			map[i] = ((fp->insn[i] & 0xffff) << 16) | +				  ((fp->insn[i] >> 16) & 0xffff); +		} +	} + +	ws->buffer_unmap(ws, fp->buffer); +} + +static boolean +nv40_fragprog_validate(struct nv40_context *nv40) +{ +	struct nv40_fragment_program *fp = nv40->fragprog; +	struct pipe_buffer *constbuf = +		nv40->constbuf[PIPE_SHADER_FRAGMENT]; +	struct pipe_winsys *ws = nv40->pipe.winsys; +	struct nouveau_stateobj *so; +	boolean new_consts = FALSE; +	int i; + +	if (fp->translated) +		goto update_constants; + +	nv40->fallback_swrast &= ~NV40_NEW_FRAGPROG; +	nv40_fragprog_translate(nv40, fp); +	if (!fp->translated) { +		nv40->fallback_swrast |= NV40_NEW_FRAGPROG; +		return FALSE; +	} + +	fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4); +	nv40_fragprog_upload(nv40, fp); + +	so = so_new(4, 1); +	so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1); +	so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | +		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, +		  NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1); +	so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1); +	so_data  (so, fp->fp_control); +	so_ref(so, &fp->so); + +update_constants: +	if (fp->nr_consts) { +		float *map; +		 +		map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ); +		for (i = 0; i < fp->nr_consts; i++) { +			struct nv40_fragment_program_data *fpd = &fp->consts[i]; +			uint32_t *p = &fp->insn[fpd->offset]; +			uint32_t *cb = (uint32_t *)&map[fpd->index * 4]; + +			if (!memcmp(p, cb, 4 * sizeof(float))) +				continue; +			memcpy(p, cb, 4 * sizeof(float)); +			new_consts = TRUE; +		} +		ws->buffer_unmap(ws, constbuf); + +		if (new_consts) +			nv40_fragprog_upload(nv40, fp); +	} + +	if (new_consts || fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) { +		so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]); +		return TRUE; +	} + +	return FALSE; +} + +void +nv40_fragprog_destroy(struct nv40_context *nv40, +		      struct nv40_fragment_program *fp) +{ +	if (fp->insn_len) +		FREE(fp->insn); +} + +struct nv40_state_entry nv40_state_fragprog = { +	.validate = nv40_fragprog_validate, +	.dirty = { +		.pipe = NV40_NEW_FRAGPROG, +		.hw = NV40_STATE_FRAGPROG +	} +}; + diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nv40/nv40_fragtex.c new file mode 100644 index 0000000000..2d45c2545c --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_fragtex.c @@ -0,0 +1,171 @@ +#include "nv40_context.h" + +#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw)            \ +{                                                                              \ +  TRUE,                                                                        \ +  PIPE_FORMAT_##m,                                                             \ +  NV40TCL_TEX_FORMAT_FORMAT_##tf,                                              \ +  (NV40TCL_TEX_SWIZZLE_S0_X_##ts0x | NV40TCL_TEX_SWIZZLE_S0_Y_##ts0y |         \ +   NV40TCL_TEX_SWIZZLE_S0_Z_##ts0z | NV40TCL_TEX_SWIZZLE_S0_W_##ts0w |         \ +   NV40TCL_TEX_SWIZZLE_S1_X_##ts1x | NV40TCL_TEX_SWIZZLE_S1_Y_##ts1y |         \ +   NV40TCL_TEX_SWIZZLE_S1_Z_##ts1z | NV40TCL_TEX_SWIZZLE_S1_W_##ts1w),         \ +  ((NV40TCL_TEX_FILTER_SIGNED_RED*sx) | (NV40TCL_TEX_FILTER_SIGNED_GREEN*sy) |       \ +   (NV40TCL_TEX_FILTER_SIGNED_BLUE*sz) | (NV40TCL_TEX_FILTER_SIGNED_ALPHA*sw))       \ +} + +struct nv40_texture_format { +	boolean defined; +	uint	pipe; +	int     format; +	int     swizzle; +	int     sign; +}; + +static struct nv40_texture_format +nv40_texture_formats[] = { +	_(A8R8G8B8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0), +	_(A1R5G5B5_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0), +	_(A4R4G4B4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0), +	_(R5G6B5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0), +	_(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0), +	_(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X, 0, 0, 0, 0), +	_(R16_SNORM     , A16     , ZERO, ZERO,   S1,  ONE, X, X, X, Y, 1, 1, 1, 1), +	_(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X, 0, 0, 0, 0), +	_(A8L8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y, 0, 0, 0, 0), +	_(Z16_UNORM     , Z16     ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0), +	_(Z24S8_UNORM   , Z24     ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0), +	_(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0), +	_(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0), +	_(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0), +	_(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0), +	{}, +}; + +static struct nv40_texture_format * +nv40_fragtex_format(uint pipe_format) +{ +	struct nv40_texture_format *tf = nv40_texture_formats; +	char fs[128]; + +	while (tf->defined) { +		if (tf->pipe == pipe_format) +			return tf; +		tf++; +	} + +	pf_sprint_name(fs, pipe_format); +	NOUVEAU_ERR("unknown texture format %s\n", fs); +	return NULL; +} + + +static struct nouveau_stateobj * +nv40_fragtex_build(struct nv40_context *nv40, int unit) +{ +	struct nv40_sampler_state *ps = nv40->tex_sampler[unit]; +	struct nv40_miptree *nv40mt = nv40->tex_miptree[unit]; +	struct pipe_texture *pt = &nv40mt->base; +	struct nv40_texture_format *tf; +	struct nouveau_stateobj *so; +	uint32_t txf, txs, txp; +	int swizzled = 0; /*XXX: implement in region code? */ +	unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + +	tf = nv40_fragtex_format(pt->format); +	if (!tf) +		assert(0); + +	txf  = ps->fmt; +	txf |= tf->format | 0x8000; +	txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT); + +	if (1) /* XXX */ +		txf |= NV40TCL_TEX_FORMAT_NO_BORDER; + +	switch (pt->target) { +	case PIPE_TEXTURE_CUBE: +		txf |= NV40TCL_TEX_FORMAT_CUBIC; +		/* fall-through */ +	case PIPE_TEXTURE_2D: +		txf |= NV40TCL_TEX_FORMAT_DIMS_2D; +		break; +	case PIPE_TEXTURE_3D: +		txf |= NV40TCL_TEX_FORMAT_DIMS_3D; +		break; +	case PIPE_TEXTURE_1D: +		txf |= NV40TCL_TEX_FORMAT_DIMS_1D; +		break; +	default: +		NOUVEAU_ERR("Unknown target %d\n", pt->target); +		return NULL; +	} + +	if (swizzled) { +		txp = 0; +	} else { +		txp  = nv40mt->level[0].pitch; +		txf |= NV40TCL_TEX_FORMAT_LINEAR; +	} + +	txs = tf->swizzle; + +	so = so_new(16, 2); +	so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8); +	so_reloc (so, nv40mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); +	so_reloc (so, nv40mt->buffer, txf, tex_flags | NOUVEAU_BO_OR, +		  NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1); +	so_data  (so, ps->wrap); +	so_data  (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en); +	so_data  (so, txs); +	so_data  (so, ps->filt | tf->sign | 0x2000 /*voodoo*/); +	so_data  (so, (pt->width[0] << NV40TCL_TEX_SIZE0_W_SHIFT) | +		       pt->height[0]); +	so_data  (so, ps->bcol); +	so_method(so, nv40->screen->curie, NV40TCL_TEX_SIZE1(unit), 1); +	so_data  (so, (pt->depth[0] << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp); + +	return so; +} + +static boolean +nv40_fragtex_validate(struct nv40_context *nv40) +{ +	struct nv40_fragment_program *fp = nv40->fragprog; +	struct nv40_state *state = &nv40->state; +	struct nouveau_stateobj *so; +	unsigned samplers, unit; + +	samplers = state->fp_samplers & ~fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		so = so_new(2, 0); +		so_method(so, nv40->screen->curie, NV40TCL_TEX_ENABLE(unit), 1); +		so_data  (so, 0); +		so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]); +		state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit)); +	} + +	samplers = nv40->dirty_samplers & fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		so = nv40_fragtex_build(nv40, unit); +		so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]); +		state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit)); +	} + +	nv40->state.fp_samplers = fp->samplers; +	return FALSE; +} + +struct nv40_state_entry nv40_state_fragtex = { +	.validate = nv40_fragtex_validate, +	.dirty = { +		.pipe = NV40_NEW_SAMPLER | NV40_NEW_FRAGPROG, +		.hw = 0 +	} +}; + diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c new file mode 100644 index 0000000000..38e1a5f04c --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_miptree.c @@ -0,0 +1,163 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "nv40_context.h" + +static void +nv40_miptree_layout(struct nv40_miptree *nv40mt) +{ +	struct pipe_texture *pt = &nv40mt->base; +	boolean swizzled = FALSE; +	uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0]; +	uint offset = 0; +	int nr_faces, l, f, pitch; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		nr_faces = 6; +	} else +	if (pt->target == PIPE_TEXTURE_3D) { +		nr_faces = pt->depth[0]; +	} else { +		nr_faces = 1; +	} + +	pitch = pt->width[0]; +	for (l = 0; l <= pt->last_level; l++) { +		pt->width[l] = width; +		pt->height[l] = height; +		pt->depth[l] = depth; +		pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); +		pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); + +		if (swizzled) +			pitch = pt->nblocksx[l]; +		pitch = align_int(pitch, 64); + +		nv40mt->level[l].pitch = pitch * pt->block.size; +		nv40mt->level[l].image_offset = +			CALLOC(nr_faces, sizeof(unsigned)); + +		width  = MAX2(1, width  >> 1); +		height = MAX2(1, height >> 1); +		depth  = MAX2(1, depth  >> 1); +	} + +	for (f = 0; f < nr_faces; f++) { +		for (l = 0; l <= pt->last_level; l++) { +			nv40mt->level[l].image_offset[f] = offset; +			offset += nv40mt->level[l].pitch * pt->height[l]; +		} +	} + +	nv40mt->total_size = offset; +} + +static struct pipe_texture * +nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv40_miptree *mt; + +	mt = MALLOC(sizeof(struct nv40_miptree)); +	if (!mt) +		return NULL; +	mt->base = *pt; +	mt->base.refcount = 1; +	mt->base.screen = pscreen; + +	nv40_miptree_layout(mt); + +	mt->buffer = ws->buffer_create(ws, 256, +				       PIPE_BUFFER_USAGE_PIXEL | +				       NOUVEAU_BUFFER_USAGE_TEXTURE, +				       mt->total_size); +	if (!mt->buffer) { +		FREE(mt); +		return NULL; +	} + +	return &mt->base; +} + +static void +nv40_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **pt) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct pipe_texture *mt = *pt; + +	*pt = NULL; +	if (--mt->refcount <= 0) { +		struct nv40_miptree *nv40mt = (struct nv40_miptree *)mt; +		int l; + +		pipe_buffer_reference(ws, &nv40mt->buffer, NULL); +		for (l = 0; l <= mt->last_level; l++) { +			if (nv40mt->level[l].image_offset) +				FREE(nv40mt->level[l].image_offset); +		} +		FREE(nv40mt); +	} +} + +static struct pipe_surface * +nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +			 unsigned face, unsigned level, unsigned zslice, +			 unsigned flags) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv40_miptree *nv40mt = (struct nv40_miptree *)pt; +	struct pipe_surface *ps; + +	ps = CALLOC_STRUCT(pipe_surface); +	if (!ps) +		return NULL; +	pipe_texture_reference(&ps->texture, pt); +	pipe_buffer_reference(ws, &ps->buffer, nv40mt->buffer); +	ps->format = pt->format; +	ps->width = pt->width[level]; +	ps->height = pt->height[level]; +	ps->block = pt->block; +	ps->nblocksx = pt->nblocksx[level]; +	ps->nblocksy = pt->nblocksy[level]; +	ps->stride = nv40mt->level[level].pitch; +	ps->usage = flags; +	ps->status = PIPE_SURFACE_STATUS_DEFINED; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		ps->offset = nv40mt->level[level].image_offset[face]; +	} else +	if (pt->target == PIPE_TEXTURE_3D) { +		ps->offset = nv40mt->level[level].image_offset[zslice]; +	} else { +		ps->offset = nv40mt->level[level].image_offset[0]; +	} + +	return ps; +} + +static void +nv40_miptree_surface_del(struct pipe_screen *pscreen, +			 struct pipe_surface **psurface) +{ +	struct pipe_surface *ps = *psurface; + +	*psurface = NULL; +	if (--ps->refcount > 0) +		return; + +	pipe_texture_reference(&ps->texture, NULL); +	pipe_buffer_reference(pscreen->winsys, &ps->buffer, NULL); +	FREE(ps); +} + +void +nv40_screen_init_miptree_functions(struct pipe_screen *pscreen) +{ +	pscreen->texture_create = nv40_miptree_create; +	pscreen->texture_release = nv40_miptree_release; +	pscreen->get_tex_surface = nv40_miptree_surface_new; +	pscreen->tex_surface_release = nv40_miptree_surface_del; +} + diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c new file mode 100644 index 0000000000..57f39cfab0 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_query.c @@ -0,0 +1,122 @@ +#include "pipe/p_context.h" + +#include "nv40_context.h" + +struct nv40_query { +	struct nouveau_resource *object; +	unsigned type; +	boolean ready; +	uint64_t result; +}; + +static INLINE struct nv40_query * +nv40_query(struct pipe_query *pipe) +{ +	return (struct nv40_query *)pipe; +} + +static struct pipe_query * +nv40_query_create(struct pipe_context *pipe, unsigned query_type) +{ +	struct nv40_query *q; + +	q = CALLOC(1, sizeof(struct nv40_query)); +	q->type = query_type; + +	return (struct pipe_query *)q; +} + +static void +nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_query *q = nv40_query(pq); + +	if (q->object) +		nv40->nvws->res_free(&q->object); +	FREE(q); +} + +static void +nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_query *q = nv40_query(pq); + +	assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); + +	/* Happens when end_query() is called, then another begin_query() +	 * without querying the result in-between.  For now we'll wait for +	 * the existing query to notify completion, but it could be better. +	 */ +	if (q->object) { +		uint64 tmp; +		pipe->get_query_result(pipe, pq, 1, &tmp); +	} + +	if (nv40->nvws->res_alloc(nv40->screen->query_heap, 1, NULL, &q->object)) +		assert(0); +	nv40->nvws->notifier_reset(nv40->screen->query, q->object->start); + +	BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1); +	OUT_RING  (1); +	BEGIN_RING(curie, NV40TCL_QUERY_UNK17CC, 1); +	OUT_RING  (1); + +	q->ready = FALSE; +} + +static void +nv40_query_end(struct pipe_context *pipe, struct pipe_query *pq) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_query *q = nv40_query(pq); + +	BEGIN_RING(curie, NV40TCL_QUERY_GET, 1); +	OUT_RING  ((0x01 << NV40TCL_QUERY_GET_UNK24_SHIFT) | +		   ((q->object->start * 32) << NV40TCL_QUERY_GET_OFFSET_SHIFT)); +	FIRE_RING(NULL); +} + +static boolean +nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq, +		  boolean wait, uint64 *result) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_query *q = nv40_query(pq); +	struct nouveau_winsys *nvws = nv40->nvws; + +	assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); + +	if (!q->ready) { +		unsigned status; + +		status = nvws->notifier_status(nv40->screen->query, +					       q->object->start); +		if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { +			if (wait == FALSE) +				return FALSE; +			nvws->notifier_wait(nv40->screen->query, q->object->start, +					    NV_NOTIFY_STATE_STATUS_COMPLETED, +					    0); +		} + +		q->result = nvws->notifier_retval(nv40->screen->query, +						  q->object->start); +		q->ready = TRUE; +		nvws->res_free(&q->object); +	} + +	*result = q->result; +	return TRUE; +} + +void +nv40_init_query_functions(struct nv40_context *nv40) +{ +	nv40->pipe.create_query = nv40_query_create; +	nv40->pipe.destroy_query = nv40_query_destroy; +	nv40->pipe.begin_query = nv40_query_begin; +	nv40->pipe.end_query = nv40_query_end; +	nv40->pipe.get_query_result = nv40_query_result; +} diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c new file mode 100644 index 0000000000..0e1df89ee8 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -0,0 +1,315 @@ +#include "pipe/p_screen.h" +#include "pipe/p_util.h" + +#include "nv40_context.h" +#include "nv40_screen.h" + +#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf +#define NV4X_GRCLASS4497_CHIPSETS 0x00005450 +#define NV6X_GRCLASS4497_CHIPSETS 0x00000088 + +static const char * +nv40_screen_get_name(struct pipe_screen *pscreen) +{ +	struct nv40_screen *screen = nv40_screen(pscreen); +	struct nouveau_device *dev = screen->nvws->channel->device; +	static char buffer[128]; + +	snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); +	return buffer; +} + +static const char * +nv40_screen_get_vendor(struct pipe_screen *pscreen) +{ +	return "nouveau"; +} + +static int +nv40_screen_get_param(struct pipe_screen *pscreen, int param) +{ +	struct nv40_screen *screen = nv40_screen(pscreen); + +	switch (param) { +	case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: +		return 16; +	case PIPE_CAP_NPOT_TEXTURES: +		return 1; +	case PIPE_CAP_TWO_SIDED_STENCIL: +		return 1; +	case PIPE_CAP_GLSL: +		return 0; +	case PIPE_CAP_S3TC: +		return 1; +	case PIPE_CAP_ANISOTROPIC_FILTER: +		return 1; +	case PIPE_CAP_POINT_SPRITE: +		return 1; +	case PIPE_CAP_MAX_RENDER_TARGETS: +		return 4; +	case PIPE_CAP_OCCLUSION_QUERY: +		return 1; +	case PIPE_CAP_TEXTURE_SHADOW_MAP: +		return 1; +	case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: +		return 13; +	case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: +		return 10; +	case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: +		return 13; +	case PIPE_CAP_TEXTURE_MIRROR_CLAMP: +	case PIPE_CAP_TEXTURE_MIRROR_REPEAT: +		return 1; +	case NOUVEAU_CAP_HW_VTXBUF: +		return 1; +	case NOUVEAU_CAP_HW_IDXBUF: +		if (screen->curie->grclass == NV40TCL) +			return 1; +		return 0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0; +	} +} + +static float +nv40_screen_get_paramf(struct pipe_screen *pscreen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_LINE_WIDTH: +	case PIPE_CAP_MAX_LINE_WIDTH_AA: +		return 10.0; +	case PIPE_CAP_MAX_POINT_WIDTH: +	case PIPE_CAP_MAX_POINT_WIDTH_AA: +		return 64.0; +	case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: +		return 16.0; +	case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: +		return 16.0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0.0; +	} +} + +static boolean +nv40_screen_surface_format_supported(struct pipe_screen *pscreen, +				     enum pipe_format format, +				     enum pipe_texture_target target, +				     unsigned tex_usage, unsigned geom_flags) +{ +	if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM:  +		case PIPE_FORMAT_Z24S8_UNORM: +		case PIPE_FORMAT_Z16_UNORM: +			return TRUE; +		default: +			break; +		} +	} else { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_A1R5G5B5_UNORM: +		case PIPE_FORMAT_A4R4G4B4_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM: +		case PIPE_FORMAT_R16_SNORM: +		case PIPE_FORMAT_L8_UNORM: +		case PIPE_FORMAT_A8_UNORM: +		case PIPE_FORMAT_I8_UNORM: +		case PIPE_FORMAT_A8L8_UNORM: +		case PIPE_FORMAT_Z16_UNORM: +		case PIPE_FORMAT_Z24S8_UNORM: +		case PIPE_FORMAT_DXT1_RGB: +		case PIPE_FORMAT_DXT1_RGBA: +		case PIPE_FORMAT_DXT3_RGBA: +		case PIPE_FORMAT_DXT5_RGBA: +			return TRUE; +		default: +			break; +		} +	} + +	return FALSE; +} + +static void * +nv40_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, +		 unsigned flags ) +{ +	struct pipe_winsys *ws = screen->winsys; +	void *map; + +	map = ws->buffer_map(ws, surface->buffer, flags); +	if (!map) +		return NULL; + +	return map + surface->offset; +} + +static void +nv40_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) +{ +	struct pipe_winsys *ws = screen->winsys; + +	ws->buffer_unmap(ws, surface->buffer); +} + +static void +nv40_screen_destroy(struct pipe_screen *pscreen) +{ +	struct nv40_screen *screen = nv40_screen(pscreen); +	struct nouveau_winsys *nvws = screen->nvws; + +	nvws->res_free(&screen->vp_exec_heap); +	nvws->res_free(&screen->vp_data_heap); +	nvws->res_free(&screen->query_heap); +	nvws->notifier_free(&screen->query); +	nvws->notifier_free(&screen->sync); +	nvws->grobj_free(&screen->curie); + +	FREE(pscreen); +} + +struct pipe_screen * +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +{ +	struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); +	struct nouveau_stateobj *so; +	unsigned curie_class; +	unsigned chipset = nvws->channel->device->chipset; +	int ret; + +	if (!screen) +		return NULL; +	screen->nvws = nvws; + +	/* 3D object */ +	switch (chipset & 0xf0) { +	case 0x40: +		if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f))) +			curie_class = NV40TCL; +		else +		if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) +			curie_class = NV44TCL; +		break; +	case 0x60: +		if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) +			curie_class = NV44TCL; +		break; +	default: +		break; +	} + +	if (!curie_class) { +		NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset); +		return NULL; +	} + +	ret = nvws->grobj_alloc(nvws, curie_class, &screen->curie); +	if (ret) { +		NOUVEAU_ERR("Error creating 3D object: %d\n", ret); +		return FALSE; +	} + +	/* Notifier for sync purposes */ +	ret = nvws->notifier_alloc(nvws, 1, &screen->sync); +	if (ret) { +		NOUVEAU_ERR("Error creating notifier object: %d\n", ret); +		nv40_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Query objects */ +	ret = nvws->notifier_alloc(nvws, 32, &screen->query); +	if (ret) { +		NOUVEAU_ERR("Error initialising query objects: %d\n", ret); +		nv40_screen_destroy(&screen->pipe); +		return NULL; +	} + +	ret = nvws->res_init(&screen->query_heap, 0, 32); +	if (ret) { +		NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); +		nv40_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Vtxprog resources */ +	if (nvws->res_init(&screen->vp_exec_heap, 0, 512) || +	    nvws->res_init(&screen->vp_data_heap, 0, 256)) { +		nv40_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Static curie initialisation */ +	so = so_new(128, 0); +	so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1); +	so_data  (so, screen->sync->handle); +	so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->gart->handle); +	so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1); +	so_data  (so, nvws->channel->vram->handle); +	so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->vram->handle); +	so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->gart->handle); +	so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2); +	so_data  (so, 0); +	so_data  (so, screen->query->handle); +	so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->vram->handle); +	so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2); +	so_data  (so, nvws->channel->vram->handle); +	so_data  (so, nvws->channel->vram->handle); + +	so_method(so, screen->curie, 0x1ea4, 3); +	so_data  (so, 0x00000010); +	so_data  (so, 0x01000100); +	so_data  (so, 0xff800006); + +	/* vtxprog output routing */ +	so_method(so, screen->curie, 0x1fc4, 1); +	so_data  (so, 0x06144321); +	so_method(so, screen->curie, 0x1fc8, 2); +	so_data  (so, 0xedcba987); +	so_data  (so, 0x00000021); +	so_method(so, screen->curie, 0x1fd0, 1); +	so_data  (so, 0x00171615); +	so_method(so, screen->curie, 0x1fd4, 1); +	so_data  (so, 0x001b1a19); + +	so_method(so, screen->curie, 0x1ef8, 1); +	so_data  (so, 0x0020ffff); +	so_method(so, screen->curie, 0x1d64, 1); +	so_data  (so, 0x00d30000); +	so_method(so, screen->curie, 0x1e94, 1); +	so_data  (so, 0x00000001); + +	so_emit(nvws, so); +	so_ref(NULL, &so); +	nvws->push_flush(nvws, 0, NULL); + +	screen->pipe.winsys = ws; +	screen->pipe.destroy = nv40_screen_destroy; + +	screen->pipe.get_name = nv40_screen_get_name; +	screen->pipe.get_vendor = nv40_screen_get_vendor; +	screen->pipe.get_param = nv40_screen_get_param; +	screen->pipe.get_paramf = nv40_screen_get_paramf; + +	screen->pipe.is_format_supported = nv40_screen_surface_format_supported; + +	screen->pipe.surface_map = nv40_surface_map; +	screen->pipe.surface_unmap = nv40_surface_unmap; + +	nv40_screen_init_miptree_functions(&screen->pipe); + +	return &screen->pipe; +} + diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h new file mode 100644 index 0000000000..c04a1275a0 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -0,0 +1,35 @@ +#ifndef __NV40_SCREEN_H__ +#define __NV40_SCREEN_H__ + +#include "pipe/p_screen.h" + +struct nv40_screen { +	struct pipe_screen pipe; + +	struct nouveau_winsys *nvws; + +	unsigned cur_pctx; + +	/* HW graphics objects */ +	struct nouveau_grobj *curie; +	struct nouveau_notifier *sync; + +	/* Query object resources */ +	struct nouveau_notifier *query; +	struct nouveau_resource *query_heap; + +	/* Vtxprog resources */ +	struct nouveau_resource *vp_exec_heap; +	struct nouveau_resource *vp_data_heap; + +	/* Current 3D state of channel */ +	struct nouveau_stateobj *state[NV40_STATE_MAX]; +}; + +static INLINE struct nv40_screen * +nv40_screen(struct pipe_screen *screen) +{ +	return (struct nv40_screen *)screen; +} + +#endif diff --git a/src/gallium/drivers/nv40/nv40_shader.h b/src/gallium/drivers/nv40/nv40_shader.h new file mode 100644 index 0000000000..854dccf548 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_shader.h @@ -0,0 +1,556 @@ +#ifndef __NV40_SHADER_H__ +#define __NV40_SHADER_H__ + +/* Vertex programs instruction set + * + * The NV40 instruction set is very similar to NV30.  Most fields are in + * a slightly different position in the instruction however. + * + * Merged instructions + *     In some cases it is possible to put two instructions into one opcode + *     slot.  The rules for when this is OK is not entirely clear to me yet. + * + *     There are separate writemasks and dest temp register fields for each + *     grouping of instructions.  There is however only one field with the + *     ID of a result register.  Writing to temp/result regs is selected by + *     setting VEC_RESULT/SCA_RESULT. + * + * Temporary registers + *     The source/dest temp register fields have been extended by 1 bit, to + *     give a total of 32 temporary registers. + * + * Relative Addressing + *     NV40 can use an address register to index into vertex attribute regs. + *     This is done by putting the offset value into INPUT_SRC and setting + *     the INDEX_INPUT flag. + * + * Conditional execution (see NV_vertex_program{2,3} for details) + *     There is a second condition code register on NV40, it's use is enabled + *     by setting the COND_REG_SELECT_1 flag. + * + * Texture lookup + *     TODO + */ + +/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */ +#define NV40_VP_INST_VEC_RESULT                                        (1 << 30) +/* uncertain.. */ +#define NV40_VP_INST_COND_UPDATE_ENABLE                        ((1 << 14)|1<<29) +/* use address reg as index into attribs */ +#define NV40_VP_INST_INDEX_INPUT                                       (1 << 27) +#define NV40_VP_INST_COND_REG_SELECT_1                                 (1 << 25) +#define NV40_VP_INST_ADDR_REG_SELECT_1                                 (1 << 24) +#define NV40_VP_INST_SRC2_ABS                                          (1 << 23) +#define NV40_VP_INST_SRC1_ABS                                          (1 << 22) +#define NV40_VP_INST_SRC0_ABS                                          (1 << 21) +#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT                                      15 +#define NV40_VP_INST_VEC_DEST_TEMP_MASK                             (0x1F << 15) +#define NV40_VP_INST_COND_TEST_ENABLE                                  (1 << 13) +#define NV40_VP_INST_COND_SHIFT                                               10 +#define NV40_VP_INST_COND_MASK                                       (0x7 << 10) +#    define NV40_VP_INST_COND_FL                                               0 +#    define NV40_VP_INST_COND_LT                                               1 +#    define NV40_VP_INST_COND_EQ                                               2 +#    define NV40_VP_INST_COND_LE                                               3 +#    define NV40_VP_INST_COND_GT                                               4 +#    define NV40_VP_INST_COND_NE                                               5 +#    define NV40_VP_INST_COND_GE                                               6 +#    define NV40_VP_INST_COND_TR                                               7 +#define NV40_VP_INST_COND_SWZ_X_SHIFT                                          8 +#define NV40_VP_INST_COND_SWZ_X_MASK                                    (3 << 8) +#define NV40_VP_INST_COND_SWZ_Y_SHIFT                                          6 +#define NV40_VP_INST_COND_SWZ_Y_MASK                                    (3 << 6) +#define NV40_VP_INST_COND_SWZ_Z_SHIFT                                          4 +#define NV40_VP_INST_COND_SWZ_Z_MASK                                    (3 << 4) +#define NV40_VP_INST_COND_SWZ_W_SHIFT                                          2 +#define NV40_VP_INST_COND_SWZ_W_MASK                                    (3 << 2) +#define NV40_VP_INST_COND_SWZ_ALL_SHIFT                                        2 +#define NV40_VP_INST_COND_SWZ_ALL_MASK                               (0xFF << 2) +#define NV40_VP_INST_ADDR_SWZ_SHIFT                                            0 +#define NV40_VP_INST_ADDR_SWZ_MASK                                   (0x03 << 0) +#define NV40_VP_INST0_KNOWN ( \ +                NV40_VP_INST_INDEX_INPUT | \ +                NV40_VP_INST_COND_REG_SELECT_1 | \ +                NV40_VP_INST_ADDR_REG_SELECT_1 | \ +                NV40_VP_INST_SRC2_ABS | \ +                NV40_VP_INST_SRC1_ABS | \ +                NV40_VP_INST_SRC0_ABS | \ +                NV40_VP_INST_VEC_DEST_TEMP_MASK | \ +                NV40_VP_INST_COND_TEST_ENABLE | \ +                NV40_VP_INST_COND_MASK | \ +                NV40_VP_INST_COND_SWZ_ALL_MASK | \ +                NV40_VP_INST_ADDR_SWZ_MASK) + +/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */ +#define NV40_VP_INST_VEC_OPCODE_SHIFT                                         22 +#define NV40_VP_INST_VEC_OPCODE_MASK                                (0x1F << 22) +#    define NV40_VP_INST_OP_NOP                                             0x00 +#    define NV40_VP_INST_OP_MOV                                             0x01 +#    define NV40_VP_INST_OP_MUL                                             0x02 +#    define NV40_VP_INST_OP_ADD                                             0x03 +#    define NV40_VP_INST_OP_MAD                                             0x04 +#    define NV40_VP_INST_OP_DP3                                             0x05 +#    define NV40_VP_INST_OP_DPH                                             0x06 +#    define NV40_VP_INST_OP_DP4                                             0x07 +#    define NV40_VP_INST_OP_DST                                             0x08 +#    define NV40_VP_INST_OP_MIN                                             0x09 +#    define NV40_VP_INST_OP_MAX                                             0x0A +#    define NV40_VP_INST_OP_SLT                                             0x0B +#    define NV40_VP_INST_OP_SGE                                             0x0C +#    define NV40_VP_INST_OP_ARL                                             0x0D +#    define NV40_VP_INST_OP_FRC                                             0x0E +#    define NV40_VP_INST_OP_FLR                                             0x0F +#    define NV40_VP_INST_OP_SEQ                                             0x10 +#    define NV40_VP_INST_OP_SFL                                             0x11 +#    define NV40_VP_INST_OP_SGT                                             0x12 +#    define NV40_VP_INST_OP_SLE                                             0x13 +#    define NV40_VP_INST_OP_SNE                                             0x14 +#    define NV40_VP_INST_OP_STR                                             0x15 +#    define NV40_VP_INST_OP_SSG                                             0x16 +#    define NV40_VP_INST_OP_ARR                                             0x17 +#    define NV40_VP_INST_OP_ARA                                             0x18 +#    define NV40_VP_INST_OP_TXL                                             0x19 +#define NV40_VP_INST_SCA_OPCODE_SHIFT                                         27 +#define NV40_VP_INST_SCA_OPCODE_MASK                                (0x1F << 27) +#    define NV40_VP_INST_OP_NOP                                             0x00 +#    define NV40_VP_INST_OP_MOV                                             0x01 +#    define NV40_VP_INST_OP_RCP                                             0x02 +#    define NV40_VP_INST_OP_RCC                                             0x03 +#    define NV40_VP_INST_OP_RSQ                                             0x04 +#    define NV40_VP_INST_OP_EXP                                             0x05 +#    define NV40_VP_INST_OP_LOG                                             0x06 +#    define NV40_VP_INST_OP_LIT                                             0x07 +#    define NV40_VP_INST_OP_BRA                                             0x09 +#    define NV40_VP_INST_OP_CAL                                             0x0B +#    define NV40_VP_INST_OP_RET                                             0x0C +#    define NV40_VP_INST_OP_LG2                                             0x0D +#    define NV40_VP_INST_OP_EX2                                             0x0E +#    define NV40_VP_INST_OP_SIN                                             0x0F +#    define NV40_VP_INST_OP_COS                                             0x10 +#    define NV40_VP_INST_OP_PUSHA                                           0x13 +#    define NV40_VP_INST_OP_POPA                                            0x14 +#define NV40_VP_INST_CONST_SRC_SHIFT                                          12 +#define NV40_VP_INST_CONST_SRC_MASK                                 (0xFF << 12) +#define NV40_VP_INST_INPUT_SRC_SHIFT                                           8 +#define NV40_VP_INST_INPUT_SRC_MASK                                  (0x0F << 8) +#    define NV40_VP_INST_IN_POS                                                0 +#    define NV40_VP_INST_IN_WEIGHT                                             1 +#    define NV40_VP_INST_IN_NORMAL                                             2 +#    define NV40_VP_INST_IN_COL0                                               3 +#    define NV40_VP_INST_IN_COL1                                               4 +#    define NV40_VP_INST_IN_FOGC                                               5 +#    define NV40_VP_INST_IN_TC0                                                8 +#    define NV40_VP_INST_IN_TC(n)                                          (8+n) +#define NV40_VP_INST_SRC0H_SHIFT                                               0 +#define NV40_VP_INST_SRC0H_MASK                                      (0xFF << 0) +#define NV40_VP_INST1_KNOWN ( \ +                NV40_VP_INST_VEC_OPCODE_MASK | \ +                NV40_VP_INST_SCA_OPCODE_MASK | \ +                NV40_VP_INST_CONST_SRC_MASK  | \ +                NV40_VP_INST_INPUT_SRC_MASK  | \ +                NV40_VP_INST_SRC0H_MASK \ +                ) + +/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */ +#define NV40_VP_INST_SRC0L_SHIFT                                              23 +#define NV40_VP_INST_SRC0L_MASK                                    (0x1FF << 23) +#define NV40_VP_INST_SRC1_SHIFT                                                6 +#define NV40_VP_INST_SRC1_MASK                                    (0x1FFFF << 6) +#define NV40_VP_INST_SRC2H_SHIFT                                               0 +#define NV40_VP_INST_SRC2H_MASK                                      (0x3F << 0) +#define NV40_VP_INST_IADDRH_SHIFT                                              0 +#define NV40_VP_INST_IADDRH_MASK                                     (0x1F << 0) + +/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */ +#define NV40_VP_INST_IADDRL_SHIFT                                             29 +#define NV40_VP_INST_IADDRL_MASK                                       (7 << 29) +#define NV40_VP_INST_SRC2L_SHIFT                                              21 +#define NV40_VP_INST_SRC2L_MASK                                    (0x7FF << 21) +#define NV40_VP_INST_SCA_WRITEMASK_SHIFT                                      17 +#define NV40_VP_INST_SCA_WRITEMASK_MASK                              (0xF << 17) +#    define NV40_VP_INST_SCA_WRITEMASK_X                               (1 << 20) +#    define NV40_VP_INST_SCA_WRITEMASK_Y                               (1 << 19) +#    define NV40_VP_INST_SCA_WRITEMASK_Z                               (1 << 18) +#    define NV40_VP_INST_SCA_WRITEMASK_W                               (1 << 17) +#define NV40_VP_INST_VEC_WRITEMASK_SHIFT                                      13 +#define NV40_VP_INST_VEC_WRITEMASK_MASK                              (0xF << 13) +#    define NV40_VP_INST_VEC_WRITEMASK_X                               (1 << 16) +#    define NV40_VP_INST_VEC_WRITEMASK_Y                               (1 << 15) +#    define NV40_VP_INST_VEC_WRITEMASK_Z                               (1 << 14) +#    define NV40_VP_INST_VEC_WRITEMASK_W                               (1 << 13) +#define NV40_VP_INST_SCA_RESULT                                        (1 << 12) +#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT                                       7 +#define NV40_VP_INST_SCA_DEST_TEMP_MASK                              (0x1F << 7) +#define NV40_VP_INST_DEST_SHIFT                                                2 +#define NV40_VP_INST_DEST_MASK                                         (31 << 2) +#    define NV40_VP_INST_DEST_POS                                              0 +#    define NV40_VP_INST_DEST_COL0                                             1 +#    define NV40_VP_INST_DEST_COL1                                             2 +#    define NV40_VP_INST_DEST_BFC0                                             3 +#    define NV40_VP_INST_DEST_BFC1                                             4 +#    define NV40_VP_INST_DEST_FOGC                                             5 +#    define NV40_VP_INST_DEST_PSZ                                              6 +#    define NV40_VP_INST_DEST_TC0                                              7 +#    define NV40_VP_INST_DEST_TC(n)                                        (7+n) +#    define NV40_VP_INST_DEST_TEMP                                          0x1F +#define NV40_VP_INST_INDEX_CONST                                        (1 << 1) +#define NV40_VP_INST_LAST                                               (1 << 0) +#define NV40_VP_INST3_KNOWN ( \ +                NV40_VP_INST_SRC2L_MASK |\ +                NV40_VP_INST_SCA_WRITEMASK_MASK |\ +                NV40_VP_INST_VEC_WRITEMASK_MASK |\ +                NV40_VP_INST_SCA_DEST_TEMP_MASK |\ +                NV40_VP_INST_DEST_MASK |\ +                NV40_VP_INST_INDEX_CONST) + +/* Useful to split the source selection regs into their pieces */ +#define NV40_VP_SRC0_HIGH_SHIFT                                                9 +#define NV40_VP_SRC0_HIGH_MASK                                        0x0001FE00 +#define NV40_VP_SRC0_LOW_MASK                                         0x000001FF +#define NV40_VP_SRC2_HIGH_SHIFT                                               11 +#define NV40_VP_SRC2_HIGH_MASK                                        0x0001F800 +#define NV40_VP_SRC2_LOW_MASK                                         0x000007FF + +/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */ +#define NV40_VP_SRC_NEGATE                                             (1 << 16) +#define NV40_VP_SRC_SWZ_X_SHIFT                                               14 +#define NV40_VP_SRC_SWZ_X_MASK                                         (3 << 14) +#define NV40_VP_SRC_SWZ_Y_SHIFT                                               12 +#define NV40_VP_SRC_SWZ_Y_MASK                                         (3 << 12) +#define NV40_VP_SRC_SWZ_Z_SHIFT                                               10 +#define NV40_VP_SRC_SWZ_Z_MASK                                         (3 << 10) +#define NV40_VP_SRC_SWZ_W_SHIFT                                                8 +#define NV40_VP_SRC_SWZ_W_MASK                                          (3 << 8) +#define NV40_VP_SRC_SWZ_ALL_SHIFT                                              8 +#define NV40_VP_SRC_SWZ_ALL_MASK                                     (0xFF << 8) +#define NV40_VP_SRC_TEMP_SRC_SHIFT                                             2 +#define NV40_VP_SRC_TEMP_SRC_MASK                                    (0x1F << 2) +#define NV40_VP_SRC_REG_TYPE_SHIFT                                             0 +#define NV40_VP_SRC_REG_TYPE_MASK                                       (3 << 0) +#    define NV40_VP_SRC_REG_TYPE_UNK0                                          0 +#    define NV40_VP_SRC_REG_TYPE_TEMP                                          1 +#    define NV40_VP_SRC_REG_TYPE_INPUT                                         2 +#    define NV40_VP_SRC_REG_TYPE_CONST                                         3 + + +/* + * Each fragment program opcode appears to be comprised of 4 32-bit values. + * + *         0 - Opcode, output reg/mask, ATTRIB source + *         1 - Source 0 + *         2 - Source 1 + *         3 - Source 2 + * + * There appears to be no special difference between result regs and temp regs. + *                 result.color == R0.xyzw + *                 result.depth == R1.z + * When the fragprog contains instructions to write depth, + * NV30_TCL_PRIMITIVE_3D_UNK1D78=0 otherwise it is set to 1. + * + * Constants are inserted directly after the instruction that uses them. + *  + * It appears that it's not possible to use two input registers in one + * instruction as the input sourcing is done in the instruction dword + * and not the source selection dwords.  As such instructions such as: + *  + *                 ADD result.color, fragment.color, fragment.texcoord[0]; + * + * must be split into two MOV's and then an ADD (nvidia does this) but + * I'm not sure why it's not just one MOV and then source the second input + * in the ADD instruction.. + * + * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary + * negation requires multiplication with a const. + * + * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO and + * SWIZZLE_ONE. + * + * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as + * SWIZZLE_ZERO is implemented simply by not writing to the relevant components + * of the destination. + * + * Looping + *   Loops appear to be fairly expensive on NV40 at least, the proprietary + *   driver goes to a lot of effort to avoid using the native looping + *   instructions.  If the total number of *executed* instructions between + *   REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop. + *   The maximum loop count is 255. + * + * Conditional execution + *   TODO + *  + * Non-native instructions: + *         LIT + *         LRP - MAD+MAD + *         SUB - ADD, negate second source + *         RSQ - LG2 + EX2 + *         POW - LG2 + MUL + EX2 + *         SCS - COS + SIN + *         XPD + *         DP2 - MUL + ADD + *         NRM + */ + +//== Opcode / Destination selection == +#define NV40_FP_OP_PROGRAM_END                                          (1 << 0) +#define NV40_FP_OP_OUT_REG_SHIFT                                               1 +#define NV40_FP_OP_OUT_REG_MASK                                        (63 << 1) +/* Needs to be set when writing outputs to get expected result.. */ +#define NV40_FP_OP_OUT_REG_HALF                                         (1 << 7) +#define NV40_FP_OP_COND_WRITE_ENABLE                                    (1 << 8) +#define NV40_FP_OP_OUTMASK_SHIFT                                               9 +#define NV40_FP_OP_OUTMASK_MASK                                       (0xF << 9) +#    define NV40_FP_OP_OUT_X                                            (1 << 9) +#    define NV40_FP_OP_OUT_Y                                            (1 <<10) +#    define NV40_FP_OP_OUT_Z                                            (1 <<11) +#    define NV40_FP_OP_OUT_W                                            (1 <<12) +/* Uncertain about these, especially the input_src values.. it's possible that + * they can be dynamically changed. + */ +#define NV40_FP_OP_INPUT_SRC_SHIFT                                            13 +#define NV40_FP_OP_INPUT_SRC_MASK                                     (15 << 13) +#    define NV40_FP_OP_INPUT_SRC_POSITION                                    0x0 +#    define NV40_FP_OP_INPUT_SRC_COL0                                        0x1 +#    define NV40_FP_OP_INPUT_SRC_COL1                                        0x2 +#    define NV40_FP_OP_INPUT_SRC_FOGC                                        0x3 +#    define NV40_FP_OP_INPUT_SRC_TC0                                         0x4 +#    define NV40_FP_OP_INPUT_SRC_TC(n)                                 (0x4 + n) +#    define NV40_FP_OP_INPUT_SRC_FACING                                      0xE +#define NV40_FP_OP_TEX_UNIT_SHIFT                                             17 +#define NV40_FP_OP_TEX_UNIT_MASK                                     (0xF << 17) +#define NV40_FP_OP_PRECISION_SHIFT                                            22 +#define NV40_FP_OP_PRECISION_MASK                                      (3 << 22) +#   define NV40_FP_PRECISION_FP32                                              0 +#   define NV40_FP_PRECISION_FP16                                              1 +#   define NV40_FP_PRECISION_FX12                                              2 +#define NV40_FP_OP_OPCODE_SHIFT                                               24 +#define NV40_FP_OP_OPCODE_MASK                                      (0x3F << 24) +#        define NV40_FP_OP_OPCODE_NOP                                       0x00 +#        define NV40_FP_OP_OPCODE_MOV                                       0x01 +#        define NV40_FP_OP_OPCODE_MUL                                       0x02 +#        define NV40_FP_OP_OPCODE_ADD                                       0x03 +#        define NV40_FP_OP_OPCODE_MAD                                       0x04 +#        define NV40_FP_OP_OPCODE_DP3                                       0x05 +#        define NV40_FP_OP_OPCODE_DP4                                       0x06 +#        define NV40_FP_OP_OPCODE_DST                                       0x07 +#        define NV40_FP_OP_OPCODE_MIN                                       0x08 +#        define NV40_FP_OP_OPCODE_MAX                                       0x09 +#        define NV40_FP_OP_OPCODE_SLT                                       0x0A +#        define NV40_FP_OP_OPCODE_SGE                                       0x0B +#        define NV40_FP_OP_OPCODE_SLE                                       0x0C +#        define NV40_FP_OP_OPCODE_SGT                                       0x0D +#        define NV40_FP_OP_OPCODE_SNE                                       0x0E +#        define NV40_FP_OP_OPCODE_SEQ                                       0x0F +#        define NV40_FP_OP_OPCODE_FRC                                       0x10 +#        define NV40_FP_OP_OPCODE_FLR                                       0x11 +#        define NV40_FP_OP_OPCODE_KIL                                       0x12 +#        define NV40_FP_OP_OPCODE_PK4B                                      0x13 +#        define NV40_FP_OP_OPCODE_UP4B                                      0x14 +/* DDX/DDY can only write to XY */ +#        define NV40_FP_OP_OPCODE_DDX                                       0x15 +#        define NV40_FP_OP_OPCODE_DDY                                       0x16 +#        define NV40_FP_OP_OPCODE_TEX                                       0x17 +#        define NV40_FP_OP_OPCODE_TXP                                       0x18 +#        define NV40_FP_OP_OPCODE_TXD                                       0x19 +#        define NV40_FP_OP_OPCODE_RCP                                       0x1A +#        define NV40_FP_OP_OPCODE_EX2                                       0x1C +#        define NV40_FP_OP_OPCODE_LG2                                       0x1D +#        define NV40_FP_OP_OPCODE_STR                                       0x20 +#        define NV40_FP_OP_OPCODE_SFL                                       0x21 +#        define NV40_FP_OP_OPCODE_COS                                       0x22 +#        define NV40_FP_OP_OPCODE_SIN                                       0x23 +#        define NV40_FP_OP_OPCODE_PK2H                                      0x24 +#        define NV40_FP_OP_OPCODE_UP2H                                      0x25 +#        define NV40_FP_OP_OPCODE_PK4UB                                     0x27 +#        define NV40_FP_OP_OPCODE_UP4UB                                     0x28 +#        define NV40_FP_OP_OPCODE_PK2US                                     0x29 +#        define NV40_FP_OP_OPCODE_UP2US                                     0x2A +#        define NV40_FP_OP_OPCODE_DP2A                                      0x2E +#        define NV40_FP_OP_OPCODE_TXL                                       0x2F +#        define NV40_FP_OP_OPCODE_TXB                                       0x31 +#        define NV40_FP_OP_OPCODE_DIV                                       0x3A +#        define NV40_FP_OP_OPCODE_UNK_LIT                                   0x3C +/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/ +#        define NV40_FP_OP_BRA_OPCODE_BRK                                    0x0 +#        define NV40_FP_OP_BRA_OPCODE_CAL                                    0x1 +#        define NV40_FP_OP_BRA_OPCODE_IF                                     0x2 +#        define NV40_FP_OP_BRA_OPCODE_LOOP                                   0x3 +#        define NV40_FP_OP_BRA_OPCODE_REP                                    0x4 +#        define NV40_FP_OP_BRA_OPCODE_RET                                    0x5 +#define NV40_FP_OP_OUT_SAT                                             (1 << 31) + +/* high order bits of SRC0 */ +#define NV40_FP_OP_OUT_ABS                                             (1 << 29) +#define NV40_FP_OP_COND_SWZ_W_SHIFT                                           27 +#define NV40_FP_OP_COND_SWZ_W_MASK                                     (3 << 27) +#define NV40_FP_OP_COND_SWZ_Z_SHIFT                                           25 +#define NV40_FP_OP_COND_SWZ_Z_MASK                                     (3 << 25) +#define NV40_FP_OP_COND_SWZ_Y_SHIFT                                           23 +#define NV40_FP_OP_COND_SWZ_Y_MASK                                     (3 << 23) +#define NV40_FP_OP_COND_SWZ_X_SHIFT                                           21 +#define NV40_FP_OP_COND_SWZ_X_MASK                                     (3 << 21) +#define NV40_FP_OP_COND_SWZ_ALL_SHIFT                                         21 +#define NV40_FP_OP_COND_SWZ_ALL_MASK                                (0xFF << 21) +#define NV40_FP_OP_COND_SHIFT                                                 18 +#define NV40_FP_OP_COND_MASK                                        (0x07 << 18) +#        define NV40_FP_OP_COND_FL                                             0 +#        define NV40_FP_OP_COND_LT                                             1 +#        define NV40_FP_OP_COND_EQ                                             2 +#        define NV40_FP_OP_COND_LE                                             3 +#        define NV40_FP_OP_COND_GT                                             4 +#        define NV40_FP_OP_COND_NE                                             5 +#        define NV40_FP_OP_COND_GE                                             6 +#        define NV40_FP_OP_COND_TR                                             7 + +/* high order bits of SRC1 */ +#define NV40_FP_OP_OPCODE_IS_BRANCH                                      (1<<31) +#define NV40_FP_OP_DST_SCALE_SHIFT                                            28 +#define NV40_FP_OP_DST_SCALE_MASK                                      (3 << 28) +#define NV40_FP_OP_DST_SCALE_1X                                                0 +#define NV40_FP_OP_DST_SCALE_2X                                                1 +#define NV40_FP_OP_DST_SCALE_4X                                                2 +#define NV40_FP_OP_DST_SCALE_8X                                                3 +#define NV40_FP_OP_DST_SCALE_INV_2X                                            5 +#define NV40_FP_OP_DST_SCALE_INV_4X                                            6 +#define NV40_FP_OP_DST_SCALE_INV_8X                                            7 + +/* SRC1 LOOP */ +#define NV40_FP_OP_LOOP_INCR_SHIFT                                            19 +#define NV40_FP_OP_LOOP_INCR_MASK                                   (0xFF << 19) +#define NV40_FP_OP_LOOP_INDEX_SHIFT                                           10 +#define NV40_FP_OP_LOOP_INDEX_MASK                                  (0xFF << 10) +#define NV40_FP_OP_LOOP_COUNT_SHIFT                                            2 +#define NV40_FP_OP_LOOP_COUNT_MASK                                   (0xFF << 2) + +/* SRC1 IF */ +#define NV40_FP_OP_ELSE_ID_SHIFT                                               2 +#define NV40_FP_OP_ELSE_ID_MASK                                      (0xFF << 2) + +/* SRC1 CAL */ +#define NV40_FP_OP_IADDR_SHIFT                                                 2 +#define NV40_FP_OP_IADDR_MASK                                        (0xFF << 2) + +/* SRC1 REP + *   I have no idea why there are 3 count values here..  but they + *   have always been filled with the same value in my tests so + *   far.. + */ +#define NV40_FP_OP_REP_COUNT1_SHIFT                                            2 +#define NV40_FP_OP_REP_COUNT1_MASK                                   (0xFF << 2) +#define NV40_FP_OP_REP_COUNT2_SHIFT                                           10 +#define NV40_FP_OP_REP_COUNT2_MASK                                  (0xFF << 10) +#define NV40_FP_OP_REP_COUNT3_SHIFT                                           19 +#define NV40_FP_OP_REP_COUNT3_MASK                                  (0xFF << 19) + +/* SRC2 REP/IF */ +#define NV40_FP_OP_END_ID_SHIFT                                                2 +#define NV40_FP_OP_END_ID_MASK                                       (0xFF << 2) + +// SRC2 high-order +#define NV40_FP_OP_INDEX_INPUT                                         (1 << 30) +#define NV40_FP_OP_ADDR_INDEX_SHIFT                                           19 +#define NV40_FP_OP_ADDR_INDEX_MASK                                   (0xF << 19) + +//== Register selection == +#define NV40_FP_REG_TYPE_SHIFT                                                 0 +#define NV40_FP_REG_TYPE_MASK                                           (3 << 0) +#        define NV40_FP_REG_TYPE_TEMP                                          0 +#        define NV40_FP_REG_TYPE_INPUT                                         1 +#        define NV40_FP_REG_TYPE_CONST                                         2 +#define NV40_FP_REG_SRC_SHIFT                                                  2 +#define NV40_FP_REG_SRC_MASK                                           (63 << 2) +#define NV40_FP_REG_SRC_HALF                                            (1 << 8) +#define NV40_FP_REG_SWZ_ALL_SHIFT                                              9 +#define NV40_FP_REG_SWZ_ALL_MASK                                      (255 << 9) +#define NV40_FP_REG_SWZ_X_SHIFT                                                9 +#define NV40_FP_REG_SWZ_X_MASK                                          (3 << 9) +#define NV40_FP_REG_SWZ_Y_SHIFT                                               11 +#define NV40_FP_REG_SWZ_Y_MASK                                         (3 << 11) +#define NV40_FP_REG_SWZ_Z_SHIFT                                               13 +#define NV40_FP_REG_SWZ_Z_MASK                                         (3 << 13) +#define NV40_FP_REG_SWZ_W_SHIFT                                               15 +#define NV40_FP_REG_SWZ_W_MASK                                         (3 << 15) +#        define NV40_FP_SWIZZLE_X                                              0 +#        define NV40_FP_SWIZZLE_Y                                              1 +#        define NV40_FP_SWIZZLE_Z                                              2 +#        define NV40_FP_SWIZZLE_W                                              3 +#define NV40_FP_REG_NEGATE                                             (1 << 17) + +#ifndef NV40_SHADER_NO_FUCKEDNESS +#define NV40SR_NONE	0 +#define NV40SR_OUTPUT	1 +#define NV40SR_INPUT	2 +#define NV40SR_TEMP	3 +#define NV40SR_CONST	4 + +struct nv40_sreg { +	int type; +	int index; + +	int dst_scale; + +	int negate; +	int abs; +	int swz[4]; + +	int cc_update; +	int cc_update_reg; +	int cc_test; +	int cc_test_reg; +	int cc_swz[4]; +}; + +static INLINE struct nv40_sreg +nv40_sr(int type, int index) +{ +	struct nv40_sreg temp = { +		.type = type, +		.index = index, +		.dst_scale = DEF_SCALE, +		.abs = 0, +		.negate = 0, +		.swz = { 0, 1, 2, 3 }, +		.cc_update = 0, +		.cc_update_reg = 0, +		.cc_test = DEF_CTEST, +		.cc_test_reg = 0, +		.cc_swz = { 0, 1, 2, 3 }, +	}; +	return temp; +} + +static INLINE struct nv40_sreg +nv40_sr_swz(struct nv40_sreg src, int x, int y, int z, int w) +{ +	struct nv40_sreg dst = src; + +	dst.swz[SWZ_X] = src.swz[x]; +	dst.swz[SWZ_Y] = src.swz[y]; +	dst.swz[SWZ_Z] = src.swz[z]; +	dst.swz[SWZ_W] = src.swz[w]; +	return dst; +} + +static INLINE struct nv40_sreg +nv40_sr_neg(struct nv40_sreg src) +{ +	src.negate = !src.negate; +	return src; +} + +static INLINE struct nv40_sreg +nv40_sr_abs(struct nv40_sreg src) +{ +	src.abs = 1; +	return src; +} + +static INLINE struct nv40_sreg +nv40_sr_scale(struct nv40_sreg src, int scale) +{ +	src.dst_scale = scale; +	return src; +} +#endif + +#endif diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c new file mode 100644 index 0000000000..63d0ecc915 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state.c @@ -0,0 +1,741 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "draw/draw_context.h" + +#include "tgsi/tgsi_parse.h" + +#include "nv40_context.h" +#include "nv40_state.h" + +static void * +nv40_blend_state_create(struct pipe_context *pipe, +			const struct pipe_blend_state *cso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nouveau_grobj *curie = nv40->screen->curie; +	struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso)); +	struct nouveau_stateobj *so = so_new(16, 0); + +	if (cso->blend_enable) { +		so_method(so, curie, NV40TCL_BLEND_ENABLE, 3); +		so_data  (so, 1); +		so_data  (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) | +			       nvgl_blend_func(cso->rgb_src_factor)); +		so_data  (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 | +			      nvgl_blend_func(cso->rgb_dst_factor)); +		so_method(so, curie, NV40TCL_BLEND_EQUATION, 1); +		so_data  (so, nvgl_blend_eqn(cso->alpha_func) << 16 | +			      nvgl_blend_eqn(cso->rgb_func)); +	} else { +		so_method(so, curie, NV40TCL_BLEND_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_method(so, curie, NV40TCL_COLOR_MASK, 1); +	so_data  (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | +		       ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | +		       ((cso->colormask & PIPE_MASK_G) ? (0x01 <<  8) : 0) | +		       ((cso->colormask & PIPE_MASK_B) ? (0x01 <<  0) : 0))); + +	if (cso->logicop_enable) { +		so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2); +		so_data  (so, 1); +		so_data  (so, nvgl_logicop_func(cso->logicop_func)); +	} else { +		so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_method(so, curie, NV40TCL_DITHER_ENABLE, 1); +	so_data  (so, cso->dither ? 1 : 0); + +	so_ref(so, &bso->so); +	bso->pipe = *cso; +	return (void *)bso; +} + +static void +nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->blend = hwcso; +	nv40->dirty |= NV40_NEW_BLEND; +} + +static void +nv40_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_blend_state *bso = hwcso; + +	so_ref(NULL, &bso->so); +	FREE(bso); +} + + +static INLINE unsigned +wrap_mode(unsigned wrap) { +	unsigned ret; + +	switch (wrap) { +	case PIPE_TEX_WRAP_REPEAT: +		ret = NV40TCL_TEX_WRAP_S_REPEAT; +		break; +	case PIPE_TEX_WRAP_MIRROR_REPEAT: +		ret = NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_EDGE: +		ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE; +		break; +	case PIPE_TEX_WRAP_CLAMP_TO_BORDER: +		ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER; +		break; +	case PIPE_TEX_WRAP_CLAMP: +		ret = NV40TCL_TEX_WRAP_S_CLAMP; +		break; +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: +		ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE; +		break; +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: +		ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER; +		break; +	case PIPE_TEX_WRAP_MIRROR_CLAMP: +		ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP; +		break; +	default: +		NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); +		ret = NV40TCL_TEX_WRAP_S_REPEAT; +		break; +	} + +	return ret >> NV40TCL_TEX_WRAP_S_SHIFT; +} + +static void * +nv40_sampler_state_create(struct pipe_context *pipe, +			  const struct pipe_sampler_state *cso) +{ +	struct nv40_sampler_state *ps; +	uint32_t filter = 0; + +	ps = MALLOC(sizeof(struct nv40_sampler_state)); + +	ps->fmt = 0; +	if (!cso->normalized_coords) +		ps->fmt |= NV40TCL_TEX_FORMAT_RECT; + +	ps->wrap = ((wrap_mode(cso->wrap_s) << NV40TCL_TEX_WRAP_S_SHIFT) | +		    (wrap_mode(cso->wrap_t) << NV40TCL_TEX_WRAP_T_SHIFT) | +		    (wrap_mode(cso->wrap_r) << NV40TCL_TEX_WRAP_R_SHIFT)); + +	ps->en = 0; +	if (cso->max_anisotropy >= 2.0) { +		/* no idea, binary driver sets it, works without it.. meh.. */ +		ps->wrap |= (1 << 5); + +		if (cso->max_anisotropy >= 16.0) { +			ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X; +		} else +		if (cso->max_anisotropy >= 12.0) { +			ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X; +		} else +		if (cso->max_anisotropy >= 10.0) { +			ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X; +		} else +		if (cso->max_anisotropy >= 8.0) { +			ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X; +		} else +		if (cso->max_anisotropy >= 6.0) { +			ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X; +		} else +		if (cso->max_anisotropy >= 4.0) { +			ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X; +		} else { +			ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X; +		} +	} + +	switch (cso->mag_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		filter |= NV40TCL_TEX_FILTER_MAG_LINEAR; +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		filter |= NV40TCL_TEX_FILTER_MAG_NEAREST; +		break; +	} + +	switch (cso->min_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST; +			break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV40TCL_TEX_FILTER_MIN_LINEAR; +			break; +		} +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		switch (cso->min_mip_filter) { +		case PIPE_TEX_MIPFILTER_NEAREST: +			filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST; +		break; +		case PIPE_TEX_MIPFILTER_LINEAR: +			filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR; +			break; +		case PIPE_TEX_MIPFILTER_NONE: +		default: +			filter |= NV40TCL_TEX_FILTER_MIN_NEAREST; +			break; +		} +		break; +	} + +	ps->filt = filter; + +	{ +		float limit; + +		limit = CLAMP(cso->lod_bias, -16.0, 15.0); +		ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + +		limit = CLAMP(cso->max_lod, 0.0, 15.0); +		ps->en |= (int)(limit * 256.0) << 7; + +		limit = CLAMP(cso->min_lod, 0.0, 15.0); +		ps->en |= (int)(limit * 256.0) << 19; +	} + + +	if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +		switch (cso->compare_func) { +		case PIPE_FUNC_NEVER: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NEVER; +			break; +		case PIPE_FUNC_GREATER: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GREATER; +			break; +		case PIPE_FUNC_EQUAL: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_EQUAL; +			break; +		case PIPE_FUNC_GEQUAL: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GEQUAL; +			break; +		case PIPE_FUNC_LESS: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LESS; +			break; +		case PIPE_FUNC_NOTEQUAL: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL; +			break; +		case PIPE_FUNC_LEQUAL: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LEQUAL; +			break; +		case PIPE_FUNC_ALWAYS: +			ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_ALWAYS; +			break; +		default: +			break; +		} +	} + +	ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | +		    (float_to_ubyte(cso->border_color[0]) << 16) | +		    (float_to_ubyte(cso->border_color[1]) <<  8) | +		    (float_to_ubyte(cso->border_color[2]) <<  0)); + +	return (void *)ps; +} + +static void +nv40_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv40->tex_sampler[unit] = sampler[unit]; +		nv40->dirty_samplers |= (1 << unit); +	} + +	for (unit = nr; unit < nv40->nr_samplers; unit++) { +		nv40->tex_sampler[unit] = NULL; +		nv40->dirty_samplers |= (1 << unit); +	} + +	nv40->nr_samplers = nr; +	nv40->dirty |= NV40_NEW_SAMPLER; +} + +static void +nv40_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void +nv40_set_sampler_texture(struct pipe_context *pipe, unsigned nr, +			 struct pipe_texture **miptree) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		pipe_texture_reference((struct pipe_texture **) +				       &nv40->tex_miptree[unit], miptree[unit]); +		nv40->dirty_samplers |= (1 << unit); +	} + +	for (unit = nr; unit < nv40->nr_textures; unit++) { +		pipe_texture_reference((struct pipe_texture **) +				       &nv40->tex_miptree[unit], NULL); +		nv40->dirty_samplers |= (1 << unit); +	} + +	nv40->nr_textures = nr; +	nv40->dirty |= NV40_NEW_SAMPLER; +} + +static void * +nv40_rasterizer_state_create(struct pipe_context *pipe, +			     const struct pipe_rasterizer_state *cso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); +	struct nouveau_stateobj *so = so_new(32, 0); +	struct nouveau_grobj *curie = nv40->screen->curie; + +	/*XXX: ignored: +	 * 	light_twoside +	 * 	point_smooth -nohw +	 * 	multisample +	 */ + +	so_method(so, curie, NV40TCL_SHADE_MODEL, 1); +	so_data  (so, cso->flatshade ? NV40TCL_SHADE_MODEL_FLAT : +				       NV40TCL_SHADE_MODEL_SMOOTH); + +	so_method(so, curie, NV40TCL_LINE_WIDTH, 2); +	so_data  (so, (unsigned char)(cso->line_width * 8.0) & 0xff); +	so_data  (so, cso->line_smooth ? 1 : 0); +	so_method(so, curie, NV40TCL_LINE_STIPPLE_ENABLE, 2); +	so_data  (so, cso->line_stipple_enable ? 1 : 0); +	so_data  (so, (cso->line_stipple_pattern << 16) | +		       cso->line_stipple_factor); + +	so_method(so, curie, NV40TCL_POINT_SIZE, 1); +	so_data  (so, fui(cso->point_size)); + +	so_method(so, curie, NV40TCL_POLYGON_MODE_FRONT, 6); +	if (cso->front_winding == PIPE_WINDING_CCW) { +		so_data(so, nvgl_polygon_mode(cso->fill_ccw)); +		so_data(so, nvgl_polygon_mode(cso->fill_cw)); +		switch (cso->cull_mode) { +		case PIPE_WINDING_CCW: +			so_data(so, NV40TCL_CULL_FACE_FRONT); +			break; +		case PIPE_WINDING_CW: +			so_data(so, NV40TCL_CULL_FACE_BACK); +			break; +		case PIPE_WINDING_BOTH: +			so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK); +			break; +		default: +			so_data(so, NV40TCL_CULL_FACE_BACK); +			break; +		} +		so_data(so, NV40TCL_FRONT_FACE_CCW); +	} else { +		so_data(so, nvgl_polygon_mode(cso->fill_cw)); +		so_data(so, nvgl_polygon_mode(cso->fill_ccw)); +		switch (cso->cull_mode) { +		case PIPE_WINDING_CCW: +			so_data(so, NV40TCL_CULL_FACE_BACK); +			break; +		case PIPE_WINDING_CW: +			so_data(so, NV40TCL_CULL_FACE_FRONT); +			break; +		case PIPE_WINDING_BOTH: +			so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK); +			break; +		default: +			so_data(so, NV40TCL_CULL_FACE_BACK); +			break; +		} +		so_data(so, NV40TCL_FRONT_FACE_CW); +	} +	so_data(so, cso->poly_smooth ? 1 : 0); +	so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); + +	so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); +	so_data  (so, cso->poly_stipple_enable ? 1 : 0); + +	so_method(so, curie, NV40TCL_POLYGON_OFFSET_POINT_ENABLE, 3); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if (cso->offset_cw || cso->offset_ccw) { +		so_method(so, curie, NV40TCL_POLYGON_OFFSET_FACTOR, 2); +		so_data  (so, fui(cso->offset_scale)); +		so_data  (so, fui(cso->offset_units * 2)); +	} + +	so_method(so, curie, NV40TCL_POINT_SPRITE, 1); +	if (cso->point_sprite) { +		unsigned psctl = (1 << 0), i; + +		for (i = 0; i < 8; i++) { +			if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE) +				psctl |= (1 << (8 + i)); +		} + +		so_data(so, psctl); +	} else { +		so_data(so, 0); +	} + +	so_ref(so, &rsso->so); +	rsso->pipe = *cso; +	return (void *)rsso; +} + +static void +nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->rasterizer = hwcso; +	nv40->dirty |= NV40_NEW_RAST; +	nv40->draw_dirty |= NV40_NEW_RAST; +} + +static void +nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_rasterizer_state *rsso = hwcso; + +	so_ref(NULL, &rsso->so); +	FREE(rsso); +} + +static void * +nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, +			const struct pipe_depth_stencil_alpha_state *cso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); +	struct nouveau_stateobj *so = so_new(32, 0); +	struct nouveau_grobj *curie = nv40->screen->curie; + +	so_method(so, curie, NV40TCL_DEPTH_FUNC, 3); +	so_data  (so, nvgl_comparison_op(cso->depth.func)); +	so_data  (so, cso->depth.writemask ? 1 : 0); +	so_data  (so, cso->depth.enabled ? 1 : 0); + +	so_method(so, curie, NV40TCL_ALPHA_TEST_ENABLE, 3); +	so_data  (so, cso->alpha.enabled ? 1 : 0); +	so_data  (so, nvgl_comparison_op(cso->alpha.func)); +	so_data  (so, float_to_ubyte(cso->alpha.ref)); + +	if (cso->stencil[0].enabled) { +		so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 8); +		so_data  (so, cso->stencil[0].enabled ? 1 : 0); +		so_data  (so, cso->stencil[0].write_mask); +		so_data  (so, nvgl_comparison_op(cso->stencil[0].func)); +		so_data  (so, cso->stencil[0].ref_value); +		so_data  (so, cso->stencil[0].value_mask); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].fail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); +	} else { +		so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1); +		so_data  (so, 0); +	} + +	if (cso->stencil[1].enabled) { +		so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 8); +		so_data  (so, cso->stencil[1].enabled ? 1 : 0); +		so_data  (so, cso->stencil[1].write_mask); +		so_data  (so, nvgl_comparison_op(cso->stencil[1].func)); +		so_data  (so, cso->stencil[1].ref_value); +		so_data  (so, cso->stencil[1].value_mask); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].fail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); +	} else { +		so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_ref(so, &zsaso->so); +	zsaso->pipe = *cso; +	return (void *)zsaso; +} + +static void +nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->zsa = hwcso; +	nv40->dirty |= NV40_NEW_ZSA; +} + +static void +nv40_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_zsa_state *zsaso = hwcso; + +	so_ref(NULL, &zsaso->so); +	FREE(zsaso); +} + +static void * +nv40_vp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_vertex_program *vp; + +	vp = CALLOC(1, sizeof(struct nv40_vertex_program)); +	vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); +	vp->draw = draw_create_vertex_shader(nv40->draw, &vp->pipe); + +	return (void *)vp; +} + +static void +nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->vertprog = hwcso; +	nv40->dirty |= NV40_NEW_VERTPROG; +	nv40->draw_dirty |= NV40_NEW_VERTPROG; +} + +static void +nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_vertex_program *vp = hwcso; + +	draw_delete_vertex_shader(nv40->draw, vp->draw); +	nv40_vertprog_destroy(nv40, vp); +	FREE((void*)vp->pipe.tokens); +	FREE(vp); +} + +static void * +nv40_fp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv40_fragment_program *fp; + +	fp = CALLOC(1, sizeof(struct nv40_fragment_program)); +	fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + +	tgsi_scan_shader(fp->pipe.tokens, &fp->info); + +	return (void *)fp; +} + +static void +nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->fragprog = hwcso; +	nv40->dirty |= NV40_NEW_FRAGPROG; +} + +static void +nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nv40_fragment_program *fp = hwcso; + +	nv40_fragprog_destroy(nv40, fp); +	FREE((void*)fp->pipe.tokens); +	FREE(fp); +} + +static void +nv40_set_blend_color(struct pipe_context *pipe, +		     const struct pipe_blend_color *bcol) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->blend_colour = *bcol; +	nv40->dirty |= NV40_NEW_BCOL; +} + +static void +nv40_set_clip_state(struct pipe_context *pipe, +		    const struct pipe_clip_state *clip) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->clip = *clip; +	nv40->dirty |= NV40_NEW_UCP; +	nv40->draw_dirty |= NV40_NEW_UCP; +} + +static void +nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, +			 const struct pipe_constant_buffer *buf ) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->constbuf[shader] = buf->buffer; +	nv40->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); + +	if (shader == PIPE_SHADER_VERTEX) { +		nv40->dirty |= NV40_NEW_VERTPROG; +	} else +	if (shader == PIPE_SHADER_FRAGMENT) { +		nv40->dirty |= NV40_NEW_FRAGPROG; +	} +} + +static void +nv40_set_framebuffer_state(struct pipe_context *pipe, +			   const struct pipe_framebuffer_state *fb) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->framebuffer = *fb; +	nv40->dirty |= NV40_NEW_FB; +} + +static void +nv40_set_polygon_stipple(struct pipe_context *pipe, +			 const struct pipe_poly_stipple *stipple) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	memcpy(nv40->stipple, stipple->stipple, 4 * 32); +	nv40->dirty |= NV40_NEW_STIPPLE; +} + +static void +nv40_set_scissor_state(struct pipe_context *pipe, +		       const struct pipe_scissor_state *s) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->scissor = *s; +	nv40->dirty |= NV40_NEW_SCISSOR; +} + +static void +nv40_set_viewport_state(struct pipe_context *pipe, +			const struct pipe_viewport_state *vpt) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->viewport = *vpt; +	nv40->dirty |= NV40_NEW_VIEWPORT; +	nv40->draw_dirty |= NV40_NEW_VIEWPORT; +} + +static void +nv40_set_vertex_buffers(struct pipe_context *pipe, unsigned count, +			const struct pipe_vertex_buffer *vb) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	memcpy(nv40->vtxbuf, vb, sizeof(*vb) * count); +	nv40->vtxbuf_nr = count; + +	nv40->dirty |= NV40_NEW_ARRAYS; +	nv40->draw_dirty |= NV40_NEW_ARRAYS; +} + +static void +nv40_set_vertex_elements(struct pipe_context *pipe, unsigned count, +			 const struct pipe_vertex_element *ve) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	memcpy(nv40->vtxelt, ve, sizeof(*ve) * count); +	nv40->vtxelt_nr = count; + +	nv40->dirty |= NV40_NEW_ARRAYS; +	nv40->draw_dirty |= NV40_NEW_ARRAYS; +} + +static void +nv40_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) +{ +	struct nv40_context *nv40 = nv40_context(pipe); + +	nv40->edgeflags = bitfield; +	nv40->dirty |= NV40_NEW_ARRAYS; +	nv40->draw_dirty |= NV40_NEW_ARRAYS; +} + +void +nv40_init_state_functions(struct nv40_context *nv40) +{ +	nv40->pipe.create_blend_state = nv40_blend_state_create; +	nv40->pipe.bind_blend_state = nv40_blend_state_bind; +	nv40->pipe.delete_blend_state = nv40_blend_state_delete; + +	nv40->pipe.create_sampler_state = nv40_sampler_state_create; +	nv40->pipe.bind_sampler_states = nv40_sampler_state_bind; +	nv40->pipe.delete_sampler_state = nv40_sampler_state_delete; +	nv40->pipe.set_sampler_textures = nv40_set_sampler_texture; + +	nv40->pipe.create_rasterizer_state = nv40_rasterizer_state_create; +	nv40->pipe.bind_rasterizer_state = nv40_rasterizer_state_bind; +	nv40->pipe.delete_rasterizer_state = nv40_rasterizer_state_delete; + +	nv40->pipe.create_depth_stencil_alpha_state = +		nv40_depth_stencil_alpha_state_create; +	nv40->pipe.bind_depth_stencil_alpha_state = +		nv40_depth_stencil_alpha_state_bind; +	nv40->pipe.delete_depth_stencil_alpha_state = +		nv40_depth_stencil_alpha_state_delete; + +	nv40->pipe.create_vs_state = nv40_vp_state_create; +	nv40->pipe.bind_vs_state = nv40_vp_state_bind; +	nv40->pipe.delete_vs_state = nv40_vp_state_delete; + +	nv40->pipe.create_fs_state = nv40_fp_state_create; +	nv40->pipe.bind_fs_state = nv40_fp_state_bind; +	nv40->pipe.delete_fs_state = nv40_fp_state_delete; + +	nv40->pipe.set_blend_color = nv40_set_blend_color; +	nv40->pipe.set_clip_state = nv40_set_clip_state; +	nv40->pipe.set_constant_buffer = nv40_set_constant_buffer; +	nv40->pipe.set_framebuffer_state = nv40_set_framebuffer_state; +	nv40->pipe.set_polygon_stipple = nv40_set_polygon_stipple; +	nv40->pipe.set_scissor_state = nv40_set_scissor_state; +	nv40->pipe.set_viewport_state = nv40_set_viewport_state; + +	nv40->pipe.set_edgeflags = nv40_set_edgeflags; +	nv40->pipe.set_vertex_buffers = nv40_set_vertex_buffers; +	nv40->pipe.set_vertex_elements = nv40_set_vertex_elements; +} + diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h new file mode 100644 index 0000000000..8a9d8c8fdf --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state.h @@ -0,0 +1,88 @@ +#ifndef __NV40_STATE_H__ +#define __NV40_STATE_H__ + +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" + +struct nv40_sampler_state { +	uint32_t fmt; +	uint32_t wrap; +	uint32_t en; +	uint32_t filt; +	uint32_t bcol; +}; + +struct nv40_vertex_program_exec { +	uint32_t data[4]; +	boolean has_branch_offset; +	int const_index; +}; + +struct nv40_vertex_program_data { +	int index; /* immediates == -1 */ +	float value[4]; +}; + +struct nv40_vertex_program { +	struct pipe_shader_state pipe; + +	struct draw_vertex_shader *draw; + +	boolean translated; + +	struct pipe_clip_state ucp; + +	struct nv40_vertex_program_exec *insns; +	unsigned nr_insns; +	struct nv40_vertex_program_data *consts; +	unsigned nr_consts; + +	struct nouveau_resource *exec; +	unsigned exec_start; +	struct nouveau_resource *data; +	unsigned data_start; +	unsigned data_start_min; + +	uint32_t ir; +	uint32_t or; +	uint32_t clip_ctrl; +	struct nouveau_stateobj *so; +}; + +struct nv40_fragment_program_data { +	unsigned offset; +	unsigned index; +}; + +struct nv40_fragment_program { +	struct pipe_shader_state pipe; +	struct tgsi_shader_info info; + +	boolean translated; +	unsigned samplers; + +	uint32_t *insn; +	int       insn_len; + +	struct nv40_fragment_program_data *consts; +	unsigned nr_consts; + +	struct pipe_buffer *buffer; + +	uint32_t fp_control; +	struct nouveau_stateobj *so; +}; + +struct nv40_miptree { +	struct pipe_texture base; + +	struct pipe_buffer *buffer; +	uint total_size; + +	struct { +		uint pitch; +		uint *image_offset; +	} level[PIPE_MAX_TEXTURE_LEVELS]; +}; + +#endif diff --git a/src/gallium/drivers/nv40/nv40_state_blend.c b/src/gallium/drivers/nv40/nv40_state_blend.c new file mode 100644 index 0000000000..95e6d7394f --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_blend.c @@ -0,0 +1,40 @@ +#include "nv40_context.h" + +static boolean +nv40_state_blend_validate(struct nv40_context *nv40) +{ +	so_ref(nv40->blend->so, &nv40->state.hw[NV40_STATE_BLEND]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_blend = { +	.validate = nv40_state_blend_validate, +	.dirty = { +		.pipe = NV40_NEW_BLEND, +		.hw = NV40_STATE_BLEND +	} +}; + +static boolean +nv40_state_blend_colour_validate(struct nv40_context *nv40) +{ +	struct nouveau_stateobj *so = so_new(2, 0); +	struct pipe_blend_color *bcol = &nv40->blend_colour; + +	so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1); +	so_data  (so, ((float_to_ubyte(bcol->color[3]) << 24) | +		       (float_to_ubyte(bcol->color[0]) << 16) | +		       (float_to_ubyte(bcol->color[1]) <<  8) | +		       (float_to_ubyte(bcol->color[2]) <<  0))); + +	so_ref(so, &nv40->state.hw[NV40_STATE_BCOL]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_blend_colour = { +	.validate = nv40_state_blend_colour_validate, +	.dirty = { +		.pipe = NV40_NEW_BCOL, +		.hw = NV40_STATE_BCOL +	} +}; diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c new file mode 100644 index 0000000000..ab88dc416e --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_emit.c @@ -0,0 +1,184 @@ +#include "nv40_context.h" +#include "nv40_state.h" +#include "draw/draw_context.h" + +static struct nv40_state_entry *render_states[] = { +	&nv40_state_framebuffer, +	&nv40_state_rasterizer, +	&nv40_state_scissor, +	&nv40_state_stipple, +	&nv40_state_fragprog, +	&nv40_state_fragtex, +	&nv40_state_vertprog, +	&nv40_state_blend, +	&nv40_state_blend_colour, +	&nv40_state_zsa, +	&nv40_state_viewport, +	&nv40_state_vbo, +	NULL +}; + +static struct nv40_state_entry *swtnl_states[] = { +	&nv40_state_framebuffer, +	&nv40_state_rasterizer, +	&nv40_state_scissor, +	&nv40_state_stipple, +	&nv40_state_fragprog, +	&nv40_state_fragtex, +	&nv40_state_vertprog, +	&nv40_state_blend, +	&nv40_state_blend_colour, +	&nv40_state_zsa, +	&nv40_state_viewport, +	&nv40_state_vtxfmt, +	NULL +}; + +static void +nv40_state_do_validate(struct nv40_context *nv40, +		       struct nv40_state_entry **states) +{ +	const struct pipe_framebuffer_state *fb = &nv40->framebuffer; +	unsigned i; + +	for (i = 0; i < fb->num_cbufs; i++) +		fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED; +	if (fb->zsbuf) +		fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED; + +	while (*states) { +		struct nv40_state_entry *e = *states; + +		if (nv40->dirty & e->dirty.pipe) { +			if (e->validate(nv40)) +				nv40->state.dirty |= (1ULL << e->dirty.hw); +		} + +		states++; +	} +	nv40->dirty = 0; +} + +void +nv40_state_emit(struct nv40_context *nv40) +{ +	struct nv40_state *state = &nv40->state; +	struct nv40_screen *screen = nv40->screen; +	unsigned i, samplers; +	uint64 states; + +	if (nv40->pctx_id != screen->cur_pctx) { +		for (i = 0; i < NV40_STATE_MAX; i++) { +			if (state->hw[i] && screen->state[i] != state->hw[i]) +				state->dirty |= (1ULL << i); +		} + +		screen->cur_pctx = nv40->pctx_id; +	} + +	for (i = 0, states = state->dirty; states; i++) { +		if (!(states & (1ULL << i))) +			continue; +		so_ref (state->hw[i], &nv40->screen->state[i]); +		if (state->hw[i]) +			so_emit(nv40->nvws, nv40->screen->state[i]); +		states &= ~(1ULL << i); +	} + +	if (state->dirty & ((1ULL << NV40_STATE_FRAGPROG) | +			    (1ULL << NV40_STATE_FRAGTEX0))) { +		BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1); +		OUT_RING  (2); +		BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1); +		OUT_RING  (1); +	} + +	state->dirty = 0; + +	so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FB]); +	for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { +		if (!(samplers & (1 << i))) +			continue; +		so_emit_reloc_markers(nv40->nvws, +				      state->hw[NV40_STATE_FRAGTEX0+i]); +		samplers &= ~(1ULL << i); +	} +	so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FRAGPROG]); +	if (state->hw[NV40_STATE_VTXBUF] && nv40->render_mode == HW) +		so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_VTXBUF]); +} + +boolean +nv40_state_validate(struct nv40_context *nv40) +{ +	boolean was_sw = nv40->fallback_swtnl ? TRUE : FALSE; + +	if (nv40->render_mode != HW) { +		/* Don't even bother trying to go back to hw if none +		 * of the states that caused swtnl previously have changed. +		 */ +		if ((nv40->fallback_swtnl & nv40->dirty) +				!= nv40->fallback_swtnl) +			return FALSE; + +		/* Attempt to go to hwtnl again */ +		nv40->pipe.flush(&nv40->pipe, 0, NULL); +		nv40->dirty |= (NV40_NEW_VIEWPORT | +				NV40_NEW_VERTPROG | +				NV40_NEW_ARRAYS); +		nv40->render_mode = HW; +	} + +	nv40_state_do_validate(nv40, render_states); +	if (nv40->fallback_swtnl || nv40->fallback_swrast) +		return FALSE; +	 +	if (was_sw) +		NOUVEAU_ERR("swtnl->hw\n"); + +	return TRUE; +} + +boolean +nv40_state_validate_swtnl(struct nv40_context *nv40) +{ +	struct draw_context *draw = nv40->draw; + +	/* Setup for swtnl */ +	if (nv40->render_mode == HW) { +		NOUVEAU_ERR("hw->swtnl 0x%08x\n", nv40->fallback_swtnl); +		nv40->pipe.flush(&nv40->pipe, 0, NULL); +		nv40->dirty |= (NV40_NEW_VIEWPORT | +				NV40_NEW_VERTPROG | +				NV40_NEW_ARRAYS); +		nv40->render_mode = SWTNL; +	} + +	if (nv40->draw_dirty & NV40_NEW_VERTPROG) +		draw_bind_vertex_shader(draw, nv40->vertprog->draw); + +	if (nv40->draw_dirty & NV40_NEW_RAST) +		draw_set_rasterizer_state(draw, &nv40->rasterizer->pipe); + +	if (nv40->draw_dirty & NV40_NEW_UCP) +		draw_set_clip_state(draw, &nv40->clip); + +	if (nv40->draw_dirty & NV40_NEW_VIEWPORT) +		draw_set_viewport_state(draw, &nv40->viewport); + +	if (nv40->draw_dirty & NV40_NEW_ARRAYS) { +		draw_set_edgeflags(draw, nv40->edgeflags); +		draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf); +		draw_set_vertex_elements(draw, nv40->vtxelt_nr, nv40->vtxelt);	 +	} + +	nv40_state_do_validate(nv40, swtnl_states); +	if (nv40->fallback_swrast) { +		NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nv40->fallback_swrast); +		return FALSE; +	} + +	nv40->draw_dirty = 0; +	return TRUE; +} + diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c new file mode 100644 index 0000000000..0e4e60eaa7 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_fb.c @@ -0,0 +1,144 @@ +#include "nv40_context.h" + +static boolean +nv40_state_framebuffer_validate(struct nv40_context *nv40) +{ +	struct pipe_framebuffer_state *fb = &nv40->framebuffer; +	struct pipe_surface *rt[4], *zeta; +	uint32_t rt_enable, rt_format; +	int i, colour_format = 0, zeta_format = 0; +	struct nouveau_stateobj *so = so_new(64, 10); +	unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; +	unsigned w = fb->width; +	unsigned h = fb->height; + +	rt_enable = 0; +	for (i = 0; i < fb->num_cbufs; i++) { +		if (colour_format) { +			assert(colour_format == fb->cbufs[i]->format); +		} else { +			colour_format = fb->cbufs[i]->format; +			rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i); +			rt[i] = fb->cbufs[i]; +		} +	} + +	if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 | +			 NV40TCL_RT_ENABLE_COLOR3)) +		rt_enable |= NV40TCL_RT_ENABLE_MRT; + +	if (fb->zsbuf) { +		zeta_format = fb->zsbuf->format; +		zeta = fb->zsbuf; +	} + +	rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR; + +	switch (colour_format) { +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case 0: +		rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8; +		break; +	case PIPE_FORMAT_R5G6B5_UNORM: +		rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5; +		break; +	default: +		assert(0); +	} + +	switch (zeta_format) { +	case PIPE_FORMAT_Z16_UNORM: +		rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16; +		break; +	case PIPE_FORMAT_Z24S8_UNORM: +	case 0: +		rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8; +		break; +	default: +		assert(0); +	} + +	if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { +		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1); +		so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv40->nvws->channel->vram->handle, +			  nv40->nvws->channel->gart->handle); +		so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2); +		so_data  (so, rt[0]->stride); +		so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +	} + +	if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { +		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1); +		so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv40->nvws->channel->vram->handle, +			  nv40->nvws->channel->gart->handle); +		so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2); +		so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +		so_data  (so, rt[1]->stride); +	} + +	if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { +		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1); +		so_reloc (so, rt[2]->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv40->nvws->channel->vram->handle, +			  nv40->nvws->channel->gart->handle); +		so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1); +		so_reloc (so, rt[2]->buffer, rt[2]->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +		so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1); +		so_data  (so, rt[2]->stride); +	} + +	if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { +		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1); +		so_reloc (so, rt[3]->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv40->nvws->channel->vram->handle, +			  nv40->nvws->channel->gart->handle); +		so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1); +		so_reloc (so, rt[3]->buffer, rt[3]->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +		so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1); +		so_data  (so, rt[3]->stride); +	} + +	if (zeta_format) { +		so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1); +		so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR, +			  nv40->nvws->channel->vram->handle, +			  nv40->nvws->channel->gart->handle); +		so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1); +		so_reloc (so, zeta->buffer, zeta->offset, rt_flags | +			  NOUVEAU_BO_LOW, 0, 0); +		so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1); +		so_data  (so, zeta->stride); +	} + +	so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1); +	so_data  (so, rt_enable); +	so_method(so, nv40->screen->curie, NV40TCL_RT_HORIZ, 3); +	so_data  (so, (w << 16) | 0); +	so_data  (so, (h << 16) | 0); +	so_data  (so, rt_format); +	so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_HORIZ, 2); +	so_data  (so, (w << 16) | 0); +	so_data  (so, (h << 16) | 0); +	so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2); +	so_data  (so, ((w - 1) << 16) | 0); +	so_data  (so, ((h - 1) << 16) | 0); +	so_method(so, nv40->screen->curie, 0x1d88, 1); +	so_data  (so, (1 << 12) | h); + +	so_ref(so, &nv40->state.hw[NV40_STATE_FB]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_framebuffer = { +	.validate = nv40_state_framebuffer_validate, +	.dirty = { +		.pipe = NV40_NEW_FB, +		.hw = NV40_STATE_FB +	} +}; diff --git a/src/gallium/drivers/nv40/nv40_state_rasterizer.c b/src/gallium/drivers/nv40/nv40_state_rasterizer.c new file mode 100644 index 0000000000..9ecda5990f --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_rasterizer.c @@ -0,0 +1,17 @@ +#include "nv40_context.h" + +static boolean +nv40_state_rasterizer_validate(struct nv40_context *nv40) +{ +	so_ref(nv40->rasterizer->so, +	       &nv40->state.hw[NV40_STATE_RAST]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_rasterizer = { +	.validate = nv40_state_rasterizer_validate, +	.dirty = { +		.pipe = NV40_NEW_RAST, +		.hw = NV40_STATE_RAST +	} +}; diff --git a/src/gallium/drivers/nv40/nv40_state_scissor.c b/src/gallium/drivers/nv40/nv40_state_scissor.c new file mode 100644 index 0000000000..285239ef41 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_scissor.c @@ -0,0 +1,35 @@ +#include "nv40_context.h" + +static boolean +nv40_state_scissor_validate(struct nv40_context *nv40) +{ +	struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe; +	struct pipe_scissor_state *s = &nv40->scissor; +	struct nouveau_stateobj *so; + +	if (nv40->state.hw[NV40_STATE_SCISSOR] && +	    (rast->scissor == 0 && nv40->state.scissor_enabled == 0)) +		return FALSE; +	nv40->state.scissor_enabled = rast->scissor; + +	so = so_new(3, 0); +	so_method(so, nv40->screen->curie, NV40TCL_SCISSOR_HORIZ, 2); +	if (nv40->state.scissor_enabled) { +		so_data  (so, ((s->maxx - s->minx) << 16) | s->minx); +		so_data  (so, ((s->maxy - s->miny) << 16) | s->miny); +	} else { +		so_data  (so, 4096 << 16); +		so_data  (so, 4096 << 16); +	} + +	so_ref(so, &nv40->state.hw[NV40_STATE_SCISSOR]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_scissor = { +	.validate = nv40_state_scissor_validate, +	.dirty = { +		.pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST, +		.hw = NV40_STATE_SCISSOR +	} +}; diff --git a/src/gallium/drivers/nv40/nv40_state_stipple.c b/src/gallium/drivers/nv40/nv40_state_stipple.c new file mode 100644 index 0000000000..b51024ad9b --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_stipple.c @@ -0,0 +1,39 @@ +#include "nv40_context.h" + +static boolean +nv40_state_stipple_validate(struct nv40_context *nv40) +{ +	struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe; +	struct nouveau_grobj *curie = nv40->screen->curie; +	struct nouveau_stateobj *so; + +	if (nv40->state.hw[NV40_STATE_STIPPLE] && +	   (rast->poly_stipple_enable == 0 && nv40->state.stipple_enabled == 0)) +		return FALSE; + +	if (rast->poly_stipple_enable) { +		unsigned i; + +		so = so_new(35, 0); +		so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); +		so_data  (so, 1); +		so_method(so, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32); +		for (i = 0; i < 32; i++) +			so_data(so, nv40->stipple[i]); +	} else { +		so = so_new(2, 0); +		so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_ref(so, &nv40->state.hw[NV40_STATE_STIPPLE]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_stipple = { +	.validate = nv40_state_stipple_validate, +	.dirty = { +		.pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST, +		.hw = NV40_STATE_STIPPLE, +	} +}; diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c new file mode 100644 index 0000000000..869a55b405 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_viewport.c @@ -0,0 +1,67 @@ +#include "nv40_context.h" + +static boolean +nv40_state_viewport_validate(struct nv40_context *nv40) +{ +	struct pipe_viewport_state *vpt = &nv40->viewport; +	struct nouveau_stateobj *so; +	unsigned bypass; + +	if (nv40->render_mode == HW && !nv40->rasterizer->pipe.bypass_clipping) +		bypass = 0; +	else +		bypass = 1; + +	if (nv40->state.hw[NV40_STATE_VIEWPORT] && +	    (bypass || !(nv40->dirty & NV40_NEW_VIEWPORT)) && +	    nv40->state.viewport_bypass == bypass) +		return FALSE; +	nv40->state.viewport_bypass = bypass; + +	so = so_new(11, 0); +	if (!bypass) { +		so_method(so, nv40->screen->curie, +			  NV40TCL_VIEWPORT_TRANSLATE_X, 8); +		so_data  (so, fui(vpt->translate[0])); +		so_data  (so, fui(vpt->translate[1])); +		so_data  (so, fui(vpt->translate[2])); +		so_data  (so, fui(vpt->translate[3])); +		so_data  (so, fui(vpt->scale[0])); +		so_data  (so, fui(vpt->scale[1])); +		so_data  (so, fui(vpt->scale[2])); +		so_data  (so, fui(vpt->scale[3])); +		so_method(so, nv40->screen->curie, 0x1d78, 1); +		so_data  (so, 1); +	} else { +		so_method(so, nv40->screen->curie, +			  NV40TCL_VIEWPORT_TRANSLATE_X, 8); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(0.0)); +		so_data  (so, fui(1.0)); +		so_data  (so, fui(1.0)); +		so_data  (so, fui(1.0)); +		so_data  (so, fui(0.0)); +		/* Not entirely certain what this is yet.  The DDX uses this +		 * value also as it fixes rendering when you pass +		 * pre-transformed vertices to the GPU.  My best gusss is that +		 * this bypasses some culling/clipping stage.  Might be worth +		 * noting that points/lines are uneffected by whatever this +		 * value fixes, only filled polygons are effected. +		 */ +		so_method(so, nv40->screen->curie, 0x1d78, 1); +		so_data  (so, 0x110); +	} + +	so_ref(so, &nv40->state.hw[NV40_STATE_VIEWPORT]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_viewport = { +	.validate = nv40_state_viewport_validate, +	.dirty = { +		.pipe = NV40_NEW_VIEWPORT | NV40_NEW_RAST, +		.hw = NV40_STATE_VIEWPORT +	} +}; diff --git a/src/gallium/drivers/nv40/nv40_state_zsa.c b/src/gallium/drivers/nv40/nv40_state_zsa.c new file mode 100644 index 0000000000..fb760677c8 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_state_zsa.c @@ -0,0 +1,17 @@ +#include "nv40_context.h" + +static boolean +nv40_state_zsa_validate(struct nv40_context *nv40) +{ +	so_ref(nv40->zsa->so, +	       &nv40->state.hw[NV40_STATE_ZSA]); +	return TRUE; +} + +struct nv40_state_entry nv40_state_zsa = { +	.validate = nv40_state_zsa_validate, +	.dirty = { +		.pipe = NV40_NEW_ZSA, +		.hw = NV40_STATE_ZSA +	} +}; diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c new file mode 100644 index 0000000000..0916555d56 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_surface.c @@ -0,0 +1,77 @@ + +/************************************************************************** + *  + * Copyright 2003 Tungsten Graphics, 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, 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 TUNGSTEN GRAPHICS 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. + *  + **************************************************************************/ + +#include "nv40_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_winsys.h" +#include "pipe/p_inlines.h" +#include "util/p_tile.h" + +static void +nv40_surface_copy(struct pipe_context *pipe, boolean do_flip, +		  struct pipe_surface *dest, unsigned destx, unsigned desty, +		  struct pipe_surface *src, unsigned srcx, unsigned srcy, +		  unsigned width, unsigned height) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nouveau_winsys *nvws = nv40->nvws; + +	if (do_flip) { +		/*XXX: This dodgyness will do for now for correctness.  But, +		 *     need to investigate whether the 2D engine is able to +		 *     manage a flip (perhaps SIFM?), if not, use the 3D engine +		 */ +		desty += height; +		while (height--) { +			nvws->surface_copy(nvws, dest, destx, desty--, src, +					   srcx, srcy++, width, 1); +		} +	} else { +		nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, +				   width, height); +	} +} + +static void +nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +		  unsigned destx, unsigned desty, unsigned width, +		  unsigned height, unsigned value) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nouveau_winsys *nvws = nv40->nvws; + +	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +} + +void +nv40_init_surface_functions(struct nv40_context *nv40) +{ +	nv40->pipe.surface_copy = nv40_surface_copy; +	nv40->pipe.surface_fill = nv40_surface_fill; +} diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c new file mode 100644 index 0000000000..93669e6192 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_vbo.c @@ -0,0 +1,560 @@ +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" + +#include "nv40_context.h" +#include "nv40_state.h" + +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_pushbuf.h" +#include "nouveau/nouveau_util.h" + +#define FORCE_SWTNL 0 + +static INLINE int +nv40_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) +{ +	char fs[128]; + +	switch (pipe) { +	case PIPE_FORMAT_R32_FLOAT: +	case PIPE_FORMAT_R32G32_FLOAT: +	case PIPE_FORMAT_R32G32B32_FLOAT: +	case PIPE_FORMAT_R32G32B32A32_FLOAT: +		*fmt = NV40TCL_VTXFMT_TYPE_FLOAT; +		break; +	case PIPE_FORMAT_R8_UNORM: +	case PIPE_FORMAT_R8G8_UNORM: +	case PIPE_FORMAT_R8G8B8_UNORM: +	case PIPE_FORMAT_R8G8B8A8_UNORM: +		*fmt = NV40TCL_VTXFMT_TYPE_UBYTE; +		break; +	case PIPE_FORMAT_R16_SSCALED: +	case PIPE_FORMAT_R16G16_SSCALED: +	case PIPE_FORMAT_R16G16B16_SSCALED: +	case PIPE_FORMAT_R16G16B16A16_SSCALED: +		*fmt = NV40TCL_VTXFMT_TYPE_USHORT; +		break; +	default: +		pf_sprint_name(fs, pipe); +		NOUVEAU_ERR("Unknown format %s\n", fs); +		return 1; +	} + +	switch (pipe) { +	case PIPE_FORMAT_R8_UNORM: +	case PIPE_FORMAT_R32_FLOAT: +	case PIPE_FORMAT_R16_SSCALED: +		*ncomp = 1; +		break; +	case PIPE_FORMAT_R8G8_UNORM: +	case PIPE_FORMAT_R32G32_FLOAT: +	case PIPE_FORMAT_R16G16_SSCALED: +		*ncomp = 2; +		break; +	case PIPE_FORMAT_R8G8B8_UNORM: +	case PIPE_FORMAT_R32G32B32_FLOAT: +	case PIPE_FORMAT_R16G16B16_SSCALED: +		*ncomp = 3; +		break; +	case PIPE_FORMAT_R8G8B8A8_UNORM: +	case PIPE_FORMAT_R32G32B32A32_FLOAT: +	case PIPE_FORMAT_R16G16B16A16_SSCALED: +		*ncomp = 4; +		break; +	default: +		pf_sprint_name(fs, pipe); +		NOUVEAU_ERR("Unknown format %s\n", fs); +		return 1; +	} + +	return 0; +} + +static boolean +nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib, +		    unsigned ib_size) +{ +	struct pipe_screen *pscreen = &nv40->screen->pipe; +	unsigned type; + +	if (!ib) { +		nv40->idxbuf = NULL; +		nv40->idxbuf_format = 0xdeadbeef; +		return FALSE; +	} + +	if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) +		return FALSE; + +	switch (ib_size) { +	case 2: +		type = NV40TCL_IDXBUF_FORMAT_TYPE_U16; +		break; +	case 4: +		type = NV40TCL_IDXBUF_FORMAT_TYPE_U32; +		break; +	default: +		return FALSE; +	} + +	if (ib != nv40->idxbuf || +	    type != nv40->idxbuf_format) { +		nv40->dirty |= NV40_NEW_ARRAYS; +		nv40->idxbuf = ib; +		nv40->idxbuf_format = type; +	} + +	return TRUE; +} + +static boolean +nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so, +		       int attrib, struct pipe_vertex_element *ve, +		       struct pipe_vertex_buffer *vb) +{ +	struct pipe_winsys *ws = nv40->pipe.winsys; +	struct nouveau_grobj *curie = nv40->screen->curie; +	unsigned type, ncomp; +	void *map; + +	if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) +		return FALSE; + +	map  = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); +	map += vb->buffer_offset + ve->src_offset; + +	switch (type) { +	case NV40TCL_VTXFMT_TYPE_FLOAT: +	{ +		float *v = map; + +		switch (ncomp) { +		case 4: +			so_method(so, curie, NV40TCL_VTX_ATTR_4F_X(attrib), 4); +			so_data  (so, fui(v[0])); +			so_data  (so, fui(v[1])); +			so_data  (so, fui(v[2])); +			so_data  (so, fui(v[3])); +			break; +		case 3: +			so_method(so, curie, NV40TCL_VTX_ATTR_3F_X(attrib), 3); +			so_data  (so, fui(v[0])); +			so_data  (so, fui(v[1])); +			so_data  (so, fui(v[2])); +			break; +		case 2: +			so_method(so, curie, NV40TCL_VTX_ATTR_2F_X(attrib), 2); +			so_data  (so, fui(v[0])); +			so_data  (so, fui(v[1])); +			break; +		case 1: +			so_method(so, curie, NV40TCL_VTX_ATTR_1F(attrib), 1); +			so_data  (so, fui(v[0])); +			break; +		default: +			ws->buffer_unmap(ws, vb->buffer); +			return FALSE; +		} +	} +		break; +	default: +		ws->buffer_unmap(ws, vb->buffer); +		return FALSE; +	} + +	ws->buffer_unmap(ws, vb->buffer); + +	return TRUE; +} + +boolean +nv40_draw_arrays(struct pipe_context *pipe, +		 unsigned mode, unsigned start, unsigned count) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nouveau_channel *chan = nv40->nvws->channel; +	unsigned restart; + +	nv40_vbo_set_idxbuf(nv40, NULL, 0); +	if (FORCE_SWTNL || !nv40_state_validate(nv40)) { +		return nv40_draw_elements_swtnl(pipe, NULL, 0, +						mode, start, count); +	} + +	while (count) { +		unsigned vc, nr; + +		nv40_state_emit(nv40); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, +					mode, start, count, &restart); +		if (!vc) { +			FIRE_RING(NULL); +			continue; +		} + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		nr = (vc & 0xff); +		if (nr) { +			BEGIN_RING(curie, NV40TCL_VB_VERTEX_BATCH, 1); +			OUT_RING  (((nr - 1) << 24) | start); +			start += nr; +		} + +		nr = vc >> 8; +		while (nr) { +			unsigned push = nr > 2047 ? 2047 : nr; + +			nr -= push; + +			BEGIN_RING_NI(curie, NV40TCL_VB_VERTEX_BATCH, push); +			while (push--) { +				OUT_RING(((0x100 - 1) << 24) | start); +				start += 0x100; +			} +		} + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (0); + +		count -= vc; +		start = restart; +	} + +	pipe->flush(pipe, 0, NULL); +	return TRUE; +} + +static INLINE void +nv40_draw_elements_u08(struct nv40_context *nv40, void *ib, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nouveau_channel *chan = nv40->nvws->channel; + +	while (count) { +		uint8_t *elts = (uint8_t *)ib + start; +		unsigned vc, push, restart; + +		nv40_state_emit(nv40); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2, +					mode, start, count, &restart); +		if (vc == 0) { +			FIRE_RING(NULL); +			continue; +		} +		count -= vc; + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		if (vc & 1) { +			BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1); +			OUT_RING  (elts[0]); +			elts++; vc--; +		} + +		while (vc) { +			unsigned i; + +			push = MIN2(vc, 2047 * 2); + +			BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1); +			for (i = 0; i < push; i+=2) +				OUT_RING((elts[i+1] << 16) | elts[i]); + +			vc -= push; +			elts += push; +		} + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (0); + +		start = restart; +	} +} + +static INLINE void +nv40_draw_elements_u16(struct nv40_context *nv40, void *ib, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nouveau_channel *chan = nv40->nvws->channel; + +	while (count) { +		uint16_t *elts = (uint16_t *)ib + start; +		unsigned vc, push, restart; + +		nv40_state_emit(nv40); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2, +					mode, start, count, &restart); +		if (vc == 0) { +			FIRE_RING(NULL); +			continue; +		} +		count -= vc; + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		if (vc & 1) { +			BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1); +			OUT_RING  (elts[0]); +			elts++; vc--; +		} + +		while (vc) { +			unsigned i; + +			push = MIN2(vc, 2047 * 2); + +			BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1); +			for (i = 0; i < push; i+=2) +				OUT_RING((elts[i+1] << 16) | elts[i]); + +			vc -= push; +			elts += push; +		} + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (0); + +		start = restart; +	} +} + +static INLINE void +nv40_draw_elements_u32(struct nv40_context *nv40, void *ib, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nouveau_channel *chan = nv40->nvws->channel; + +	while (count) { +		uint32_t *elts = (uint32_t *)ib + start; +		unsigned vc, push, restart; + +		nv40_state_emit(nv40); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1, +					mode, start, count, &restart); +		if (vc == 0) { +			FIRE_RING(NULL); +			continue; +		} +		count -= vc; + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		while (vc) { +			push = MIN2(vc, 2047); + +			BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U32, push); +			OUT_RINGp    (elts, push); + +			vc -= push; +			elts += push; +		} + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (0); + +		start = restart; +	} +} + +static boolean +nv40_draw_elements_inline(struct pipe_context *pipe, +			  struct pipe_buffer *ib, unsigned ib_size, +			  unsigned mode, unsigned start, unsigned count) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct pipe_winsys *ws = pipe->winsys; +	void *map; + +	map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ); +	if (!ib) { +		NOUVEAU_ERR("failed mapping ib\n"); +		return FALSE; +	} + +	switch (ib_size) { +	case 1: +		nv40_draw_elements_u08(nv40, map, mode, start, count); +		break; +	case 2: +		nv40_draw_elements_u16(nv40, map, mode, start, count); +		break; +	case 4: +		nv40_draw_elements_u32(nv40, map, mode, start, count); +		break; +	default: +		NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); +		break; +	} + +	ws->buffer_unmap(ws, ib); +	return TRUE; +} + +static boolean +nv40_draw_elements_vbo(struct pipe_context *pipe, +		       unsigned mode, unsigned start, unsigned count) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	struct nouveau_channel *chan = nv40->nvws->channel; +	unsigned restart; + +	while (count) { +		unsigned nr, vc; + +		nv40_state_emit(nv40); + +		vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256, +					mode, start, count, &restart); +		if (!vc) { +			FIRE_RING(NULL); +			continue; +		} +		 +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (nvgl_primitive(mode)); + +		nr = (vc & 0xff); +		if (nr) { +			BEGIN_RING(curie, NV40TCL_VB_INDEX_BATCH, 1); +			OUT_RING  (((nr - 1) << 24) | start); +			start += nr; +		} + +		nr = vc >> 8; +		while (nr) { +			unsigned push = nr > 2047 ? 2047 : nr; + +			nr -= push; + +			BEGIN_RING_NI(curie, NV40TCL_VB_INDEX_BATCH, push); +			while (push--) { +				OUT_RING(((0x100 - 1) << 24) | start); +				start += 0x100; +			} +		} + +		BEGIN_RING(curie, NV40TCL_BEGIN_END, 1); +		OUT_RING  (0); + +		count -= vc; +		start = restart; +	} + +	return TRUE; +} + +boolean +nv40_draw_elements(struct pipe_context *pipe, +		   struct pipe_buffer *indexBuffer, unsigned indexSize, +		   unsigned mode, unsigned start, unsigned count) +{ +	struct nv40_context *nv40 = nv40_context(pipe); +	boolean idxbuf; + +	idxbuf = nv40_vbo_set_idxbuf(nv40, indexBuffer, indexSize); +	if (FORCE_SWTNL || !nv40_state_validate(nv40)) { +		return nv40_draw_elements_swtnl(pipe, NULL, 0, +						mode, start, count); +	} + +	if (idxbuf) { +		nv40_draw_elements_vbo(pipe, mode, start, count); +	} else { +		nv40_draw_elements_inline(pipe, indexBuffer, indexSize, +					  mode, start, count); +	} + +	pipe->flush(pipe, 0, NULL); +	return TRUE; +} + +static boolean +nv40_vbo_validate(struct nv40_context *nv40) +{ +	struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; +	struct nouveau_grobj *curie = nv40->screen->curie; +	struct pipe_buffer *ib = nv40->idxbuf; +	unsigned ib_format = nv40->idxbuf_format; +	unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; +	int hw; + +	if (nv40->edgeflags) { +		nv40->fallback_swtnl |= NV40_NEW_ARRAYS; +		return FALSE; +	} + +	vtxbuf = so_new(20, 18); +	so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt_nr); +	vtxfmt = so_new(17, 0); +	so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt_nr); + +	for (hw = 0; hw < nv40->vtxelt_nr; hw++) { +		struct pipe_vertex_element *ve; +		struct pipe_vertex_buffer *vb; +		unsigned type, ncomp; + +		ve = &nv40->vtxelt[hw]; +		vb = &nv40->vtxbuf[ve->vertex_buffer_index]; + +		if (!vb->pitch) { +			if (!sattr) +				sattr = so_new(16 * 5, 0); + +			if (nv40_vbo_static_attrib(nv40, sattr, hw, ve, vb)) { +				so_data(vtxbuf, 0); +				so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT); +				continue; +			} +		} + +		if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { +			nv40->fallback_swtnl |= NV40_NEW_ARRAYS; +			so_ref(NULL, &vtxbuf); +			so_ref(NULL, &vtxfmt); +			return FALSE; +		} + +		so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset, +			 vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, +			 0, NV40TCL_VTXBUF_ADDRESS_DMA1); +		so_data (vtxfmt, ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) | +				  (ncomp << NV40TCL_VTXFMT_SIZE_SHIFT) | type)); +	} + +	if (ib) { +		so_method(vtxbuf, curie, NV40TCL_IDXBUF_ADDRESS, 2); +		so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); +		so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR, +			  0, NV40TCL_IDXBUF_FORMAT_DMA1); +	} + +	so_method(vtxbuf, curie, 0x1710, 1); +	so_data  (vtxbuf, 0); + +	so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]); +	nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF); +	so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]); +	nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT); +	so_ref(sattr, &nv40->state.hw[NV40_STATE_VTXATTR]); +	nv40->state.dirty |= (1ULL << NV40_STATE_VTXATTR); +	return FALSE; +} + +struct nv40_state_entry nv40_state_vbo = { +	.validate = nv40_vbo_validate, +	.dirty = { +		.pipe = NV40_NEW_ARRAYS, +		.hw = 0, +	} +}; + diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c new file mode 100644 index 0000000000..ff988e6a5f --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_vertprog.c @@ -0,0 +1,1070 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" + +#include "nv40_context.h" +#include "nv40_state.h" + +/* TODO (at least...): + *  1. Indexed consts  + ARL + *  3. NV_vp11, NV_vp2, NV_vp3 features + *       - extra arith opcodes + *       - branching + *       - texture sampling + *       - indexed attribs + *       - indexed results + *  4. bugs + */ + +#define SWZ_X 0 +#define SWZ_Y 1 +#define SWZ_Z 2 +#define SWZ_W 3 +#define MASK_X 8 +#define MASK_Y 4 +#define MASK_Z 2 +#define MASK_W 1 +#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) +#define DEF_SCALE 0 +#define DEF_CTEST 0 +#include "nv40_shader.h" + +#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) +#define neg(s) nv40_sr_neg((s)) +#define abs(s) nv40_sr_abs((s)) + +#define NV40_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n)) + +struct nv40_vpc { +	struct nv40_vertex_program *vp; + +	struct nv40_vertex_program_exec *vpi; + +	unsigned r_temps; +	unsigned r_temps_discard; +	struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; +	struct nv40_sreg *r_address; +	struct nv40_sreg *r_temp; + +	struct nv40_sreg *imm; +	unsigned nr_imm; + +	unsigned hpos_idx; +}; + +static struct nv40_sreg +temp(struct nv40_vpc *vpc) +{ +	int idx = ffs(~vpc->r_temps) - 1; + +	if (idx < 0) { +		NOUVEAU_ERR("out of temps!!\n"); +		assert(0); +		return nv40_sr(NV40SR_TEMP, 0); +	} + +	vpc->r_temps |= (1 << idx); +	vpc->r_temps_discard |= (1 << idx); +	return nv40_sr(NV40SR_TEMP, idx); +} + +static INLINE void +release_temps(struct nv40_vpc *vpc) +{ +	vpc->r_temps &= ~vpc->r_temps_discard; +	vpc->r_temps_discard = 0; +} + +static struct nv40_sreg +constant(struct nv40_vpc *vpc, int pipe, float x, float y, float z, float w) +{ +	struct nv40_vertex_program *vp = vpc->vp; +	struct nv40_vertex_program_data *vpd; +	int idx; + +	if (pipe >= 0) { +		for (idx = 0; idx < vp->nr_consts; idx++) { +			if (vp->consts[idx].index == pipe) +				return nv40_sr(NV40SR_CONST, idx); +		} +	} + +	idx = vp->nr_consts++; +	vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); +	vpd = &vp->consts[idx]; + +	vpd->index = pipe; +	vpd->value[0] = x; +	vpd->value[1] = y; +	vpd->value[2] = z; +	vpd->value[3] = w; +	return nv40_sr(NV40SR_CONST, idx); +} + +#define arith(cc,s,o,d,m,s0,s1,s2) \ +	nv40_vp_arith((cc), (s), NV40_VP_INST_##o, (d), (m), (s0), (s1), (s2)) + +static void +emit_src(struct nv40_vpc *vpc, uint32_t *hw, int pos, struct nv40_sreg src) +{ +	struct nv40_vertex_program *vp = vpc->vp; +	uint32_t sr = 0; + +	switch (src.type) { +	case NV40SR_TEMP: +		sr |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT); +		sr |= (src.index << NV40_VP_SRC_TEMP_SRC_SHIFT); +		break; +	case NV40SR_INPUT: +		sr |= (NV40_VP_SRC_REG_TYPE_INPUT << +		       NV40_VP_SRC_REG_TYPE_SHIFT); +		vp->ir |= (1 << src.index); +		hw[1] |= (src.index << NV40_VP_INST_INPUT_SRC_SHIFT); +		break; +	case NV40SR_CONST: +		sr |= (NV40_VP_SRC_REG_TYPE_CONST << +		       NV40_VP_SRC_REG_TYPE_SHIFT); +		assert(vpc->vpi->const_index == -1 || +		       vpc->vpi->const_index == src.index); +		vpc->vpi->const_index = src.index; +		break; +	case NV40SR_NONE: +		sr |= (NV40_VP_SRC_REG_TYPE_INPUT << +		       NV40_VP_SRC_REG_TYPE_SHIFT); +		break; +	default: +		assert(0); +	} + +	if (src.negate) +		sr |= NV40_VP_SRC_NEGATE; + +	if (src.abs) +		hw[0] |= (1 << (21 + pos)); + +	sr |= ((src.swz[0] << NV40_VP_SRC_SWZ_X_SHIFT) | +	       (src.swz[1] << NV40_VP_SRC_SWZ_Y_SHIFT) | +	       (src.swz[2] << NV40_VP_SRC_SWZ_Z_SHIFT) | +	       (src.swz[3] << NV40_VP_SRC_SWZ_W_SHIFT)); + +	switch (pos) { +	case 0: +		hw[1] |= ((sr & NV40_VP_SRC0_HIGH_MASK) >> +			  NV40_VP_SRC0_HIGH_SHIFT) << NV40_VP_INST_SRC0H_SHIFT; +		hw[2] |= (sr & NV40_VP_SRC0_LOW_MASK) << +			  NV40_VP_INST_SRC0L_SHIFT; +		break; +	case 1: +		hw[2] |= sr << NV40_VP_INST_SRC1_SHIFT; +		break; +	case 2: +		hw[2] |= ((sr & NV40_VP_SRC2_HIGH_MASK) >> +			  NV40_VP_SRC2_HIGH_SHIFT) << NV40_VP_INST_SRC2H_SHIFT; +		hw[3] |= (sr & NV40_VP_SRC2_LOW_MASK) << +			  NV40_VP_INST_SRC2L_SHIFT; +		break; +	default: +		assert(0); +	} +} + +static void +emit_dst(struct nv40_vpc *vpc, uint32_t *hw, int slot, struct nv40_sreg dst) +{ +	struct nv40_vertex_program *vp = vpc->vp; + +	switch (dst.type) { +	case NV40SR_TEMP: +		hw[3] |= NV40_VP_INST_DEST_MASK; +		if (slot == 0) { +			hw[0] |= (dst.index << +				  NV40_VP_INST_VEC_DEST_TEMP_SHIFT); +		} else { +			hw[3] |= (dst.index <<  +				  NV40_VP_INST_SCA_DEST_TEMP_SHIFT); +		} +		break; +	case NV40SR_OUTPUT: +		switch (dst.index) { +		case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; +		case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; +		case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; +		case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; +		case NV40_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; +		case NV40_VP_INST_DEST_PSZ  : vp->or |= (1 << 5); break; +		case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; +		case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; +		case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; +		case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; +		case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; +		case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; +		case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; +		case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; +		case NV40_VP_INST_DEST_CLIP(0): +			vp->or |= (1 << 6); +			vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE0; +			dst.index = NV40_VP_INST_DEST_FOGC; +			break; +		case NV40_VP_INST_DEST_CLIP(1): +			vp->or |= (1 << 7); +			vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE1; +			dst.index = NV40_VP_INST_DEST_FOGC; +			break; +		case NV40_VP_INST_DEST_CLIP(2): +			vp->or |= (1 << 8); +			vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE2; +			dst.index = NV40_VP_INST_DEST_FOGC; +			break; +		case NV40_VP_INST_DEST_CLIP(3): +			vp->or |= (1 << 9); +			vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE3; +			dst.index = NV40_VP_INST_DEST_PSZ; +			break; +		case NV40_VP_INST_DEST_CLIP(4): +			vp->or |= (1 << 10); +			vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE4; +			dst.index = NV40_VP_INST_DEST_PSZ; +			break; +		case NV40_VP_INST_DEST_CLIP(5): +			vp->or |= (1 << 11); +			vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE5; +			dst.index = NV40_VP_INST_DEST_PSZ; +			break; +		default: +			break; +		} + +		hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT); +		if (slot == 0) { +			hw[0] |= NV40_VP_INST_VEC_RESULT; +			hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); +		} else { +			hw[3] |= NV40_VP_INST_SCA_RESULT; +			hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; +		} +		break; +	default: +		assert(0); +	} +} + +static void +nv40_vp_arith(struct nv40_vpc *vpc, int slot, int op, +	      struct nv40_sreg dst, int mask, +	      struct nv40_sreg s0, struct nv40_sreg s1, +	      struct nv40_sreg s2) +{ +	struct nv40_vertex_program *vp = vpc->vp; +	uint32_t *hw; + +	vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); +	vpc->vpi = &vp->insns[vp->nr_insns - 1]; +	memset(vpc->vpi, 0, sizeof(*vpc->vpi)); +	vpc->vpi->const_index = -1; + +	hw = vpc->vpi->data; + +	hw[0] |= (NV40_VP_INST_COND_TR << NV40_VP_INST_COND_SHIFT); +	hw[0] |= ((0 << NV40_VP_INST_COND_SWZ_X_SHIFT) | +		  (1 << NV40_VP_INST_COND_SWZ_Y_SHIFT) | +		  (2 << NV40_VP_INST_COND_SWZ_Z_SHIFT) | +		  (3 << NV40_VP_INST_COND_SWZ_W_SHIFT)); + +	if (slot == 0) { +		hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT); +		hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; +		hw[3] |= (mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT); +	} else { +		hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT); +		hw[0] |= (NV40_VP_INST_VEC_DEST_TEMP_MASK | (1 << 20)); +		hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT); +	} + +	emit_dst(vpc, hw, slot, dst); +	emit_src(vpc, hw, 0, s0); +	emit_src(vpc, hw, 1, s1); +	emit_src(vpc, hw, 2, s2); +} + +static INLINE struct nv40_sreg +tgsi_src(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc) { +	struct nv40_sreg src; + +	switch (fsrc->SrcRegister.File) { +	case TGSI_FILE_INPUT: +		src = nv40_sr(NV40SR_INPUT, fsrc->SrcRegister.Index); +		break; +	case TGSI_FILE_CONSTANT: +		src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0); +		break; +	case TGSI_FILE_IMMEDIATE: +		src = vpc->imm[fsrc->SrcRegister.Index]; +		break; +	case TGSI_FILE_TEMPORARY: +		src = vpc->r_temp[fsrc->SrcRegister.Index]; +		break; +	default: +		NOUVEAU_ERR("bad src file\n"); +		break; +	} + +	src.abs = fsrc->SrcRegisterExtMod.Absolute; +	src.negate = fsrc->SrcRegister.Negate; +	src.swz[0] = fsrc->SrcRegister.SwizzleX; +	src.swz[1] = fsrc->SrcRegister.SwizzleY; +	src.swz[2] = fsrc->SrcRegister.SwizzleZ; +	src.swz[3] = fsrc->SrcRegister.SwizzleW; +	return src; +} + +static INLINE struct nv40_sreg +tgsi_dst(struct nv40_vpc *vpc, const struct tgsi_full_dst_register *fdst) { +	struct nv40_sreg dst; + +	switch (fdst->DstRegister.File) { +	case TGSI_FILE_OUTPUT: +		dst = vpc->r_result[fdst->DstRegister.Index]; +		break; +	case TGSI_FILE_TEMPORARY: +		dst = vpc->r_temp[fdst->DstRegister.Index]; +		break; +	case TGSI_FILE_ADDRESS: +		dst = vpc->r_address[fdst->DstRegister.Index]; +		break; +	default: +		NOUVEAU_ERR("bad dst file\n"); +		break; +	} + +	return dst; +} + +static INLINE int +tgsi_mask(uint tgsi) +{ +	int mask = 0; + +	if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; +	if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; +	if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; +	if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; +	return mask; +} + +static boolean +src_native_swz(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc, +	       struct nv40_sreg *src) +{ +	const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); +	struct nv40_sreg tgsi = tgsi_src(vpc, fsrc); +	uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0; +	uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX, +			fsrc->SrcRegisterExtSwz.NegateY, +			fsrc->SrcRegisterExtSwz.NegateZ, +			fsrc->SrcRegisterExtSwz.NegateW }; +	uint c; + +	for (c = 0; c < 4; c++) { +		switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) { +		case TGSI_EXTSWIZZLE_X: +		case TGSI_EXTSWIZZLE_Y: +		case TGSI_EXTSWIZZLE_Z: +		case TGSI_EXTSWIZZLE_W: +			mask |= tgsi_mask(1 << c); +			break; +		case TGSI_EXTSWIZZLE_ZERO: +			zero_mask |= tgsi_mask(1 << c); +			tgsi.swz[c] = SWZ_X; +			break; +		case TGSI_EXTSWIZZLE_ONE: +			one_mask |= tgsi_mask(1 << c); +			tgsi.swz[c] = SWZ_X; +			break; +		default: +			assert(0); +		} + +		if (!tgsi.negate && neg[c]) +			neg_mask |= tgsi_mask(1 << c); +	} + +	if (mask == MASK_ALL && !neg_mask) +		return TRUE; + +	*src = temp(vpc); + +	if (mask) +		arith(vpc, 0, OP_MOV, *src, mask, tgsi, none, none); + +	if (zero_mask) +		arith(vpc, 0, OP_SFL, *src, zero_mask, *src, none, none); + +	if (one_mask) +		arith(vpc, 0, OP_STR, *src, one_mask, *src, none, none); + +	if (neg_mask) { +		struct nv40_sreg one = temp(vpc); +		arith(vpc, 0, OP_STR, one, neg_mask, one, none, none); +		arith(vpc, 0, OP_MUL, *src, neg_mask, *src, neg(one), none); +	} + +	return FALSE; +} + +static boolean +nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, +				const struct tgsi_full_instruction *finst) +{ +	struct nv40_sreg src[3], dst, tmp; +	struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); +	int mask; +	int ai = -1, ci = -1, ii = -1; +	int i; + +	if (finst->Instruction.Opcode == TGSI_OPCODE_END) +		return TRUE; + +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; +		if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) { +			src[i] = tgsi_src(vpc, fsrc); +		} +	} + +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; + +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +		case TGSI_FILE_CONSTANT: +		case TGSI_FILE_TEMPORARY: +			if (!src_native_swz(vpc, fsrc, &src[i])) +				continue; +			break; +		default: +			break; +		} + +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +			if (ai == -1 || ai == fsrc->SrcRegister.Index) { +				ai = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(vpc, fsrc); +			} else { +				src[i] = temp(vpc); +				arith(vpc, 0, OP_MOV, src[i], MASK_ALL, +				      tgsi_src(vpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_CONSTANT: +			if ((ci == -1 && ii == -1) || +			    ci == fsrc->SrcRegister.Index) { +				ci = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(vpc, fsrc); +			} else { +				src[i] = temp(vpc); +				arith(vpc, 0, OP_MOV, src[i], MASK_ALL, +				      tgsi_src(vpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_IMMEDIATE: +			if ((ci == -1 && ii == -1) || +			    ii == fsrc->SrcRegister.Index) { +				ii = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(vpc, fsrc); +			} else { +				src[i] = temp(vpc); +				arith(vpc, 0, OP_MOV, src[i], MASK_ALL, +				      tgsi_src(vpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_TEMPORARY: +			/* handled above */ +			break; +		default: +			NOUVEAU_ERR("bad src file\n"); +			return FALSE; +		} +	} + +	dst  = tgsi_dst(vpc, &finst->FullDstRegisters[0]); +	mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask); + +	switch (finst->Instruction.Opcode) { +	case TGSI_OPCODE_ABS: +		arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); +		break; +	case TGSI_OPCODE_ADD: +		arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); +		break; +	case TGSI_OPCODE_ARL: +		arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_DP3: +		arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DP4: +		arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DPH: +		arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DST: +		arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_EX2: +		arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_EXP: +		arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_FLR: +		arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_FRC: +		arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_LG2: +		arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_LIT: +		arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_LOG: +		arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_MAD: +		arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); +		break; +	case TGSI_OPCODE_MAX: +		arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MIN: +		arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MOV: +		arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_MUL: +		arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_POW: +		tmp = temp(vpc); +		arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, +		      swz(src[0], X, X, X, X)); +		arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), +		      swz(src[1], X, X, X, X), none); +		arith(vpc, 1, OP_EX2, dst, mask, none, none, +		      swz(tmp, X, X, X, X)); +		break; +	case TGSI_OPCODE_RCP: +		arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_RET: +		break; +	case TGSI_OPCODE_RSQ: +		arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_SGE: +		arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SLT: +		arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SUB: +		arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); +		break; +	case TGSI_OPCODE_XPD: +		tmp = temp(vpc); +		arith(vpc, 0, OP_MUL, tmp, mask, +		      swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); +		arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), +		      swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), +		      neg(tmp)); +		break; +	default: +		NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); +		return FALSE; +	} + +	release_temps(vpc); +	return TRUE; +} + +static boolean +nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc, +				const struct tgsi_full_declaration *fdec) +{ +	unsigned idx = fdec->DeclarationRange.First; +	int hw; + +	switch (fdec->Semantic.SemanticName) { +	case TGSI_SEMANTIC_POSITION: +		hw = NV40_VP_INST_DEST_POS; +		vpc->hpos_idx = idx; +		break; +	case TGSI_SEMANTIC_COLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV40_VP_INST_DEST_COL0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV40_VP_INST_DEST_COL1; +		} else { +			NOUVEAU_ERR("bad colour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_BCOLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV40_VP_INST_DEST_BFC0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV40_VP_INST_DEST_BFC1; +		} else { +			NOUVEAU_ERR("bad bcolour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_FOG: +		hw = NV40_VP_INST_DEST_FOGC; +		break; +	case TGSI_SEMANTIC_PSIZE: +		hw = NV40_VP_INST_DEST_PSZ; +		break; +	case TGSI_SEMANTIC_GENERIC: +		if (fdec->Semantic.SemanticIndex <= 7) { +			hw = NV40_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex); +		} else { +			NOUVEAU_ERR("bad generic semantic index\n"); +			return FALSE; +		} +		break; +	default: +		NOUVEAU_ERR("bad output semantic\n"); +		return FALSE; +	} + +	vpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw); +	return TRUE; +} + +static boolean +nv40_vertprog_prepare(struct nv40_vpc *vpc) +{ +	struct tgsi_parse_context p; +	int high_temp = -1, high_addr = -1, nr_imm = 0, i; + +	tgsi_parse_init(&p, vpc->vp->pipe.tokens); +	while (!tgsi_parse_end_of_tokens(&p)) { +		const union tgsi_full_token *tok = &p.FullToken; + +		tgsi_parse_token(&p); +		switch(tok->Token.Type) { +		case TGSI_TOKEN_TYPE_IMMEDIATE: +			nr_imm++; +			break; +		case TGSI_TOKEN_TYPE_DECLARATION: +		{ +			const struct tgsi_full_declaration *fdec; + +			fdec = &p.FullToken.FullDeclaration; +			switch (fdec->Declaration.File) { +			case TGSI_FILE_TEMPORARY: +				if (fdec->DeclarationRange.Last > high_temp) { +					high_temp = +						fdec->DeclarationRange.Last; +				} +				break; +#if 0 /* this would be nice.. except gallium doesn't track it */ +			case TGSI_FILE_ADDRESS: +				if (fdec->DeclarationRange.Last > high_addr) { +					high_addr = +						fdec->DeclarationRange.Last; +				} +				break; +#endif +			case TGSI_FILE_OUTPUT: +				if (!nv40_vertprog_parse_decl_output(vpc, fdec)) +					return FALSE; +				break; +			default: +				break; +			} +		} +			break; +#if 1 /* yay, parse instructions looking for address regs instead */ +		case TGSI_TOKEN_TYPE_INSTRUCTION: +		{ +			const struct tgsi_full_instruction *finst; +			const struct tgsi_full_dst_register *fdst; + +			finst = &p.FullToken.FullInstruction; +			fdst = &finst->FullDstRegisters[0]; + +			if (fdst->DstRegister.File == TGSI_FILE_ADDRESS) { +				if (fdst->DstRegister.Index > high_addr) +					high_addr = fdst->DstRegister.Index; +			} +		 +		} +			break; +#endif +		default: +			break; +		} +	} +	tgsi_parse_free(&p); + +	if (nr_imm) { +		vpc->imm = CALLOC(nr_imm, sizeof(struct nv40_sreg)); +		assert(vpc->imm); +	} + +	if (++high_temp) { +		vpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg)); +		for (i = 0; i < high_temp; i++) +			vpc->r_temp[i] = temp(vpc); +	} + +	if (++high_addr) { +		vpc->r_address = CALLOC(high_addr, sizeof(struct nv40_sreg)); +		for (i = 0; i < high_addr; i++) +			vpc->r_address[i] = temp(vpc); +	} + +	vpc->r_temps_discard = 0; +	return TRUE; +} + +static void +nv40_vertprog_translate(struct nv40_context *nv40, +			struct nv40_vertex_program *vp) +{ +	struct tgsi_parse_context parse; +	struct nv40_vpc *vpc = NULL; +	struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); +	int i; + +	vpc = CALLOC(1, sizeof(struct nv40_vpc)); +	if (!vpc) +		return; +	vpc->vp = vp; + +	if (!nv40_vertprog_prepare(vpc)) { +		FREE(vpc); +		return; +	} + +	/* Redirect post-transform vertex position to a temp if user clip +	 * planes are enabled.  We need to append code the the vtxprog +	 * to handle clip planes later. +	 */ +	if (vp->ucp.nr)  { +		vpc->r_result[vpc->hpos_idx] = temp(vpc); +		vpc->r_temps_discard = 0; +	} + +	tgsi_parse_init(&parse, vp->pipe.tokens); + +	while (!tgsi_parse_end_of_tokens(&parse)) { +		tgsi_parse_token(&parse); + +		switch (parse.FullToken.Token.Type) { +		case TGSI_TOKEN_TYPE_IMMEDIATE: +		{ +			const struct tgsi_full_immediate *imm; + +			imm = &parse.FullToken.FullImmediate; +			assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); +//			assert(imm->Immediate.Size == 4); +			vpc->imm[vpc->nr_imm++] = +				constant(vpc, -1, +					 imm->u.ImmediateFloat32[0].Float, +					 imm->u.ImmediateFloat32[1].Float, +					 imm->u.ImmediateFloat32[2].Float, +					 imm->u.ImmediateFloat32[3].Float); +		} +			break; +		case TGSI_TOKEN_TYPE_INSTRUCTION: +		{ +			const struct tgsi_full_instruction *finst; +			finst = &parse.FullToken.FullInstruction; +			if (!nv40_vertprog_parse_instruction(vpc, finst)) +				goto out_err; +		} +			break; +		default: +			break; +		} +	} + +	/* Write out HPOS if it was redirected to a temp earlier */ +	if (vpc->r_result[vpc->hpos_idx].type != NV40SR_OUTPUT) { +		struct nv40_sreg hpos = nv40_sr(NV40SR_OUTPUT, +						NV40_VP_INST_DEST_POS); +		struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx]; + +		arith(vpc, 0, OP_MOV, hpos, MASK_ALL, htmp, none, none); +	} + +	/* Insert code to handle user clip planes */ +	for (i = 0; i < vp->ucp.nr; i++) { +		struct nv40_sreg cdst = nv40_sr(NV40SR_OUTPUT, +						NV40_VP_INST_DEST_CLIP(i)); +		struct nv40_sreg ceqn = constant(vpc, -1, +						 nv40->clip.ucp[i][0], +						 nv40->clip.ucp[i][1], +						 nv40->clip.ucp[i][2], +						 nv40->clip.ucp[i][3]); +		struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx]; +		unsigned mask; + +		switch (i) { +		case 0: case 3: mask = MASK_Y; break; +		case 1: case 4: mask = MASK_Z; break; +		case 2: case 5: mask = MASK_W; break; +		default: +			NOUVEAU_ERR("invalid clip dist #%d\n", i); +			goto out_err; +		} + +		arith(vpc, 0, OP_DP4, cdst, mask, htmp, ceqn, none); +	} + +	vp->insns[vp->nr_insns - 1].data[3] |= NV40_VP_INST_LAST; +	vp->translated = TRUE; +out_err: +	tgsi_parse_free(&parse); +	if (vpc->r_temp) +		FREE(vpc->r_temp);  +	if (vpc->r_address) +		FREE(vpc->r_address);  +	if (vpc->imm)	 +		FREE(vpc->imm);  +	FREE(vpc); +} + +static boolean +nv40_vertprog_validate(struct nv40_context *nv40) +{  +	struct nouveau_winsys *nvws = nv40->nvws; +	struct pipe_winsys *ws = nv40->pipe.winsys; +	struct nouveau_grobj *curie = nv40->screen->curie; +	struct nv40_vertex_program *vp; +	struct pipe_buffer *constbuf; +	boolean upload_code = FALSE, upload_data = FALSE; +	int i; + +	if (nv40->render_mode == HW) { +		vp = nv40->vertprog; +		constbuf = nv40->constbuf[PIPE_SHADER_VERTEX]; + +		if ((nv40->dirty & NV40_NEW_UCP) || +		    memcmp(&nv40->clip, &vp->ucp, sizeof(vp->ucp))) { +			nv40_vertprog_destroy(nv40, vp); +			memcpy(&vp->ucp, &nv40->clip, sizeof(vp->ucp)); +		} +	} else { +		vp = nv40->swtnl.vertprog; +		constbuf = NULL; +	} + +	/* Translate TGSI shader into hw bytecode */ +	if (vp->translated) +		goto check_gpu_resources; + +	nv40->fallback_swtnl &= ~NV40_NEW_VERTPROG; +	nv40_vertprog_translate(nv40, vp); +	if (!vp->translated) { +		nv40->fallback_swtnl |= NV40_NEW_VERTPROG; +		return FALSE; +	} + +check_gpu_resources: +	/* Allocate hw vtxprog exec slots */ +	if (!vp->exec) { +		struct nouveau_resource *heap = nv40->screen->vp_exec_heap; +		struct nouveau_stateobj *so; +		uint vplen = vp->nr_insns; + +		if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) { +			while (heap->next && heap->size < vplen) { +				struct nv40_vertex_program *evict; +				 +				evict = heap->next->priv; +				nvws->res_free(&evict->exec); +			} + +			if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) +				assert(0); +		} + +		so = so_new(7, 0); +		so_method(so, curie, NV40TCL_VP_START_FROM_ID, 1); +		so_data  (so, vp->exec->start); +		so_method(so, curie, NV40TCL_VP_ATTRIB_EN, 2); +		so_data  (so, vp->ir); +		so_data  (so, vp->or); +		so_method(so, curie,  NV40TCL_CLIP_PLANE_ENABLE, 1); +		so_data  (so, vp->clip_ctrl); +		so_ref(so, &vp->so); + +		upload_code = TRUE; +	} + +	/* Allocate hw vtxprog const slots */ +	if (vp->nr_consts && !vp->data) { +		struct nouveau_resource *heap = nv40->screen->vp_data_heap; + +		if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) { +			while (heap->next && heap->size < vp->nr_consts) { +				struct nv40_vertex_program *evict; +				 +				evict = heap->next->priv; +				nvws->res_free(&evict->data); +			} + +			if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) +				assert(0); +		} + +		/*XXX: handle this some day */ +		assert(vp->data->start >= vp->data_start_min); + +		upload_data = TRUE; +		if (vp->data_start != vp->data->start) +			upload_code = TRUE; +	} + +	/* If exec or data segments moved we need to patch the program to +	 * fixup offsets and register IDs. +	 */ +	if (vp->exec_start != vp->exec->start) { +		for (i = 0; i < vp->nr_insns; i++) { +			struct nv40_vertex_program_exec *vpi = &vp->insns[i]; + +			if (vpi->has_branch_offset) { +				assert(0); +			} +		} + +		vp->exec_start = vp->exec->start; +	} + +	if (vp->nr_consts && vp->data_start != vp->data->start) { +		for (i = 0; i < vp->nr_insns; i++) { +			struct nv40_vertex_program_exec *vpi = &vp->insns[i]; + +			if (vpi->const_index >= 0) { +				vpi->data[1] &= ~NV40_VP_INST_CONST_SRC_MASK; +				vpi->data[1] |= +					(vpi->const_index + vp->data->start) << +					NV40_VP_INST_CONST_SRC_SHIFT; + +			} +		} + +		vp->data_start = vp->data->start; +	} + +	/* Update + Upload constant values */ +	if (vp->nr_consts) { +		float *map = NULL; + +		if (constbuf) { +			map = ws->buffer_map(ws, constbuf, +					     PIPE_BUFFER_USAGE_CPU_READ); +		} + +		for (i = 0; i < vp->nr_consts; i++) { +			struct nv40_vertex_program_data *vpd = &vp->consts[i]; + +			if (vpd->index >= 0) { +				if (!upload_data && +				    !memcmp(vpd->value, &map[vpd->index * 4], +					    4 * sizeof(float))) +					continue; +				memcpy(vpd->value, &map[vpd->index * 4], +				       4 * sizeof(float)); +			} + +			BEGIN_RING(curie, NV40TCL_VP_UPLOAD_CONST_ID, 5); +			OUT_RING  (i + vp->data->start); +			OUT_RINGp ((uint32_t *)vpd->value, 4); +		} + +		if (constbuf) +			ws->buffer_unmap(ws, constbuf); +	} + +	/* Upload vtxprog */ +	if (upload_code) { +#if 0 +		for (i = 0; i < vp->nr_insns; i++) { +			NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[0]); +			NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[1]); +			NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[2]); +			NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[3]); +		} +#endif +		BEGIN_RING(curie, NV40TCL_VP_UPLOAD_FROM_ID, 1); +		OUT_RING  (vp->exec->start); +		for (i = 0; i < vp->nr_insns; i++) { +			BEGIN_RING(curie, NV40TCL_VP_UPLOAD_INST(0), 4); +			OUT_RINGp (vp->insns[i].data, 4); +		} +	} + +	if (vp->so != nv40->state.hw[NV40_STATE_VERTPROG]) { +		so_ref(vp->so, &nv40->state.hw[NV40_STATE_VERTPROG]); +		return TRUE; +	} + +	return FALSE; +} + +void +nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp) +{ +	struct nouveau_winsys *nvws = nv40->screen->nvws; + +	vp->translated = FALSE; + +	if (vp->nr_insns) { +		FREE(vp->insns); +		vp->insns = NULL; +		vp->nr_insns = 0; +	} + +	if (vp->nr_consts) { +		FREE(vp->consts); +		vp->consts = NULL; +		vp->nr_consts = 0; +	} + +	nvws->res_free(&vp->exec); +	vp->exec_start = 0; +	nvws->res_free(&vp->data); +	vp->data_start = 0; +	vp->data_start_min = 0; + +	vp->ir = vp->or = vp->clip_ctrl = 0; +	so_ref(NULL, &vp->so); +} + +struct nv40_state_entry nv40_state_vertprog = { +	.validate = nv40_vertprog_validate, +	.dirty = { +		.pipe = NV40_NEW_VERTPROG | NV40_NEW_UCP, +		.hw = NV40_STATE_VERTPROG, +	} +}; + diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile new file mode 100644 index 0000000000..be30400c03 --- /dev/null +++ b/src/gallium/drivers/nv50/Makefile @@ -0,0 +1,29 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nv50 + +DRIVER_SOURCES = \ +	nv50_clear.c \ +	nv50_context.c \ +	nv50_draw.c \ +	nv50_miptree.c \ +	nv50_query.c \ +	nv50_program.c \ +	nv50_screen.c \ +	nv50_state.c \ +	nv50_state_validate.c \ +	nv50_surface.c \ +	nv50_tex.c \ +	nv50_vbo.c + +C_SOURCES = \ +	$(COMMON_SOURCES) \ +	$(DRIVER_SOURCES) + +ASM_SOURCES =  + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c new file mode 100644 index 0000000000..fbc6cd09ce --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_clear.c @@ -0,0 +1,35 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "nv50_context.h" + +void +nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps, +	   unsigned clearValue) +{ +	pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); +	ps->status = PIPE_SURFACE_STATUS_CLEAR; +} diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c new file mode 100644 index 0000000000..07987c7d02 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -0,0 +1,91 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" +#include "pipe/p_util.h" + +#include "nv50_context.h" +#include "nv50_screen.h" + +static void +nv50_flush(struct pipe_context *pipe, unsigned flags, +	   struct pipe_fence_handle **fence) +{ +	struct nv50_context *nv50 = (struct nv50_context *)pipe; +	 +	FIRE_RING(fence); +} + +static void +nv50_destroy(struct pipe_context *pipe) +{ +	struct nv50_context *nv50 = (struct nv50_context *)pipe; + +	draw_destroy(nv50->draw); +	FREE(nv50); +} + + +static void +nv50_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) +{ +} + +struct pipe_context * +nv50_create(struct pipe_screen *pscreen, unsigned pctx_id) +{ +	struct pipe_winsys *pipe_winsys = pscreen->winsys; +	struct nv50_screen *screen = nv50_screen(pscreen); +	struct nv50_context *nv50; + +	nv50 = CALLOC_STRUCT(nv50_context); +	if (!nv50) +		return NULL; +	nv50->screen = screen; +	nv50->pctx_id = pctx_id; + +	nv50->pipe.winsys = pipe_winsys; +	nv50->pipe.screen = pscreen; + +	nv50->pipe.destroy = nv50_destroy; + +	nv50->pipe.set_edgeflags = nv50_set_edgeflags; +	nv50->pipe.draw_arrays = nv50_draw_arrays; +	nv50->pipe.draw_elements = nv50_draw_elements; +	nv50->pipe.clear = nv50_clear; + +	nv50->pipe.flush = nv50_flush; + +	nv50_init_surface_functions(nv50); +	nv50_init_state_functions(nv50); +	nv50_init_query_functions(nv50); + +	nv50->draw = draw_create(); +	assert(nv50->draw); +	draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50)); + +	return &nv50->pipe; +} + +		 diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h new file mode 100644 index 0000000000..1c069f1625 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -0,0 +1,181 @@ +#ifndef __NV50_CONTEXT_H__ +#define __NV50_CONTEXT_H__ + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" +#include "nouveau/nouveau_stateobj.h" + +#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \ +	struct nv50_screen *ctx = nv50->screen +#include "nouveau/nouveau_push.h" + +#include "nv50_screen.h" +#include "nv50_program.h" + +#define NOUVEAU_ERR(fmt, args...) \ +	fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ +	fprintf(stderr, "nouveau: "fmt, ##args); + +/* Constant buffer assignment */ +#define NV50_CB_PMISC		0 +#define NV50_CB_PVP		1 +#define NV50_CB_PFP		2 +#define NV50_CB_PGP		3 +#define NV50_CB_TIC		4 +#define NV50_CB_TSC		5 +#define NV50_CB_PUPLOAD         6 + +#define NV50_NEW_BLEND		(1 << 0) +#define NV50_NEW_ZSA		(1 << 1) +#define NV50_NEW_BLEND_COLOUR	(1 << 2) +#define NV50_NEW_STIPPLE	(1 << 3) +#define NV50_NEW_SCISSOR	(1 << 4) +#define NV50_NEW_VIEWPORT	(1 << 5) +#define NV50_NEW_RASTERIZER	(1 << 6) +#define NV50_NEW_FRAMEBUFFER	(1 << 7) +#define NV50_NEW_VERTPROG	(1 << 8) +#define NV50_NEW_VERTPROG_CB	(1 << 9) +#define NV50_NEW_FRAGPROG	(1 << 10) +#define NV50_NEW_FRAGPROG_CB	(1 << 11) +#define NV50_NEW_ARRAYS		(1 << 12) +#define NV50_NEW_SAMPLER	(1 << 13) +#define NV50_NEW_TEXTURE	(1 << 14) + +struct nv50_blend_stateobj { +	struct pipe_blend_state pipe; +	struct nouveau_stateobj *so; +}; + +struct nv50_zsa_stateobj { +	struct pipe_depth_stencil_alpha_state pipe; +	struct nouveau_stateobj *so; +}; + +struct nv50_rasterizer_stateobj { +	struct pipe_rasterizer_state pipe; +	struct nouveau_stateobj *so; +}; + +struct nv50_miptree { +	struct pipe_texture base; +	struct pipe_buffer *buffer; +}; + +static INLINE struct nv50_miptree * +nv50_miptree(struct pipe_texture *pt) +{ +	return (struct nv50_miptree *)pt; +} + +struct nv50_surface { +	struct pipe_surface base; +	struct pipe_buffer *untiled; +}; + +static INLINE struct nv50_surface * +nv50_surface(struct pipe_surface *pt) +{ +	return (struct nv50_surface *)pt; +} + +struct nv50_state { +	unsigned dirty; + +	struct nouveau_stateobj *fb; +	struct nouveau_stateobj *blend; +	struct nouveau_stateobj *blend_colour; +	struct nouveau_stateobj *zsa; +	struct nouveau_stateobj *rast; +	struct nouveau_stateobj *stipple; +	struct nouveau_stateobj *scissor; +	unsigned scissor_enabled; +	struct nouveau_stateobj *viewport; +	unsigned viewport_bypass; +	struct nouveau_stateobj *tsc_upload; +	struct nouveau_stateobj *tic_upload; +	struct nouveau_stateobj *vertprog; +	struct nouveau_stateobj *fragprog; +	struct nouveau_stateobj *vtxfmt; +	struct nouveau_stateobj *vtxbuf; +}; + +struct nv50_context { +	struct pipe_context pipe; + +	struct nv50_screen *screen; +	unsigned pctx_id; + +	struct draw_context *draw; + +	struct nv50_state state; + +	unsigned dirty; +	struct nv50_blend_stateobj *blend; +	struct nv50_zsa_stateobj *zsa; +	struct nv50_rasterizer_stateobj *rasterizer; +	struct pipe_blend_color blend_colour; +	struct pipe_poly_stipple stipple; +	struct pipe_scissor_state scissor; +	struct pipe_viewport_state viewport; +	struct pipe_framebuffer_state framebuffer; +	struct nv50_program *vertprog; +	struct nv50_program *fragprog; +	struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; +	struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; +	unsigned vtxbuf_nr; +	struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; +	unsigned vtxelt_nr; +	unsigned *sampler[PIPE_MAX_SAMPLERS]; +	unsigned sampler_nr; +	struct nv50_miptree *miptree[PIPE_MAX_SAMPLERS]; +	unsigned miptree_nr; +}; + +static INLINE struct nv50_context * +nv50_context(struct pipe_context *pipe) +{ +	return (struct nv50_context *)pipe; +} + +extern void nv50_init_surface_functions(struct nv50_context *nv50); +extern void nv50_init_state_functions(struct nv50_context *nv50); +extern void nv50_init_query_functions(struct nv50_context *nv50); + +extern void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen); + +/* nv50_draw.c */ +extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50); + +/* nv50_vbo.c */ +extern boolean nv50_draw_arrays(struct pipe_context *, unsigned mode, +				unsigned start, unsigned count); +extern boolean nv50_draw_elements(struct pipe_context *pipe, +				  struct pipe_buffer *indexBuffer, +				  unsigned indexSize, +				  unsigned mode, unsigned start, +				  unsigned count); +extern void nv50_vbo_validate(struct nv50_context *nv50); + +/* nv50_clear.c */ +extern void nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps, +		       unsigned clearValue); + +/* nv50_program.c */ +extern void nv50_vertprog_validate(struct nv50_context *nv50); +extern void nv50_fragprog_validate(struct nv50_context *nv50); +extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p); + +/* nv50_state_validate.c */ +extern boolean nv50_state_validate(struct nv50_context *nv50); + +/* nv50_tex.c */ +extern void nv50_tex_validate(struct nv50_context *); + +#endif diff --git a/src/gallium/drivers/nv50/nv50_draw.c b/src/gallium/drivers/nv50/nv50_draw.c new file mode 100644 index 0000000000..4fd81bd27a --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_draw.c @@ -0,0 +1,90 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "draw/draw_pipe.h" +#include "pipe/p_util.h" + +#include "nv50_context.h" + +struct nv50_render_stage { +	struct draw_stage stage; +	struct nv50_context *nv50; +}; + +static INLINE struct nv50_render_stage * +nv50_render_stage(struct draw_stage *stage) +{ +	return (struct nv50_render_stage *)stage; +} + +static void +nv50_render_point(struct draw_stage *stage, struct prim_header *prim) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv50_render_line(struct draw_stage *stage, struct prim_header *prim) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv50_render_tri(struct draw_stage *stage, struct prim_header *prim) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv50_render_flush(struct draw_stage *stage, unsigned flags) +{ +} + +static void +nv50_render_reset_stipple_counter(struct draw_stage *stage) +{ +	NOUVEAU_ERR("\n"); +} + +static void +nv50_render_destroy(struct draw_stage *stage) +{ +	FREE(stage); +} + +struct draw_stage * +nv50_draw_render_stage(struct nv50_context *nv50) +{ +	struct nv50_render_stage *rs = CALLOC_STRUCT(nv50_render_stage); + +	rs->nv50 = nv50; +	rs->stage.draw = nv50->draw; +	rs->stage.destroy = nv50_render_destroy; +	rs->stage.point = nv50_render_point; +	rs->stage.line = nv50_render_line; +	rs->stage.tri = nv50_render_tri; +	rs->stage.flush = nv50_render_flush; +	rs->stage.reset_stipple_counter = nv50_render_reset_stipple_counter; + +	return &rs->stage; +} + diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c new file mode 100644 index 0000000000..a02ad41885 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -0,0 +1,137 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "nv50_context.h" + +static struct pipe_texture * +nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); +	unsigned usage, pitch; + +	mt->base = *pt; +	mt->base.refcount = 1; +	mt->base.screen = pscreen; + +	usage = PIPE_BUFFER_USAGE_PIXEL; +	switch (pt->format) { +	case PIPE_FORMAT_Z24S8_UNORM: +	case PIPE_FORMAT_Z16_UNORM: +		usage |= NOUVEAU_BUFFER_USAGE_ZETA; +		break; +	default: +		break; +	} + +	pitch = ((pt->width[0] + 63) & ~63) * pt->block.size; + +	mt->buffer = ws->buffer_create(ws, 256, usage, pitch * pt->height[0]); +	if (!mt->buffer) { +		FREE(mt); +		return NULL; +	} + +	return &mt->base; +} + +static void +nv50_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct pipe_texture *pt = *ppt; + +	*ppt = NULL; + +	if (--pt->refcount <= 0) { +		struct nv50_miptree *mt = nv50_miptree(pt); + +		pipe_buffer_reference(ws, &mt->buffer, NULL); +		FREE(mt); +	} +} + +static struct pipe_surface * +nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +			 unsigned face, unsigned level, unsigned zslice, +			 unsigned flags) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv50_miptree *mt = nv50_miptree(pt); +	struct nv50_surface *s; +	struct pipe_surface *ps; + +	s = CALLOC_STRUCT(nv50_surface); +	if (!s) +		return NULL; +	ps = &s->base; + +	ps->refcount = 1; +	ps->winsys = ws; +	ps->format = pt->format; +	ps->width = pt->width[level]; +	ps->height = pt->height[level]; +	ps->block = pt->block; +	ps->nblocksx = pt->nblocksx[level]; +	ps->nblocksy = pt->nblocksy[level]; +	ps->stride = ps->width * ps->block.size; +	ps->offset = 0; +	ps->usage = flags; +	ps->status = PIPE_SURFACE_STATUS_DEFINED; + +	pipe_texture_reference(&ps->texture, pt); +	pipe_buffer_reference(ws, &ps->buffer, mt->buffer); + +	return ps; +} + +static void +nv50_miptree_surface_del(struct pipe_screen *pscreen, +			 struct pipe_surface **psurface) +{ +	struct pipe_winsys *ws = pscreen->winsys; +	struct pipe_surface *ps = *psurface; +	struct nv50_surface *s = nv50_surface(ps); + +	*psurface = NULL; + +	if (--ps->refcount <= 0) { +		pipe_texture_reference(&ps->texture, NULL); +		pipe_buffer_reference(ws, &ps->buffer, NULL); +		FREE(s); +	} +} + +void +nv50_screen_init_miptree_functions(struct pipe_screen *pscreen) +{ +	pscreen->texture_create = nv50_miptree_create; +	pscreen->texture_release = nv50_miptree_release; +	pscreen->get_tex_surface = nv50_miptree_surface_new; +	pscreen->tex_surface_release = nv50_miptree_surface_del; +} + diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c new file mode 100644 index 0000000000..d6fbdd1824 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -0,0 +1,1708 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" + +#include "nv50_context.h" + +#define NV50_SU_MAX_TEMP 64 +#define NV50_PROGRAM_DUMP + +/* ARL - gallium craps itself on progs/vp/arl.txt + * + * MSB - Like MAD, but MUL+SUB + * 	- Fuck it off, introduce a way to negate args for ops that + * 	  support it. + * + * Look into inlining IMMD for ops other than MOV (make it general?) + * 	- Maybe even relax restrictions a bit, can't do P_RESULT + P_IMMD, + * 	  but can emit to P_TEMP first - then MOV later. NVIDIA does this + * + * In ops such as ADD it's possible to construct a bad opcode in the !is_long() + * case, if the emit_src() causes the inst to suddenly become long. + * + * Verify half-insns work where expected - and force disable them where they + * don't work - MUL has it forcibly disabled atm as it fixes POW.. + * + * FUCK! watch dst==src vectors, can overwrite components that are needed. + * 	ie. SUB R0, R0.yzxw, R0 + * + * Things to check with renouveau: + * 	FP attr/result assignment - how? + * 		attrib + * 			- 0x16bc maps vp output onto fp hpos + * 			- 0x16c0 maps vp output onto fp col0 + * 		result + * 			- colr always 0-3 + * 			- depr always 4 + * 0x16bc->0x16e8 --> some binding between vp/fp regs + * 0x16b8 --> VP output count + * + * 0x1298 --> "MOV rcol.x, fcol.y" "MOV depr, fcol.y" = 0x00000005 + * 	      "MOV rcol.x, fcol.y" = 0x00000004 + * 0x19a8 --> as above but 0x00000100 and 0x00000000 + * 	- 0x00100000 used when KIL used + * 0x196c --> as above but 0x00000011 and 0x00000000 + * + * 0x1988 --> 0xXXNNNNNN + * 	- XX == FP high something + */ +struct nv50_reg { +	enum { +		P_TEMP, +		P_ATTR, +		P_RESULT, +		P_CONST, +		P_IMMD +	} type; +	int index; + +	int hw; +	int neg; +}; + +struct nv50_pc { +	struct nv50_program *p; + +	/* hw resources */ +	struct nv50_reg *r_temp[NV50_SU_MAX_TEMP]; + +	/* tgsi resources */ +	struct nv50_reg *temp; +	int temp_nr; +	struct nv50_reg *attr; +	int attr_nr; +	struct nv50_reg *result; +	int result_nr; +	struct nv50_reg *param; +	int param_nr; +	struct nv50_reg *immd; +	float *immd_buf; +	int immd_nr; + +	struct nv50_reg *temp_temp[16]; +	unsigned temp_temp_nr; +}; + +static void +alloc_reg(struct nv50_pc *pc, struct nv50_reg *reg) +{ +	int i; + +	if (reg->type == P_RESULT) { +		if (pc->p->cfg.high_result < (reg->hw + 1)) +			pc->p->cfg.high_result = reg->hw + 1; +	} + +	if (reg->type != P_TEMP) +		return; + +	if (reg->hw >= 0) { +		/*XXX: do this here too to catch FP temp-as-attr usage.. +		 *     not clean, but works */ +		if (pc->p->cfg.high_temp < (reg->hw + 1)) +			pc->p->cfg.high_temp = reg->hw + 1; +		return; +	} + +	for (i = 0; i < NV50_SU_MAX_TEMP; i++) { +		if (!(pc->r_temp[i])) { +			pc->r_temp[i] = reg; +			reg->hw = i; +			if (pc->p->cfg.high_temp < (i + 1)) +				pc->p->cfg.high_temp = i + 1; +			return; +		} +	} + +	assert(0); +} + +static struct nv50_reg * +alloc_temp(struct nv50_pc *pc, struct nv50_reg *dst) +{ +	struct nv50_reg *r; +	int i; + +	if (dst && dst->type == P_TEMP && dst->hw == -1) +		return dst; + +	for (i = 0; i < NV50_SU_MAX_TEMP; i++) { +		if (!pc->r_temp[i]) { +			r = CALLOC_STRUCT(nv50_reg); +			r->type = P_TEMP; +			r->index = -1; +			r->hw = i; +			pc->r_temp[i] = r; +			return r; +		} +	} + +	assert(0); +	return NULL; +} + +static void +free_temp(struct nv50_pc *pc, struct nv50_reg *r) +{ +	if (r->index == -1) { +		unsigned hw = r->hw; + +		FREE(pc->r_temp[hw]); +		pc->r_temp[hw] = NULL; +	} +} + +static struct nv50_reg * +temp_temp(struct nv50_pc *pc) +{ +	if (pc->temp_temp_nr >= 16) +		assert(0); + +	pc->temp_temp[pc->temp_temp_nr] = alloc_temp(pc, NULL); +	return pc->temp_temp[pc->temp_temp_nr++]; +} + +static void +kill_temp_temp(struct nv50_pc *pc) +{ +	int i; +	 +	for (i = 0; i < pc->temp_temp_nr; i++) +		free_temp(pc, pc->temp_temp[i]); +	pc->temp_temp_nr = 0; +} + +static int +ctor_immd(struct nv50_pc *pc, float x, float y, float z, float w) +{ +	pc->immd_buf = REALLOC(pc->immd_buf, (pc->immd_nr * r * sizeof(float)), +			       (pc->immd_nr + 1) * 4 * sizeof(float)); +	pc->immd_buf[(pc->immd_nr * 4) + 0] = x; +	pc->immd_buf[(pc->immd_nr * 4) + 1] = y; +	pc->immd_buf[(pc->immd_nr * 4) + 2] = z; +	pc->immd_buf[(pc->immd_nr * 4) + 3] = w; +	 +	return pc->immd_nr++; +} + +static struct nv50_reg * +alloc_immd(struct nv50_pc *pc, float f) +{ +	struct nv50_reg *r = CALLOC_STRUCT(nv50_reg); +	unsigned hw; + +	hw = ctor_immd(pc, f, 0, 0, 0) * 4; +	r->type = P_IMMD; +	r->hw = hw; +	r->index = -1; +	return r; +} + +static struct nv50_program_exec * +exec(struct nv50_pc *pc) +{ +	struct nv50_program_exec *e = CALLOC_STRUCT(nv50_program_exec); + +	e->param.index = -1; +	return e; +} + +static void +emit(struct nv50_pc *pc, struct nv50_program_exec *e) +{ +	struct nv50_program *p = pc->p; + +	if (p->exec_tail) +		p->exec_tail->next = e; +	if (!p->exec_head) +		p->exec_head = e; +	p->exec_tail = e; +	p->exec_size += (e->inst[0] & 1) ? 2 : 1; +} + +static INLINE void set_long(struct nv50_pc *, struct nv50_program_exec *); + +static boolean +is_long(struct nv50_program_exec *e) +{ +	if (e->inst[0] & 1) +		return TRUE; +	return FALSE; +} + +static boolean +is_immd(struct nv50_program_exec *e) +{ +	if (is_long(e) && (e->inst[1] & 3) == 3) +		return TRUE; +	return FALSE; +} + +static INLINE void +set_pred(struct nv50_pc *pc, unsigned pred, unsigned idx, +	 struct nv50_program_exec *e) +{ +	set_long(pc, e); +	e->inst[1] &= ~((0x1f << 7) | (0x3 << 12)); +	e->inst[1] |= (pred << 7) | (idx << 12); +} + +static INLINE void +set_pred_wr(struct nv50_pc *pc, unsigned on, unsigned idx, +	    struct nv50_program_exec *e) +{ +	set_long(pc, e); +	e->inst[1] &= ~((0x3 << 4) | (1 << 6)); +	e->inst[1] |= (idx << 4) | (on << 6); +} + +static INLINE void +set_long(struct nv50_pc *pc, struct nv50_program_exec *e) +{ +	if (is_long(e)) +		return; + +	e->inst[0] |= 1; +	set_pred(pc, 0xf, 0, e); +	set_pred_wr(pc, 0, 0, e); +} + +static INLINE void +set_dst(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_program_exec *e) +{ +	if (dst->type == P_RESULT) { +		set_long(pc, e); +		e->inst[1] |= 0x00000008; +	} + +	alloc_reg(pc, dst); +	e->inst[0] |= (dst->hw << 2); +} + +static INLINE void +set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) +{ +	unsigned val = fui(pc->immd_buf[imm->hw]); /* XXX */ + +	set_long(pc, e); +	/*XXX: can't be predicated - bits overlap.. catch cases where both +	 *     are required and avoid them. */ +	set_pred(pc, 0, 0, e); +	set_pred_wr(pc, 0, 0, e); + +	e->inst[1] |= 0x00000002 | 0x00000001; +	e->inst[0] |= (val & 0x3f) << 16; +	e->inst[1] |= (val >> 6) << 2; +} + +static void +emit_interp(struct nv50_pc *pc, struct nv50_reg *dst, +	    struct nv50_reg *src, struct nv50_reg *iv) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0x80000000; +	set_dst(pc, dst, e); +	alloc_reg(pc, src); +	e->inst[0] |= (src->hw << 16); +	if (iv) { +		e->inst[0] |= (1 << 25); +		alloc_reg(pc, iv); +		e->inst[0] |= (iv->hw << 9); +	} + +	emit(pc, e); +} + +static void +set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s, +	 struct nv50_program_exec *e) +{ +	set_long(pc, e); +#if 1 +	e->inst[1] |= (1 << 22); +#else +	if (src->type == P_IMMD) { +		e->inst[1] |= (NV50_CB_PMISC << 22); +	} else { +		if (pc->p->type == PIPE_SHADER_VERTEX) +			e->inst[1] |= (NV50_CB_PVP << 22); +		else +			e->inst[1] |= (NV50_CB_PFP << 22); +	} +#endif + +	e->param.index = src->hw; +	e->param.shift = s; +	e->param.mask = m << (s % 32); +} + +static void +emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0x10000000; + +	set_dst(pc, dst, e); + +	if (0 && dst->type != P_RESULT && src->type == P_IMMD) { +		set_immd(pc, src, e); +		/*XXX: 32-bit, but steals part of "half" reg space - need to +		 *     catch and handle this case if/when we do half-regs +		 */ +		e->inst[0] |= 0x00008000; +	} else +	if (src->type == P_IMMD || src->type == P_CONST) { +		set_long(pc, e); +		set_data(pc, src, 0x7f, 9, e); +		e->inst[1] |= 0x20000000; /* src0 const? */ +	} else { +		if (src->type == P_ATTR) { +			set_long(pc, e); +			e->inst[1] |= 0x00200000; +		} + +		alloc_reg(pc, src); +		e->inst[0] |= (src->hw << 9); +	} + +	/* We really should support "half" instructions here at some point, +	 * but I don't feel confident enough about them yet. +	 */ +	set_long(pc, e); +	if (is_long(e) && !is_immd(e)) { +		e->inst[1] |= 0x04000000; /* 32-bit */ +		e->inst[1] |= 0x0003c000; /* "subsubop" 0xf == mov */ +	} + +	emit(pc, e); +} + +static boolean +check_swap_src_0_1(struct nv50_pc *pc, +		   struct nv50_reg **s0, struct nv50_reg **s1) +{ +	struct nv50_reg *src0 = *s0, *src1 = *s1; + +	if (src0->type == P_CONST) { +		if (src1->type != P_CONST) { +			*s0 = src1; +			*s1 = src0; +			return TRUE; +		} +	} else +	if (src1->type == P_ATTR) { +		if (src0->type != P_ATTR) { +			*s0 = src1; +			*s1 = src0; +			return TRUE; +		} +	} + +	return FALSE; +} + +static void +set_src_0(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) +{ +	if (src->type == P_ATTR) { +		set_long(pc, e); +		e->inst[1] |= 0x00200000; +	} else +	if (src->type == P_CONST || src->type == P_IMMD) { +		struct nv50_reg *temp = temp_temp(pc); + +		emit_mov(pc, temp, src); +		src = temp; +	} + +	alloc_reg(pc, src); +	e->inst[0] |= (src->hw << 9); +} + +static void +set_src_1(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) +{ +	if (src->type == P_ATTR) { +		struct nv50_reg *temp = temp_temp(pc); + +		emit_mov(pc, temp, src); +		src = temp; +	} else +	if (src->type == P_CONST || src->type == P_IMMD) { +		assert(!(e->inst[0] & 0x00800000)); +		if (e->inst[0] & 0x01000000) { +			struct nv50_reg *temp = temp_temp(pc); + +			emit_mov(pc, temp, src); +			src = temp; +		} else { +			set_data(pc, src, 0x7f, 16, e); +			e->inst[0] |= 0x00800000; +		} +	} + +	alloc_reg(pc, src); +	e->inst[0] |= (src->hw << 16); +} + +static void +set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) +{ +	set_long(pc, e); + +	if (src->type == P_ATTR) { +		struct nv50_reg *temp = temp_temp(pc); + +		emit_mov(pc, temp, src); +		src = temp; +	} else +	if (src->type == P_CONST || src->type == P_IMMD) { +		assert(!(e->inst[0] & 0x01000000)); +		if (e->inst[0] & 0x00800000) { +			struct nv50_reg *temp = temp_temp(pc); + +			emit_mov(pc, temp, src); +			src = temp; +		} else { +			set_data(pc, src, 0x7f, 32+14, e); +			e->inst[0] |= 0x01000000; +		} +	} + +	alloc_reg(pc, src); +	e->inst[1] |= (src->hw << 14); +} + +static void +emit_mul(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, +	 struct nv50_reg *src1) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0xc0000000; +	set_long(pc, e); + +	check_swap_src_0_1(pc, &src0, &src1); +	set_dst(pc, dst, e); +	set_src_0(pc, src0, e); +	set_src_1(pc, src1, e); + +	emit(pc, e); +} + +static void +emit_add(struct nv50_pc *pc, struct nv50_reg *dst, +	 struct nv50_reg *src0, struct nv50_reg *src1) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0xb0000000; + +	check_swap_src_0_1(pc, &src0, &src1); +	set_dst(pc, dst, e); +	set_src_0(pc, src0, e); +	if (is_long(e)) +		set_src_2(pc, src1, e); +	else +		set_src_1(pc, src1, e); + +	emit(pc, e); +} + +static void +emit_minmax(struct nv50_pc *pc, unsigned sub, struct nv50_reg *dst, +	    struct nv50_reg *src0, struct nv50_reg *src1) +{ +	struct nv50_program_exec *e = exec(pc); + +	set_long(pc, e); +	e->inst[0] |= 0xb0000000; +	e->inst[1] |= (sub << 29); + +	check_swap_src_0_1(pc, &src0, &src1); +	set_dst(pc, dst, e); +	set_src_0(pc, src0, e); +	set_src_1(pc, src1, e); + +	emit(pc, e); +} + +static void +emit_sub(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, +	 struct nv50_reg *src1) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0xb0000000; + +	set_long(pc, e); +	if (check_swap_src_0_1(pc, &src0, &src1)) +		e->inst[1] |= 0x04000000; +	else +		e->inst[1] |= 0x08000000; + +	set_dst(pc, dst, e); +	set_src_0(pc, src0, e); +	set_src_2(pc, src1, e); + +	emit(pc, e); +} + +static void +emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, +	 struct nv50_reg *src1, struct nv50_reg *src2) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0xe0000000; + +	check_swap_src_0_1(pc, &src0, &src1); +	set_dst(pc, dst, e); +	set_src_0(pc, src0, e); +	set_src_1(pc, src1, e); +	set_src_2(pc, src2, e); + +	emit(pc, e); +} + +static void +emit_msb(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, +	 struct nv50_reg *src1, struct nv50_reg *src2) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0xe0000000; +	set_long(pc, e); +	e->inst[1] |= 0x08000000; /* src0 * src1 - src2 */ + +	check_swap_src_0_1(pc, &src0, &src1); +	set_dst(pc, dst, e); +	set_src_0(pc, src0, e); +	set_src_1(pc, src1, e); +	set_src_2(pc, src2, e); + +	emit(pc, e); +} + +static void +emit_flop(struct nv50_pc *pc, unsigned sub, +	  struct nv50_reg *dst, struct nv50_reg *src) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0x90000000; +	if (sub) { +		set_long(pc, e); +		e->inst[1] |= (sub << 29); +	} + +	set_dst(pc, dst, e); +	set_src_0(pc, src, e); + +	emit(pc, e); +} + +static void +emit_preex2(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0xb0000000; + +	set_dst(pc, dst, e); +	set_src_0(pc, src, e); +	set_long(pc, e); +	e->inst[1] |= (6 << 29) | 0x00004000; + +	emit(pc, e); +} + +static void +emit_precossin(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] |= 0xb0000000; + +	set_dst(pc, dst, e); +	set_src_0(pc, src, e); +	set_long(pc, e); +	e->inst[1] |= (6 << 29); + +	emit(pc, e); +} + +static void +emit_set(struct nv50_pc *pc, unsigned c_op, struct nv50_reg *dst, +	 struct nv50_reg *src0, struct nv50_reg *src1) +{ +	struct nv50_program_exec *e = exec(pc); +	unsigned inv_cop[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; +	struct nv50_reg *rdst; + +	assert(c_op <= 7); +	if (check_swap_src_0_1(pc, &src0, &src1)) +		c_op = inv_cop[c_op]; + +	rdst = dst; +	if (dst->type != P_TEMP) +		dst = alloc_temp(pc, NULL); + +	/* set.u32 */ +	set_long(pc, e); +	e->inst[0] |= 0xb0000000; +	e->inst[1] |= (3 << 29); +	e->inst[1] |= (c_op << 14); +	/*XXX: breaks things, .u32 by default? +	 *     decuda will disasm as .u16 and use .lo/.hi regs, but this +	 *     doesn't seem to match what the hw actually does. +	inst[1] |= 0x04000000; << breaks things.. .u32 by default? +	 */ +	set_dst(pc, dst, e); +	set_src_0(pc, src0, e); +	set_src_1(pc, src1, e); +	emit(pc, e); + +	/* cvt.f32.u32 */ +	e = exec(pc); +	e->inst[0] = 0xa0000001; +	e->inst[1] = 0x64014780; +	set_dst(pc, rdst, e); +	set_src_0(pc, dst, e); +	emit(pc, e); + +	if (dst != rdst) +		free_temp(pc, dst); +} + +static void +emit_flr(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] = 0xa0000000; /* cvt */ +	set_long(pc, e); +	e->inst[1] |= (6 << 29); /* cvt */ +	e->inst[1] |= 0x08000000; /* integer mode */ +	e->inst[1] |= 0x04000000; /* 32 bit */ +	e->inst[1] |= ((0x1 << 3)) << 14; /* .rn */ +	e->inst[1] |= (1 << 14); /* src .f32 */ +	set_dst(pc, dst, e); +	set_src_0(pc, src, e); + +	emit(pc, e); +} + +static void +emit_pow(struct nv50_pc *pc, struct nv50_reg *dst, +	 struct nv50_reg *v, struct nv50_reg *e) +{ +	struct nv50_reg *temp = alloc_temp(pc, NULL); + +	emit_flop(pc, 3, temp, v); +	emit_mul(pc, temp, temp, e); +	emit_preex2(pc, temp, temp); +	emit_flop(pc, 6, dst, temp); + +	free_temp(pc, temp); +} + +static void +emit_abs(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) +{ +	struct nv50_program_exec *e = exec(pc); + +	e->inst[0] = 0xa0000000; /* cvt */ +	set_long(pc, e); +	e->inst[1] |= (6 << 29); /* cvt */ +	e->inst[1] |= 0x04000000; /* 32 bit */ +	e->inst[1] |= (1 << 14); /* src .f32 */ +	e->inst[1] |= ((1 << 6) << 14); /* .abs */ +	set_dst(pc, dst, e); +	set_src_0(pc, src, e); + +	emit(pc, e); +} + +static void +emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask, +	 struct nv50_reg **src) +{ +	struct nv50_reg *one = alloc_immd(pc, 1.0); +	struct nv50_reg *zero = alloc_immd(pc, 0.0); +	struct nv50_reg *neg128 = alloc_immd(pc, -127.999999); +	struct nv50_reg *pos128 = alloc_immd(pc,  127.999999); +	struct nv50_reg *tmp[4]; + +	if (mask & (1 << 0)) +		emit_mov(pc, dst[0], one); + +	if (mask & (1 << 3)) +		emit_mov(pc, dst[3], one); + +	if (mask & (3 << 1)) { +		if (mask & (1 << 1)) +			tmp[0] = dst[1]; +		else +			tmp[0] = temp_temp(pc); +		emit_minmax(pc, 4, tmp[0], src[0], zero); +	} + +	if (mask & (1 << 2)) { +		set_pred_wr(pc, 1, 0, pc->p->exec_tail); + +		tmp[1] = temp_temp(pc); +		emit_minmax(pc, 4, tmp[1], src[1], zero); + +		tmp[3] = temp_temp(pc); +		emit_minmax(pc, 4, tmp[3], src[3], neg128); +		emit_minmax(pc, 5, tmp[3], tmp[3], pos128); + +		emit_pow(pc, dst[2], tmp[1], tmp[3]); +		emit_mov(pc, dst[2], zero); +		set_pred(pc, 3, 0, pc->p->exec_tail); +	} +} + +static void +emit_neg(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) +{ +	struct nv50_program_exec *e = exec(pc); + +	set_long(pc, e); +	e->inst[0] |= 0xa0000000; /* delta */ +	e->inst[1] |= (7 << 29); /* delta */ +	e->inst[1] |= 0x04000000; /* negate arg0? probably not */ +	e->inst[1] |= (1 << 14); /* src .f32 */ +	set_dst(pc, dst, e); +	set_src_0(pc, src, e); + +	emit(pc, e); +} + +static struct nv50_reg * +tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst) +{ +	switch (dst->DstRegister.File) { +	case TGSI_FILE_TEMPORARY: +		return &pc->temp[dst->DstRegister.Index * 4 + c]; +	case TGSI_FILE_OUTPUT: +		return &pc->result[dst->DstRegister.Index * 4 + c]; +	case TGSI_FILE_NULL: +		return NULL; +	default: +		break; +	} + +	return NULL; +} + +static struct nv50_reg * +tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src) +{ +	struct nv50_reg *r = NULL; +	struct nv50_reg *temp; +	unsigned c; + +	c = tgsi_util_get_full_src_register_extswizzle(src, chan); +	switch (c) { +	case TGSI_EXTSWIZZLE_X: +	case TGSI_EXTSWIZZLE_Y: +	case TGSI_EXTSWIZZLE_Z: +	case TGSI_EXTSWIZZLE_W: +		switch (src->SrcRegister.File) { +		case TGSI_FILE_INPUT: +			r = &pc->attr[src->SrcRegister.Index * 4 + c]; +			break; +		case TGSI_FILE_TEMPORARY: +			r = &pc->temp[src->SrcRegister.Index * 4 + c]; +			break; +		case TGSI_FILE_CONSTANT: +			r = &pc->param[src->SrcRegister.Index * 4 + c]; +			break; +		case TGSI_FILE_IMMEDIATE: +			r = &pc->immd[src->SrcRegister.Index * 4 + c]; +			break; +		case TGSI_FILE_SAMPLER: +			break; +		default: +			assert(0); +			break; +		} +		break; +	case TGSI_EXTSWIZZLE_ZERO: +		r = alloc_immd(pc, 0.0); +		break; +	case TGSI_EXTSWIZZLE_ONE: +		r = alloc_immd(pc, 1.0); +		break; +	default: +		assert(0); +		break; +	} + +	switch (tgsi_util_get_full_src_register_sign_mode(src, chan)) { +	case TGSI_UTIL_SIGN_KEEP: +		break; +	case TGSI_UTIL_SIGN_CLEAR: +		temp = temp_temp(pc); +		emit_abs(pc, temp, r); +		r = temp; +		break; +	case TGSI_UTIL_SIGN_TOGGLE: +		temp = temp_temp(pc); +		emit_neg(pc, temp, r); +		r = temp; +		break; +	case TGSI_UTIL_SIGN_SET: +		temp = temp_temp(pc); +		emit_abs(pc, temp, r); +		emit_neg(pc, temp, r); +		r = temp; +		break; +	default: +		assert(0); +		break; +	} + +	return r; +} + +static boolean +nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) +{ +	const struct tgsi_full_instruction *inst = &tok->FullInstruction; +	struct nv50_reg *rdst[4], *dst[4], *src[3][4], *temp; +	unsigned mask, sat; +	int i, c; + +	mask = inst->FullDstRegisters[0].DstRegister.WriteMask; +	sat = inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE; + +	for (c = 0; c < 4; c++) { +		if (mask & (1 << c)) +			dst[c] = tgsi_dst(pc, c, &inst->FullDstRegisters[0]); +		else +			dst[c] = NULL; +	} + +	for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { +		for (c = 0; c < 4; c++) +			src[i][c] = tgsi_src(pc, c, &inst->FullSrcRegisters[i]); +	} + +	if (sat) { +		for (c = 0; c < 4; c++) { +			rdst[c] = dst[c]; +			dst[c] = temp_temp(pc); +		} +	} + +	switch (inst->Instruction.Opcode) { +	case TGSI_OPCODE_ABS: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_abs(pc, dst[c], src[0][c]); +		} +		break; +	case TGSI_OPCODE_ADD: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_add(pc, dst[c], src[0][c], src[1][c]); +		} +		break; +	case TGSI_OPCODE_COS: +		temp = alloc_temp(pc, NULL); +		emit_precossin(pc, temp, src[0][0]); +		emit_flop(pc, 5, temp, temp); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		break; +	case TGSI_OPCODE_DP3: +		temp = alloc_temp(pc, NULL); +		emit_mul(pc, temp, src[0][0], src[1][0]); +		emit_mad(pc, temp, src[0][1], src[1][1], temp); +		emit_mad(pc, temp, src[0][2], src[1][2], temp); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		free_temp(pc, temp); +		break; +	case TGSI_OPCODE_DP4: +		temp = alloc_temp(pc, NULL); +		emit_mul(pc, temp, src[0][0], src[1][0]); +		emit_mad(pc, temp, src[0][1], src[1][1], temp); +		emit_mad(pc, temp, src[0][2], src[1][2], temp); +		emit_mad(pc, temp, src[0][3], src[1][3], temp); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		free_temp(pc, temp); +		break; +	case TGSI_OPCODE_DPH: +		temp = alloc_temp(pc, NULL); +		emit_mul(pc, temp, src[0][0], src[1][0]); +		emit_mad(pc, temp, src[0][1], src[1][1], temp); +		emit_mad(pc, temp, src[0][2], src[1][2], temp); +		emit_add(pc, temp, src[1][3], temp); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		free_temp(pc, temp); +		break; +	case TGSI_OPCODE_DST: +	{ +		struct nv50_reg *one = alloc_immd(pc, 1.0); +		if (mask & (1 << 0)) +			emit_mov(pc, dst[0], one); +		if (mask & (1 << 1)) +			emit_mul(pc, dst[1], src[0][1], src[1][1]); +		if (mask & (1 << 2)) +			emit_mov(pc, dst[2], src[0][2]); +		if (mask & (1 << 3)) +			emit_mov(pc, dst[3], src[1][3]); +		FREE(one); +	} +		break; +	case TGSI_OPCODE_EX2: +		temp = alloc_temp(pc, NULL); +		emit_preex2(pc, temp, src[0][0]); +		emit_flop(pc, 6, temp, temp); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		free_temp(pc, temp); +		break; +	case TGSI_OPCODE_FLR: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_flr(pc, dst[c], src[0][c]); +		} +		break; +	case TGSI_OPCODE_FRC: +		temp = alloc_temp(pc, NULL); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_flr(pc, temp, src[0][c]); +			emit_sub(pc, dst[c], src[0][c], temp); +		} +		free_temp(pc, temp); +		break; +	case TGSI_OPCODE_LIT: +		emit_lit(pc, &dst[0], mask, &src[0][0]); +		break; +	case TGSI_OPCODE_LG2: +		temp = alloc_temp(pc, NULL); +		emit_flop(pc, 3, temp, src[0][0]); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		break; +	case TGSI_OPCODE_LRP: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			/*XXX: we can do better than this */ +			temp = alloc_temp(pc, NULL); +			emit_neg(pc, temp, src[0][c]); +			emit_mad(pc, temp, temp, src[2][c], src[2][c]); +			emit_mad(pc, dst[c], src[0][c], src[1][c], temp); +			free_temp(pc, temp); +		} +		break; +	case TGSI_OPCODE_MAD: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mad(pc, dst[c], src[0][c], src[1][c], src[2][c]); +		} +		break; +	case TGSI_OPCODE_MAX: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_minmax(pc, 4, dst[c], src[0][c], src[1][c]); +		} +		break; +	case TGSI_OPCODE_MIN: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_minmax(pc, 5, dst[c], src[0][c], src[1][c]); +		} +		break; +	case TGSI_OPCODE_MOV: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], src[0][c]); +		} +		break; +	case TGSI_OPCODE_MUL: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mul(pc, dst[c], src[0][c], src[1][c]); +		} +		break; +	case TGSI_OPCODE_POW: +		temp = alloc_temp(pc, NULL); +		emit_pow(pc, temp, src[0][0], src[1][0]); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		free_temp(pc, temp); +		break; +	case TGSI_OPCODE_RCP: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_flop(pc, 0, dst[c], src[0][0]); +		} +		break; +	case TGSI_OPCODE_RSQ: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_flop(pc, 2, dst[c], src[0][0]); +		} +		break; +	case TGSI_OPCODE_SCS: +		temp = alloc_temp(pc, NULL); +		emit_precossin(pc, temp, src[0][0]); +		if (mask & (1 << 0)) +			emit_flop(pc, 5, dst[0], temp); +		if (mask & (1 << 1)) +			emit_flop(pc, 4, dst[1], temp); +		break; +	case TGSI_OPCODE_SGE: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_set(pc, 6, dst[c], src[0][c], src[1][c]); +		} +		break; +	case TGSI_OPCODE_SIN: +		temp = alloc_temp(pc, NULL); +		emit_precossin(pc, temp, src[0][0]); +		emit_flop(pc, 4, temp, temp); +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_mov(pc, dst[c], temp); +		} +		break; +	case TGSI_OPCODE_SLT: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_set(pc, 1, dst[c], src[0][c], src[1][c]); +		} +		break; +	case TGSI_OPCODE_SUB: +		for (c = 0; c < 4; c++) { +			if (!(mask & (1 << c))) +				continue; +			emit_sub(pc, dst[c], src[0][c], src[1][c]); +		} +		break; +	case TGSI_OPCODE_TEX: +		{ +			struct nv50_reg *t0, *t1, *t2, *t3; +			struct nv50_program_exec *e; + +			t0 = alloc_temp(pc, NULL); +			t0 = alloc_temp(pc, NULL); +			t1 = alloc_temp(pc, NULL); +			t2 = alloc_temp(pc, NULL); +			t3 = alloc_temp(pc, NULL); +			emit_mov(pc, t0, src[0][0]); +			emit_mov(pc, t1, src[0][1]); + +			e = exec(pc); +			e->inst[0] = 0xf6400000; +			set_long(pc, e); +			e->inst[1] |= 0x0000c004; +			set_dst(pc, t0, e); +			emit(pc, e); + +			if (mask & (1 << 0)) emit_mov(pc, dst[0], t0); +			if (mask & (1 << 1)) emit_mov(pc, dst[1], t1); +			if (mask & (1 << 2)) emit_mov(pc, dst[2], t2); +			if (mask & (1 << 3)) emit_mov(pc, dst[3], t3); + +			free_temp(pc, t0); +			free_temp(pc, t1); +			free_temp(pc, t2); +			free_temp(pc, t3); +		} +		break; +	case TGSI_OPCODE_XPD: +		temp = alloc_temp(pc, NULL); +		if (mask & (1 << 0)) { +			emit_mul(pc, temp, src[0][2], src[1][1]); +			emit_msb(pc, dst[0], src[0][1], src[1][2], temp); +		} +		if (mask & (1 << 1)) { +			emit_mul(pc, temp, src[0][0], src[1][2]); +			emit_msb(pc, dst[1], src[0][2], src[1][0], temp); +		} +		if (mask & (1 << 2)) { +			emit_mul(pc, temp, src[0][1], src[1][0]); +			emit_msb(pc, dst[2], src[0][0], src[1][1], temp); +		} +		free_temp(pc, temp); +		break; +	case TGSI_OPCODE_END: +		break; +	default: +		NOUVEAU_ERR("invalid opcode %d\n", inst->Instruction.Opcode); +		return FALSE; +	} + +	if (sat) { +		for (c = 0; c < 4; c++) { +			struct nv50_program_exec *e; + +			if (!(mask & (1 << c))) +				continue; +			e = exec(pc); + +			e->inst[0] = 0xa0000000; /* cvt */ +			set_long(pc, e); +			e->inst[1] |= (6 << 29); /* cvt */ +			e->inst[1] |= 0x04000000; /* 32 bit */ +			e->inst[1] |= (1 << 14); /* src .f32 */ +			e->inst[1] |= ((1 << 5) << 14); /* .sat */ +			set_dst(pc, rdst[c], e); +			set_src_0(pc, dst[c], e); +			emit(pc, e); +		} +	} + +	kill_temp_temp(pc); +	return TRUE; +} + +static boolean +nv50_program_tx_prep(struct nv50_pc *pc) +{ +	struct tgsi_parse_context p; +	boolean ret = FALSE; +	unsigned i, c; + +	tgsi_parse_init(&p, pc->p->pipe.tokens); +	while (!tgsi_parse_end_of_tokens(&p)) { +		const union tgsi_full_token *tok = &p.FullToken; + +		tgsi_parse_token(&p); +		switch (tok->Token.Type) { +		case TGSI_TOKEN_TYPE_IMMEDIATE: +		{ +			const struct tgsi_full_immediate *imm = +				&p.FullToken.FullImmediate; + +			ctor_immd(pc, imm->u.ImmediateFloat32[0].Float, +				      imm->u.ImmediateFloat32[1].Float, +				      imm->u.ImmediateFloat32[2].Float, +				      imm->u.ImmediateFloat32[3].Float); +		} +			break; +		case TGSI_TOKEN_TYPE_DECLARATION: +		{ +			const struct tgsi_full_declaration *d; +			unsigned last; + +			d = &p.FullToken.FullDeclaration; +			last = d->DeclarationRange.Last; + +			switch (d->Declaration.File) { +			case TGSI_FILE_TEMPORARY: +				if (pc->temp_nr < (last + 1)) +					pc->temp_nr = last + 1; +				break; +			case TGSI_FILE_OUTPUT: +				if (pc->result_nr < (last + 1)) +					pc->result_nr = last + 1; +				break; +			case TGSI_FILE_INPUT: +				if (pc->attr_nr < (last + 1)) +					pc->attr_nr = last + 1; +				break; +			case TGSI_FILE_CONSTANT: +				if (pc->param_nr < (last + 1)) +					pc->param_nr = last + 1; +				break; +			case TGSI_FILE_SAMPLER: +				break; +			default: +				NOUVEAU_ERR("bad decl file %d\n", +					    d->Declaration.File); +				goto out_err; +			} +		} +			break; +		case TGSI_TOKEN_TYPE_INSTRUCTION: +			break; +		default: +			break; +		} +	} + +	if (pc->temp_nr) { +		pc->temp = CALLOC(pc->temp_nr * 4, sizeof(struct nv50_reg)); +		if (!pc->temp) +			goto out_err; + +		for (i = 0; i < pc->temp_nr; i++) { +			for (c = 0; c < 4; c++) { +				pc->temp[i*4+c].type = P_TEMP; +				pc->temp[i*4+c].hw = -1; +				pc->temp[i*4+c].index = i; +			} +		} +	} + +	if (pc->attr_nr) { +		struct nv50_reg *iv = NULL; +		int aid = 0; + +		pc->attr = CALLOC(pc->attr_nr * 4, sizeof(struct nv50_reg)); +		if (!pc->attr) +			goto out_err; + +		if (pc->p->type == PIPE_SHADER_FRAGMENT) { +			iv = alloc_temp(pc, NULL); +			emit_interp(pc, iv, iv, NULL); +			emit_flop(pc, 0, iv, iv); +			aid++; +		} + +		for (i = 0; i < pc->attr_nr; i++) { +			struct nv50_reg *a = &pc->attr[i*4]; + +			for (c = 0; c < 4; c++) { +				if (pc->p->type == PIPE_SHADER_FRAGMENT) { +					struct nv50_reg *at = +						alloc_temp(pc, NULL); +					pc->attr[i*4+c].type = at->type; +					pc->attr[i*4+c].hw = at->hw; +					pc->attr[i*4+c].index = at->index; +				} else { +					pc->p->cfg.vp.attr[aid/32] |= +						(1 << (aid % 32)); +					pc->attr[i*4+c].type = P_ATTR; +					pc->attr[i*4+c].hw = aid++; +					pc->attr[i*4+c].index = i; +				} +			} + +			if (pc->p->type != PIPE_SHADER_FRAGMENT) +				continue; + +			emit_interp(pc, &a[0], &a[0], iv); +			emit_interp(pc, &a[1], &a[1], iv); +			emit_interp(pc, &a[2], &a[2], iv); +			emit_interp(pc, &a[3], &a[3], iv); +		} + +		if (iv) +			free_temp(pc, iv); +	} + +	if (pc->result_nr) { +		int rid = 0; + +		pc->result = CALLOC(pc->result_nr * 4, sizeof(struct nv50_reg)); +		if (!pc->result) +			goto out_err; + +		for (i = 0; i < pc->result_nr; i++) { +			for (c = 0; c < 4; c++) { +				if (pc->p->type == PIPE_SHADER_FRAGMENT) { +					pc->result[i*4+c].type = P_TEMP; +					pc->result[i*4+c].hw = -1; +				} else { +					pc->result[i*4+c].type = P_RESULT; +					pc->result[i*4+c].hw = rid++; +				} +				pc->result[i*4+c].index = i; +			} +		} +	} + +	if (pc->param_nr) { +		int rid = 0; + +		pc->param = CALLOC(pc->param_nr * 4, sizeof(struct nv50_reg)); +		if (!pc->param) +			goto out_err; + +		for (i = 0; i < pc->param_nr; i++) { +			for (c = 0; c < 4; c++) { +				pc->param[i*4+c].type = P_CONST; +				pc->param[i*4+c].hw = rid++; +				pc->param[i*4+c].index = i; +			} +		} +	} + +	if (pc->immd_nr) { +		int rid = pc->param_nr * 4; + +		pc->immd = CALLOC(pc->immd_nr * 4, sizeof(struct nv50_reg)); +		if (!pc->immd) +			goto out_err; + +		for (i = 0; i < pc->immd_nr; i++) { +			for (c = 0; c < 4; c++) { +				pc->immd[i*4+c].type = P_IMMD; +				pc->immd[i*4+c].hw = rid++; +				pc->immd[i*4+c].index = i; +			} +		} +	} + +	ret = TRUE; +out_err: +	tgsi_parse_free(&p); +	return ret; +} + +static boolean +nv50_program_tx(struct nv50_program *p) +{ +	struct tgsi_parse_context parse; +	struct nv50_pc *pc; +	boolean ret; + +	pc = CALLOC_STRUCT(nv50_pc); +	if (!pc) +		return FALSE; +	pc->p = p; +	pc->p->cfg.high_temp = 4; + +	ret = nv50_program_tx_prep(pc); +	if (ret == FALSE) +		goto out_cleanup; + +	tgsi_parse_init(&parse, pc->p->pipe.tokens); +	while (!tgsi_parse_end_of_tokens(&parse)) { +		const union tgsi_full_token *tok = &parse.FullToken; + +		tgsi_parse_token(&parse); + +		switch (tok->Token.Type) { +		case TGSI_TOKEN_TYPE_INSTRUCTION: +			ret = nv50_program_tx_insn(pc, tok); +			if (ret == FALSE) +				goto out_err; +			break; +		default: +			break; +		} +	} + +	if (p->type == PIPE_SHADER_FRAGMENT) { +		struct nv50_reg out; + +		out.type = P_TEMP; +		for (out.hw = 0; out.hw < pc->result_nr * 4; out.hw++) +			emit_mov(pc, &out, &pc->result[out.hw]); +	} + +	assert(is_long(pc->p->exec_tail) && !is_immd(pc->p->exec_head)); +	pc->p->exec_tail->inst[1] |= 0x00000001; + +	p->param_nr = pc->param_nr * 4; +	p->immd_nr = pc->immd_nr * 4; +	p->immd = pc->immd_buf; + +out_err: +	tgsi_parse_free(&parse); + +out_cleanup: +	return ret; +} + +static void +nv50_program_validate(struct nv50_context *nv50, struct nv50_program *p) +{ +	if (nv50_program_tx(p) == FALSE) +		assert(0); +	p->translated = TRUE; +} + +static void +nv50_program_upload_data(struct nv50_context *nv50, float *map, +			 unsigned start, unsigned count) +{ +	while (count) { +		unsigned nr = count > 2047 ? 2047 : count; + +		BEGIN_RING(tesla, 0x00000f00, 1); +		OUT_RING  ((NV50_CB_PMISC << 0) | (start << 8)); +		BEGIN_RING(tesla, 0x40000f04, nr); +		OUT_RINGp (map, nr); + +		map += nr; +		start += nr; +		count -= nr; +	} +} + +static void +nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) +{ +	struct nouveau_winsys *nvws = nv50->screen->nvws; +	struct pipe_winsys *ws = nv50->pipe.winsys; +	unsigned nr = p->param_nr + p->immd_nr; + +	if (!p->data && nr) { +		struct nouveau_resource *heap = nv50->screen->vp_data_heap; + +		if (nvws->res_alloc(heap, nr, p, &p->data)) { +			while (heap->next && heap->size < nr) { +				struct nv50_program *evict = heap->next->priv; +				nvws->res_free(&evict->data); +			} + +			if (nvws->res_alloc(heap, nr, p, &p->data)) +				assert(0); +		} +	} + +	if (p->param_nr) { +		float *map = ws->buffer_map(ws, nv50->constbuf[p->type], +					    PIPE_BUFFER_USAGE_CPU_READ); +		nv50_program_upload_data(nv50, map, p->data->start, +					 p->param_nr); +		ws->buffer_unmap(ws, nv50->constbuf[p->type]); +	} + +	if (p->immd_nr) { +		nv50_program_upload_data(nv50, p->immd, +					 p->data->start + p->param_nr, +					 p->immd_nr); +	} +} + +static void +nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) +{ +	struct pipe_winsys *ws = nv50->pipe.winsys; +	struct nv50_program_exec *e; +	struct nouveau_stateobj *so; +	const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; +	unsigned start, count, *up, *ptr; +	boolean upload = FALSE; + +	if (!p->buffer) { +		p->buffer = ws->buffer_create(ws, 0x100, 0, p->exec_size * 4); +		upload = TRUE; +	} + +	if (p->data && p->data->start != p->data_start) { +		for (e = p->exec_head; e; e = e->next) { +			unsigned ei, ci; + +			if (e->param.index < 0) +				continue; +			ei = e->param.shift >> 5; +			ci = e->param.index + p->data->start; + +			e->inst[ei] &= ~e->param.mask; +			e->inst[ei] |= (ci << e->param.shift); +		} + +		p->data_start = p->data->start; +		upload = TRUE; +	} + +	if (!upload) +		return; + +	up = ptr = MALLOC(p->exec_size * 4); +	for (e = p->exec_head; e; e = e->next) { +		*(ptr++) = e->inst[0]; +		if (is_long(e)) +			*(ptr++) = e->inst[1]; +	} + +	so = so_new(4,2); +	so_method(so, nv50->screen->tesla, 0x1280, 3); +	so_reloc (so, p->buffer, 0, flags | NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, p->buffer, 0, flags | NOUVEAU_BO_LOW, 0, 0); +	so_data  (so, (NV50_CB_PUPLOAD << 16) | 0x0800); //(p->exec_size * 4)); + +	start = 0; count = p->exec_size; +	while (count) { +		struct nouveau_winsys *nvws = nv50->screen->nvws; +		unsigned nr; + +		so_emit(nvws, so); + +		nr = MIN2(count, 2047); +		nr = MIN2(nvws->channel->pushbuf->remaining, nr); +		if (nvws->channel->pushbuf->remaining < (nr + 3)) { +			FIRE_RING(NULL); +			continue; +		} + +		BEGIN_RING(tesla, 0x0f00, 1); +		OUT_RING  ((start << 8) | NV50_CB_PUPLOAD); +		BEGIN_RING(tesla, 0x40000f04, nr);	 +		OUT_RINGp (up + start, nr); + +		start += nr; +		count -= nr; +	} + +	FREE(up); +	so_ref(NULL, &so); +} + +void +nv50_vertprog_validate(struct nv50_context *nv50) +{ +	struct nouveau_grobj *tesla = nv50->screen->tesla; +	struct nv50_program *p = nv50->vertprog; +	struct nouveau_stateobj *so; + +	if (!p->translated) { +		nv50_program_validate(nv50, p); +		if (!p->translated) +			assert(0); +	} + +	nv50_program_validate_data(nv50, p); +	nv50_program_validate_code(nv50, p); + +	so = so_new(13, 2); +	so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2); +	so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | +		  NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | +		  NOUVEAU_BO_LOW, 0, 0); +	so_method(so, tesla, 0x1650, 2); +	so_data  (so, p->cfg.vp.attr[0]); +	so_data  (so, p->cfg.vp.attr[1]); +	so_method(so, tesla, 0x16b8, 1); +	so_data  (so, p->cfg.high_result); +	so_method(so, tesla, 0x16ac, 2); +	so_data  (so, p->cfg.high_result); //8); +	so_data  (so, p->cfg.high_temp); +	so_method(so, tesla, 0x140c, 1); +	so_data  (so, 0); /* program start offset */ +	so_ref(so, &nv50->state.vertprog); +} + +void +nv50_fragprog_validate(struct nv50_context *nv50) +{ +	struct nouveau_grobj *tesla = nv50->screen->tesla; +	struct nv50_program *p = nv50->fragprog; +	struct nouveau_stateobj *so; + +	if (!p->translated) { +		nv50_program_validate(nv50, p); +		if (!p->translated) +			assert(0); +	} + +	nv50_program_validate_data(nv50, p); +	nv50_program_validate_code(nv50, p); + +	so = so_new(64, 2); +	so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2); +	so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | +		  NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | +		  NOUVEAU_BO_LOW, 0, 0); +	so_method(so, tesla, 0x1904, 4); +	so_data  (so, 0x01040404); /* p: 0x01000404 */ +	so_data  (so, 0x00000004); +	so_data  (so, 0x00000000); +	so_data  (so, 0x00000000); +	so_method(so, tesla, 0x16bc, 3); /*XXX: fixme */ +	so_data  (so, 0x03020100); +	so_data  (so, 0x07060504); +	so_data  (so, 0x0b0a0908); +	so_method(so, tesla, 0x1988, 2); +	so_data  (so, 0x08080408); //0x08040404); /* p: 0x0f000401 */ +	so_data  (so, p->cfg.high_temp); +	so_method(so, tesla, 0x1414, 1); +	so_data  (so, 0); /* program start offset */ +	so_ref(so, &nv50->state.fragprog); +} + +void +nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) +{ +	struct pipe_winsys *ws = nv50->pipe.winsys; + +	while (p->exec_head) { +		struct nv50_program_exec *e = p->exec_head; + +		p->exec_head = e->next; +		FREE(e); +	} +	p->exec_tail = NULL; +	p->exec_size = 0; + +	if (p->buffer) +		pipe_buffer_reference(ws, &p->buffer, NULL); + +	nv50->screen->nvws->res_free(&p->data); + +	p->translated = 0; +} + diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h new file mode 100644 index 0000000000..78deed6a38 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_program.h @@ -0,0 +1,45 @@ +#ifndef __NV50_PROGRAM_H__ +#define __NV50_PROGRAM_H__ + +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" + +struct nv50_program_exec { +	struct nv50_program_exec *next; + +	unsigned inst[2]; +	struct { +		int index; +		unsigned mask; +		unsigned shift; +	} param; +}; + +struct nv50_program { +	struct pipe_shader_state pipe; +	struct tgsi_shader_info info; +	boolean translated; + +	unsigned type; +	struct nv50_program_exec *exec_head; +	struct nv50_program_exec *exec_tail; +	unsigned exec_size; +	struct nouveau_resource *data; +	unsigned data_start; + +	struct pipe_buffer *buffer; + +	float *immd; +	unsigned immd_nr; +	unsigned param_nr; + +	struct { +		unsigned high_temp; +		unsigned high_result; +		struct { +			unsigned attr[2]; +		} vp; +	} cfg; +}; + +#endif diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c new file mode 100644 index 0000000000..26bd90ccc5 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -0,0 +1,69 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "pipe/p_context.h" + +#include "nv50_context.h" + +static struct pipe_query * +nv50_query_create(struct pipe_context *pipe, unsigned type) +{ +	NOUVEAU_ERR("unimplemented\n"); +	return NULL; +} + +static void +nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *q) +{ +	NOUVEAU_ERR("unimplemented\n"); +} + +static void +nv50_query_begin(struct pipe_context *pipe, struct pipe_query *q) +{ +	NOUVEAU_ERR("unimplemented\n"); +} + +static void +nv50_query_end(struct pipe_context *pipe, struct pipe_query *q) +{ +	NOUVEAU_ERR("unimplemented\n"); +} + +static boolean +nv50_query_result(struct pipe_context *pipe, struct pipe_query *q, +		  boolean wait, uint64 *result) +{ +	NOUVEAU_ERR("unimplemented\n"); +	*result = 0xdeadcafe; +	return TRUE; +} + +void +nv50_init_query_functions(struct nv50_context *nv50) +{ +	nv50->pipe.create_query = nv50_query_create; +	nv50->pipe.destroy_query = nv50_query_destroy; +	nv50->pipe.begin_query = nv50_query_begin; +	nv50->pipe.end_query = nv50_query_end; +	nv50->pipe.get_query_result = nv50_query_result; +} diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c new file mode 100644 index 0000000000..ec43923929 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -0,0 +1,324 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "pipe/p_screen.h" +#include "pipe/p_util.h" + +#include "nv50_context.h" +#include "nv50_screen.h" + +#include "nouveau/nouveau_stateobj.h" + +#define NV5X_GRCLASS5097_CHIPSETS 0x00000001 +#define NV8X_GRCLASS8297_CHIPSETS 0x00000050 +#define NV9X_GRCLASS8297_CHIPSETS 0x00000014 + +static boolean +nv50_screen_is_format_supported(struct pipe_screen *pscreen, +				enum pipe_format format, +				enum pipe_texture_target target, +				unsigned tex_usage, unsigned geom_flags) +{ +	if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM: +		case PIPE_FORMAT_Z24S8_UNORM: +		case PIPE_FORMAT_Z16_UNORM: +			return TRUE; +		default: +			break; +		} +	} else { +		switch (format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +		case PIPE_FORMAT_A1R5G5B5_UNORM: +		case PIPE_FORMAT_A4R4G4B4_UNORM: +		case PIPE_FORMAT_R5G6B5_UNORM: +		case PIPE_FORMAT_L8_UNORM: +		case PIPE_FORMAT_A8_UNORM: +		case PIPE_FORMAT_I8_UNORM: +		case PIPE_FORMAT_A8L8_UNORM: +			return TRUE; +		default: +			break; +		} +	} + +	return FALSE; +} + +static const char * +nv50_screen_get_name(struct pipe_screen *pscreen) +{ +	struct nv50_screen *screen = nv50_screen(pscreen); +	struct nouveau_device *dev = screen->nvws->channel->device; +	static char buffer[128]; + +	snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); +	return buffer; +} + +static const char * +nv50_screen_get_vendor(struct pipe_screen *pscreen) +{ +	return "nouveau"; +} + +static int +nv50_screen_get_param(struct pipe_screen *pscreen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: +		return 32; +	case PIPE_CAP_NPOT_TEXTURES: +		return 0; +	case PIPE_CAP_TWO_SIDED_STENCIL: +		return 1; +	case PIPE_CAP_GLSL: +		return 0; +	case PIPE_CAP_S3TC: +		return 0; +	case PIPE_CAP_ANISOTROPIC_FILTER: +		return 0; +	case PIPE_CAP_POINT_SPRITE: +		return 0; +	case PIPE_CAP_MAX_RENDER_TARGETS: +		return 8; +	case PIPE_CAP_OCCLUSION_QUERY: +		return 0; +	case PIPE_CAP_TEXTURE_SHADOW_MAP: +		return 0; +	case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: +		return 13; +	case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: +		return 10; +	case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: +		return 13; +	case PIPE_CAP_TEXTURE_MIRROR_CLAMP: +	case PIPE_CAP_TEXTURE_MIRROR_REPEAT: +		return 1; +	case NOUVEAU_CAP_HW_VTXBUF:	 +		return 1; +	case NOUVEAU_CAP_HW_IDXBUF:	 +		return 0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0; +	} +} + +static float +nv50_screen_get_paramf(struct pipe_screen *pscreen, int param) +{ +	switch (param) { +	case PIPE_CAP_MAX_LINE_WIDTH: +	case PIPE_CAP_MAX_LINE_WIDTH_AA: +		return 10.0; +	case PIPE_CAP_MAX_POINT_WIDTH: +	case PIPE_CAP_MAX_POINT_WIDTH_AA: +		return 64.0; +	case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: +		return 16.0; +	case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: +		return 4.0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0.0; +	} +} + +static void +nv50_screen_destroy(struct pipe_screen *pscreen) +{ +	FREE(pscreen); +} + +struct pipe_screen * +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +{ +	struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen); +	struct nouveau_stateobj *so; +	unsigned tesla_class = 0, ret; +	unsigned chipset = nvws->channel->device->chipset; +	int i; + +	if (!screen) +		return NULL; +	screen->nvws = nvws; + +	/* 3D object */ +	if ((chipset & 0xf0) != 0x50 && (chipset & 0xf0) != 0x80) { +		NOUVEAU_ERR("Not a G8x chipset\n"); +		nv50_screen_destroy(&screen->pipe); +		return NULL; +	} + +	switch (chipset & 0xf0) { +	case 0x50: +		if (NV5X_GRCLASS5097_CHIPSETS & (1 << (chipset & 0x0f))) +			tesla_class = 0x5097; +		break; +	case 0x80: +		if (NV8X_GRCLASS8297_CHIPSETS & (1 << (chipset & 0x0f))) +			tesla_class = 0x8297; +		break; +	case 0x90: +		if (NV9X_GRCLASS8297_CHIPSETS & (1 << (chipset & 0x0f))) +			tesla_class = 0x8297; +		break; +	default: +		break; +	} + +	if (tesla_class == 0) { +		NOUVEAU_ERR("Unknown G8x chipset: NV%02x\n", chipset); +		nv50_screen_destroy(&screen->pipe); +		return NULL; +	} + +	ret = nvws->grobj_alloc(nvws, tesla_class, &screen->tesla); +	if (ret) { +		NOUVEAU_ERR("Error creating 3D object: %d\n", ret); +		nv50_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Sync notifier */ +	ret = nvws->notifier_alloc(nvws, 1, &screen->sync); +	if (ret) { +		NOUVEAU_ERR("Error creating notifier object: %d\n", ret); +		nv50_screen_destroy(&screen->pipe); +		return NULL; +	} + +	/* Static tesla init */ +	so = so_new(256, 20); + +	so_method(so, screen->tesla, 0x1558, 1); +	so_data  (so, 1); +	so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1); +	so_data  (so, screen->sync->handle); +	so_method(so, screen->tesla, NV50TCL_DMA_UNK0(0), +				     NV50TCL_DMA_UNK0__SIZE); +	for (i = 0; i < NV50TCL_DMA_UNK0__SIZE; i++) +		so_data(so, nvws->channel->vram->handle); +	so_method(so, screen->tesla, NV50TCL_DMA_UNK1(0), +				     NV50TCL_DMA_UNK1__SIZE); +	for (i = 0; i < NV50TCL_DMA_UNK1__SIZE; i++) +		so_data(so, nvws->channel->vram->handle); +	so_method(so, screen->tesla, 0x121c, 1); +	so_data  (so, 1); + +	so_method(so, screen->tesla, 0x13bc, 1); +	so_data  (so, 0x54); +	so_method(so, screen->tesla, 0x13ac, 1); +	so_data  (so, 1); +	so_method(so, screen->tesla, 0x16b8, 1); +	so_data  (so, 8); + +	/* Shared constant buffer */ +	screen->constbuf = ws->buffer_create(ws, 0, 0, 128 * 4 * 4); +	if (nvws->res_init(&screen->vp_data_heap, 0, 128)) { +		NOUVEAU_ERR("Error initialising constant buffer\n"); +		nv50_screen_destroy(&screen->pipe); +		return NULL; +	} + +	so_method(so, screen->tesla, 0x1280, 3); +	so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); +	so_data  (so, (NV50_CB_PMISC << 16) | 0x00001000); + +	/* Texture sampler/image unit setup - we abuse the constant buffer +	 * upload mechanism for the moment to upload data to the tex config +	 * blocks.  At some point we *may* want to go the NVIDIA way of doing +	 * things? +	 */ +	screen->tic = ws->buffer_create(ws, 0, 0, 32 * 8 * 4); +	so_method(so, screen->tesla, 0x1280, 3); +	so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); +	so_data  (so, (NV50_CB_TIC << 16) | 0x0800); +	so_method(so, screen->tesla, 0x1574, 3); +	so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); +	so_data  (so, 0x00000800); + +	screen->tsc = ws->buffer_create(ws, 0, 0, 32 * 8 * 4); +	so_method(so, screen->tesla, 0x1280, 3); +	so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); +	so_data  (so, (NV50_CB_TSC << 16) | 0x0800); +	so_method(so, screen->tesla, 0x155c, 3); +	so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); +	so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | +		  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); +	so_data  (so, 0x00000800); + + +	/* Vertex array limits - max them out */ +	for (i = 0; i < 16; i++) { +		so_method(so, screen->tesla, 0x1080 + (i * 8), 2); +		so_data  (so, 0x000000ff); +		so_data  (so, 0xffffffff); +	} + +	so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR, 2); +	so_data  (so, fui(0.0)); +	so_data  (so, fui(1.0)); + +	so_method(so, screen->tesla, 0x1234, 1); +	so_data  (so, 1); +	so_method(so, screen->tesla, 0x1458, 1); +	so_data  (so, 1); + +	so_emit(nvws, so); +	so_ref(so, &screen->static_init); +	nvws->push_flush(nvws, 0, NULL); + +	screen->pipe.winsys = ws; + +	screen->pipe.destroy = nv50_screen_destroy; + +	screen->pipe.get_name = nv50_screen_get_name; +	screen->pipe.get_vendor = nv50_screen_get_vendor; +	screen->pipe.get_param = nv50_screen_get_param; +	screen->pipe.get_paramf = nv50_screen_get_paramf; + +	screen->pipe.is_format_supported = nv50_screen_is_format_supported; + +	nv50_screen_init_miptree_functions(&screen->pipe); +	nv50_surface_init_screen_functions(&screen->pipe); + +	return &screen->pipe; +} + diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h new file mode 100644 index 0000000000..400ddcef06 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -0,0 +1,33 @@ +#ifndef __NV50_SCREEN_H__ +#define __NV50_SCREEN_H__ + +#include "pipe/p_screen.h" + +struct nv50_screen { +	struct pipe_screen pipe; + +	struct nouveau_winsys *nvws; + +	unsigned cur_pctx; + +	struct nouveau_grobj *tesla; +	struct nouveau_notifier *sync; + +	struct pipe_buffer *constbuf; +	struct nouveau_resource *vp_data_heap; + +	struct pipe_buffer *tic; +	struct pipe_buffer *tsc; + +	struct nouveau_stateobj *static_init; +}; + +static INLINE struct nv50_screen * +nv50_screen(struct pipe_screen *screen) +{ +	return (struct nv50_screen *)screen; +} + +void nv50_surface_init_screen_functions(struct pipe_screen *); + +#endif diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c new file mode 100644 index 0000000000..4055527d9f --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -0,0 +1,639 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "tgsi/tgsi_parse.h" + +#include "nv50_context.h" +#include "nv50_texture.h" + +#include "nouveau/nouveau_stateobj.h" + +static void * +nv50_blend_state_create(struct pipe_context *pipe, +			const struct pipe_blend_state *cso) +{ +	struct nouveau_stateobj *so = so_new(64, 0); +	struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla; +	struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj); +	unsigned cmask = 0, i; + +	/*XXX ignored: +	 * 	- dither +	 */ + +	if (cso->blend_enable == 0) { +		so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); +		for (i = 0; i < 8; i++) +			so_data(so, 0); +	} else { +		so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); +		for (i = 0; i < 8; i++) +			so_data(so, 1); +		so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5); +		so_data  (so, nvgl_blend_eqn(cso->rgb_func)); +		so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor)); +		so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor)); +		so_data  (so, nvgl_blend_eqn(cso->alpha_func)); +		so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor)); +		so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1); +		so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor)); +	} + +	if (cso->logicop_enable == 0 ) { +		so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 1); +		so_data  (so, 0); +	} else { +		so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 2); +		so_data  (so, 1); +		so_data  (so, nvgl_logicop_func(cso->logicop_func)); +	} + +	if (cso->colormask & PIPE_MASK_R) +		cmask |= (1 << 0); +	if (cso->colormask & PIPE_MASK_G) +		cmask |= (1 << 4); +	if (cso->colormask & PIPE_MASK_B) +		cmask |= (1 << 8); +	if (cso->colormask & PIPE_MASK_A) +		cmask |= (1 << 12); +	so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8); +	for (i = 0; i < 8; i++) +		so_data(so, cmask); + +	bso->pipe = *cso; +	so_ref(so, &bso->so); +	return (void *)bso; +} + +static void +nv50_blend_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->blend = hwcso; +	nv50->dirty |= NV50_NEW_BLEND; +} + +static void +nv50_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_blend_stateobj *bso = hwcso; + +	so_ref(NULL, &bso->so); +	FREE(bso); +} + +static INLINE unsigned +wrap_mode(unsigned wrap) +{ +	switch (wrap) { +	case PIPE_TEX_WRAP_REPEAT: +		return NV50TSC_1_0_WRAPS_REPEAT; +	case PIPE_TEX_WRAP_MIRROR_REPEAT: +		return NV50TSC_1_0_WRAPS_MIRROR_REPEAT; +	case PIPE_TEX_WRAP_CLAMP_TO_EDGE: +		return NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE; +	case PIPE_TEX_WRAP_CLAMP_TO_BORDER: +		return NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER; +	case PIPE_TEX_WRAP_CLAMP: +		return NV50TSC_1_0_WRAPS_CLAMP; +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: +		return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE; +	case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: +		return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER; +	case PIPE_TEX_WRAP_MIRROR_CLAMP: +		return NV50TSC_1_0_WRAPS_MIRROR_CLAMP; +	default: +		NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); +		return NV50TSC_1_0_WRAPS_REPEAT; +	} +} +static void * +nv50_sampler_state_create(struct pipe_context *pipe, +			  const struct pipe_sampler_state *cso) +{ +	unsigned *tsc = CALLOC(8, sizeof(unsigned)); + +	tsc[0] = (0x00024000 | +		  (wrap_mode(cso->wrap_s) << 0) | +		  (wrap_mode(cso->wrap_t) << 3) | +		  (wrap_mode(cso->wrap_r) << 6)); + +	switch (cso->mag_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		tsc[1] |= NV50TSC_1_1_MAGF_LINEAR; +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		tsc[1] |= NV50TSC_1_1_MAGF_NEAREST; +		break; +	} + +	switch (cso->min_img_filter) { +	case PIPE_TEX_FILTER_LINEAR: +		tsc[1] |= NV50TSC_1_1_MINF_LINEAR; +		break; +	case PIPE_TEX_FILTER_NEAREST: +	default: +		tsc[1] |= NV50TSC_1_1_MINF_NEAREST; +		break; +	} + +	switch (cso->min_mip_filter) { +	case PIPE_TEX_MIPFILTER_LINEAR: +		tsc[1] |= NV50TSC_1_1_MIPF_LINEAR; +		break; +	case PIPE_TEX_MIPFILTER_NEAREST: +		tsc[1] |= NV50TSC_1_1_MIPF_NEAREST; +		break; +	case PIPE_TEX_MIPFILTER_NONE: +	default: +		tsc[1] |= NV50TSC_1_1_MIPF_NONE; +		break; +	} + +	return (void *)tsc; +} + +static void +nv50_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ +	struct nv50_context *nv50 = nv50_context(pipe); +	int i; + +	nv50->sampler_nr = nr; +	for (i = 0; i < nv50->sampler_nr; i++) +		nv50->sampler[i] = sampler[i]; + +	nv50->dirty |= NV50_NEW_SAMPLER; +} + +static void +nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void +nv50_set_sampler_texture(struct pipe_context *pipe, unsigned nr, +			 struct pipe_texture **pt) +{ +	struct nv50_context *nv50 = nv50_context(pipe); +	int i; + +	for (i = 0; i < nr; i++) +		pipe_texture_reference((void *)&nv50->miptree[i], pt[i]); +	for (i = nr; i < nv50->miptree_nr; i++) +		pipe_texture_reference((void *)&nv50->miptree[i], NULL); + +	nv50->miptree_nr = nr; +	nv50->dirty |= NV50_NEW_TEXTURE; +} + +static void * +nv50_rasterizer_state_create(struct pipe_context *pipe, +			     const struct pipe_rasterizer_state *cso) +{ +	struct nouveau_stateobj *so = so_new(64, 0); +	struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla; +	struct nv50_rasterizer_stateobj *rso = +		CALLOC_STRUCT(nv50_rasterizer_stateobj); + +	/*XXX: ignored +	 * 	- light_twosize +	 * 	- point_smooth +	 * 	- multisample +	 * 	- point_sprite / sprite_coord_mode +	 */ + +	so_method(so, tesla, NV50TCL_SHADE_MODEL, 1); +	so_data  (so, cso->flatshade ? NV50TCL_SHADE_MODEL_FLAT : +				       NV50TCL_SHADE_MODEL_SMOOTH); + +	so_method(so, tesla, NV50TCL_LINE_WIDTH, 1); +	so_data  (so, fui(cso->line_width)); +	so_method(so, tesla, NV50TCL_LINE_SMOOTH_ENABLE, 1); +	so_data  (so, cso->line_smooth ? 1 : 0); +	if (cso->line_stipple_enable) { +		so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1); +		so_data  (so, 1); +		so_method(so, tesla, NV50TCL_LINE_STIPPLE_PATTERN, 1); +		so_data  (so, (cso->line_stipple_pattern << 8) | +			       cso->line_stipple_factor); +	} else { +		so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1); +		so_data  (so, 0); +	} + +	so_method(so, tesla, NV50TCL_POINT_SIZE, 1); +	so_data  (so, fui(cso->point_size)); + +	so_method(so, tesla, NV50TCL_POLYGON_MODE_FRONT, 3); +	if (cso->front_winding == PIPE_WINDING_CCW) { +		so_data(so, nvgl_polygon_mode(cso->fill_ccw)); +		so_data(so, nvgl_polygon_mode(cso->fill_cw)); +	} else { +		so_data(so, nvgl_polygon_mode(cso->fill_cw)); +		so_data(so, nvgl_polygon_mode(cso->fill_ccw)); +	} +	so_data(so, cso->poly_smooth ? 1 : 0); + +	so_method(so, tesla, NV50TCL_CULL_FACE_ENABLE, 3); +	so_data  (so, cso->cull_mode != PIPE_WINDING_NONE); +	if (cso->front_winding == PIPE_WINDING_CCW) { +		so_data(so, NV50TCL_FRONT_FACE_CCW); +		switch (cso->cull_mode) { +		case PIPE_WINDING_CCW: +			so_data(so, NV50TCL_CULL_FACE_FRONT); +			break; +		case PIPE_WINDING_CW: +			so_data(so, NV50TCL_CULL_FACE_BACK); +			break; +		case PIPE_WINDING_BOTH: +			so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK); +			break; +		default: +			so_data(so, NV50TCL_CULL_FACE_BACK); +			break; +		} +	} else { +		so_data(so, NV50TCL_FRONT_FACE_CW); +		switch (cso->cull_mode) { +		case PIPE_WINDING_CCW: +			so_data(so, NV50TCL_CULL_FACE_BACK); +			break; +		case PIPE_WINDING_CW: +			so_data(so, NV50TCL_CULL_FACE_FRONT); +			break; +		case PIPE_WINDING_BOTH: +			so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK); +			break; +		default: +			so_data(so, NV50TCL_CULL_FACE_BACK); +			break; +		} +	} + +	so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_ENABLE, 1); +	so_data  (so, cso->poly_stipple_enable ? 1 : 0); + +	so_method(so, tesla, NV50TCL_POLYGON_OFFSET_POINT_ENABLE, 3); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) +		so_data(so, 1); +	else +		so_data(so, 0); +	if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || +	    (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) +		so_data(so, 1); +	else +		so_data(so, 0); + +	if (cso->offset_cw || cso->offset_ccw) { +		so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1); +		so_data  (so, fui(cso->offset_scale)); +		so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1); +		so_data  (so, fui(cso->offset_units)); +	} + +	rso->pipe = *cso; +	so_ref(so, &rso->so); +	return (void *)rso; +} + +static void +nv50_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->rasterizer = hwcso; +	nv50->dirty |= NV50_NEW_RASTERIZER; +} + +static void +nv50_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_rasterizer_stateobj *rso = hwcso; + +	so_ref(NULL, &rso->so); +	FREE(rso); +} + +static void * +nv50_depth_stencil_alpha_state_create(struct pipe_context *pipe, +			const struct pipe_depth_stencil_alpha_state *cso) +{ +	struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla; +	struct nv50_zsa_stateobj *zsa = CALLOC_STRUCT(nv50_zsa_stateobj); +	struct nouveau_stateobj *so = so_new(64, 0); + +	so_method(so, tesla, NV50TCL_DEPTH_WRITE_ENABLE, 1); +	so_data  (so, cso->depth.writemask ? 1 : 0); +	if (cso->depth.enabled) { +		so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1); +		so_data  (so, 1); +		so_method(so, tesla, NV50TCL_DEPTH_TEST_FUNC, 1); +		so_data  (so, nvgl_comparison_op(cso->depth.func)); +	} else { +		so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1); +		so_data  (so, 0); +	} + +	/*XXX: yes, I know they're backwards.. header needs fixing */ +	if (cso->stencil[0].enabled) { +		so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 5); +		so_data  (so, 1); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].fail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); +		so_data  (so, nvgl_comparison_op(cso->stencil[0].func)); +		so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 3); +		so_data  (so, cso->stencil[0].ref_value); +		so_data  (so, cso->stencil[0].write_mask); +		so_data  (so, cso->stencil[0].value_mask); +	} else { +		so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 1); +		so_data  (so, 0); +	} + +	if (cso->stencil[1].enabled) { +		so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 8); +		so_data  (so, 1); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].fail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); +		so_data  (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); +		so_data  (so, nvgl_comparison_op(cso->stencil[1].func)); +		so_data  (so, cso->stencil[1].ref_value); +		so_data  (so, cso->stencil[1].write_mask); +		so_data  (so, cso->stencil[1].value_mask); +	} else { +		so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 1); +		so_data  (so, 0); +	} + +	if (cso->alpha.enabled) { +		so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1); +		so_data  (so, 1); +		so_method(so, tesla, NV50TCL_ALPHA_TEST_REF, 2); +		so_data  (so, fui(cso->alpha.ref)); +		so_data  (so, nvgl_comparison_op(cso->alpha.func)); +	} else { +		so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1); +		so_data  (so, 0); +	} + +	zsa->pipe = *cso; +	so_ref(so, &zsa->so); +	return (void *)zsa; +} + +static void +nv50_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->zsa = hwcso; +	nv50->dirty |= NV50_NEW_ZSA; +} + +static void +nv50_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_zsa_stateobj *zsa = hwcso; + +	so_ref(NULL, &zsa->so); +	FREE(zsa); +} + +static void * +nv50_vp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv50_program *p = CALLOC_STRUCT(nv50_program); + +	p->pipe.tokens = tgsi_dup_tokens(cso->tokens); +	p->type = PIPE_SHADER_VERTEX; +	tgsi_scan_shader(p->pipe.tokens, &p->info); +	return (void *)p; +} + +static void +nv50_vp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->vertprog = hwcso; +	nv50->dirty |= NV50_NEW_VERTPROG; +} + +static void +nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_context *nv50 = nv50_context(pipe); +	struct nv50_program *p = hwcso; + +	nv50_program_destroy(nv50, p); +	FREE((void*)p->pipe.tokens); +	FREE(p); +} + +static void * +nv50_fp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv50_program *p = CALLOC_STRUCT(nv50_program); + +	p->pipe.tokens = tgsi_dup_tokens(cso->tokens); +	p->type = PIPE_SHADER_FRAGMENT; +	tgsi_scan_shader(p->pipe.tokens, &p->info); +	return (void *)p; +} + +static void +nv50_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->fragprog = hwcso; +	nv50->dirty |= NV50_NEW_FRAGPROG; +} + +static void +nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv50_context *nv50 = nv50_context(pipe); +	struct nv50_program *p = hwcso; + +	nv50_program_destroy(nv50, p); +	FREE((void*)p->pipe.tokens); +	FREE(p); +} + +static void +nv50_set_blend_color(struct pipe_context *pipe, +		     const struct pipe_blend_color *bcol) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->blend_colour = *bcol; +	nv50->dirty |= NV50_NEW_BLEND_COLOUR; +} + +static void +nv50_set_clip_state(struct pipe_context *pipe, +		    const struct pipe_clip_state *clip) +{ +} + +static void +nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, +			 const struct pipe_constant_buffer *buf ) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	if (shader == PIPE_SHADER_VERTEX) { +		nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer; +		nv50->dirty |= NV50_NEW_VERTPROG_CB; +	} else +	if (shader == PIPE_SHADER_FRAGMENT) { +		nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer; +		nv50->dirty |= NV50_NEW_FRAGPROG_CB; +	} +} + +static void +nv50_set_framebuffer_state(struct pipe_context *pipe, +			   const struct pipe_framebuffer_state *fb) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->framebuffer = *fb; +	nv50->dirty |= NV50_NEW_FRAMEBUFFER; +} + +static void +nv50_set_polygon_stipple(struct pipe_context *pipe, +			 const struct pipe_poly_stipple *stipple) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->stipple = *stipple; +	nv50->dirty |= NV50_NEW_STIPPLE; +} + +static void +nv50_set_scissor_state(struct pipe_context *pipe, +		       const struct pipe_scissor_state *s) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->scissor = *s; +	nv50->dirty |= NV50_NEW_SCISSOR; +} + +static void +nv50_set_viewport_state(struct pipe_context *pipe, +			const struct pipe_viewport_state *vpt) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50->viewport = *vpt; +	nv50->dirty |= NV50_NEW_VIEWPORT; +} + +static void +nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count, +			const struct pipe_vertex_buffer *vb) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	memcpy(nv50->vtxbuf, vb, sizeof(*vb) * count); +	nv50->vtxbuf_nr = count; + +	nv50->dirty |= NV50_NEW_ARRAYS; +} + +static void +nv50_set_vertex_elements(struct pipe_context *pipe, unsigned count, +			 const struct pipe_vertex_element *ve) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	memcpy(nv50->vtxelt, ve, sizeof(*ve) * count); +	nv50->vtxelt_nr = count; + +	nv50->dirty |= NV50_NEW_ARRAYS; +} + +void +nv50_init_state_functions(struct nv50_context *nv50) +{ +	nv50->pipe.create_blend_state = nv50_blend_state_create; +	nv50->pipe.bind_blend_state = nv50_blend_state_bind; +	nv50->pipe.delete_blend_state = nv50_blend_state_delete; + +	nv50->pipe.create_sampler_state = nv50_sampler_state_create; +	nv50->pipe.bind_sampler_states = nv50_sampler_state_bind; +	nv50->pipe.delete_sampler_state = nv50_sampler_state_delete; +	nv50->pipe.set_sampler_textures = nv50_set_sampler_texture; + +	nv50->pipe.create_rasterizer_state = nv50_rasterizer_state_create; +	nv50->pipe.bind_rasterizer_state = nv50_rasterizer_state_bind; +	nv50->pipe.delete_rasterizer_state = nv50_rasterizer_state_delete; + +	nv50->pipe.create_depth_stencil_alpha_state = +		nv50_depth_stencil_alpha_state_create; +	nv50->pipe.bind_depth_stencil_alpha_state = +		nv50_depth_stencil_alpha_state_bind; +	nv50->pipe.delete_depth_stencil_alpha_state = +		nv50_depth_stencil_alpha_state_delete; + +	nv50->pipe.create_vs_state = nv50_vp_state_create; +	nv50->pipe.bind_vs_state = nv50_vp_state_bind; +	nv50->pipe.delete_vs_state = nv50_vp_state_delete; + +	nv50->pipe.create_fs_state = nv50_fp_state_create; +	nv50->pipe.bind_fs_state = nv50_fp_state_bind; +	nv50->pipe.delete_fs_state = nv50_fp_state_delete; + +	nv50->pipe.set_blend_color = nv50_set_blend_color; +	nv50->pipe.set_clip_state = nv50_set_clip_state; +	nv50->pipe.set_constant_buffer = nv50_set_constant_buffer; +	nv50->pipe.set_framebuffer_state = nv50_set_framebuffer_state; +	nv50->pipe.set_polygon_stipple = nv50_set_polygon_stipple; +	nv50->pipe.set_scissor_state = nv50_set_scissor_state; +	nv50->pipe.set_viewport_state = nv50_set_viewport_state; + +	nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers; +	nv50->pipe.set_vertex_elements = nv50_set_vertex_elements; +} + diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c new file mode 100644 index 0000000000..8f9ee05acc --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -0,0 +1,315 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "nv50_context.h" +#include "nouveau/nouveau_stateobj.h" + +static void +nv50_state_validate_fb(struct nv50_context *nv50) +{ +	struct nouveau_grobj *tesla = nv50->screen->tesla; +	struct nouveau_stateobj *so = so_new(128, 18); +	struct pipe_framebuffer_state *fb = &nv50->framebuffer; +	unsigned i, w, h, gw = 0; + +	for (i = 0; i < fb->num_cbufs; i++) { +		if (!gw) { +			w = fb->cbufs[i]->width; +			h = fb->cbufs[i]->height; +			gw = 1; +		} else { +			assert(w == fb->cbufs[i]->width); +			assert(h == fb->cbufs[i]->height); +		} + +		so_method(so, tesla, NV50TCL_RT_HORIZ(i), 2); +		so_data  (so, fb->cbufs[i]->width); +		so_data  (so, fb->cbufs[i]->height); + +		so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5); +		so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset, +			  NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0); +		so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset, +			  NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0); +		switch (fb->cbufs[i]->format) { +		case PIPE_FORMAT_A8R8G8B8_UNORM: +			so_data(so, 0xcf); +			break; +		case PIPE_FORMAT_R5G6B5_UNORM: +			so_data(so, 0xe8); +			break; +		default: +			{ +				char fmt[128]; +				pf_sprint_name(fmt, fb->cbufs[i]->format); +				NOUVEAU_ERR("AIIII unknown format %s\n", fmt); +			}		     +			so_data(so, 0xe6); +			break; +		} +		so_data(so, 0x00000000); +		so_data(so, 0x00000000); + +		so_method(so, tesla, 0x1224, 1); +		so_data  (so, 1); +	} + +	if (fb->zsbuf) { +		if (!gw) { +			w = fb->zsbuf->width; +			h = fb->zsbuf->height; +			gw = 1; +		} else { +			assert(w == fb->zsbuf->width); +			assert(h == fb->zsbuf->height); +		} + +		so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5); +		so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset, +			  NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0); +		so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset, +			  NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0); +		switch (fb->zsbuf->format) { +		case PIPE_FORMAT_Z24S8_UNORM: +			so_data(so, 0x16); +			break; +		case PIPE_FORMAT_Z16_UNORM: +			so_data(so, 0x15); +			break; +		default: +			{ +				char fmt[128]; +				pf_sprint_name(fmt, fb->zsbuf->format); +				NOUVEAU_ERR("AIIII unknown format %s\n", fmt); +			}		     +			so_data(so, 0x16); +			break; +		} +		so_data(so, 0x00000000); +		so_data(so, 0x00000000); + +		so_method(so, tesla, 0x1538, 1); +		so_data  (so, 1); +		so_method(so, tesla, 0x1228, 3); +		so_data  (so, fb->zsbuf->width); +		so_data  (so, fb->zsbuf->height); +		so_data  (so, 0x00010001); +	} + +	so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2); +	so_data  (so, w << 16); +	so_data  (so, h << 16); +	so_method(so, tesla, 0x0e04, 2); +	so_data  (so, w << 16); +	so_data  (so, h << 16); +	so_method(so, tesla, 0xdf8, 2); +	so_data  (so, 0); +	so_data  (so, h); + +	so_ref(so, &nv50->state.fb); +} + +static void +nv50_state_emit(struct nv50_context *nv50) +{ +	struct nv50_screen *screen = nv50->screen; +	struct nouveau_winsys *nvws = screen->nvws; + +	if (nv50->pctx_id != screen->cur_pctx) { +		nv50->state.dirty |= 0xffffffff; +		screen->cur_pctx = nv50->pctx_id; +	} + +	if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER) +		so_emit(nvws, nv50->state.fb); +	if (nv50->state.dirty & NV50_NEW_BLEND) +		so_emit(nvws, nv50->state.blend); +	if (nv50->state.dirty & NV50_NEW_ZSA) +		so_emit(nvws, nv50->state.zsa); +	if (nv50->state.dirty & NV50_NEW_VERTPROG) +		so_emit(nvws, nv50->state.vertprog); +	if (nv50->state.dirty & NV50_NEW_FRAGPROG) +		so_emit(nvws, nv50->state.fragprog); +	if (nv50->state.dirty & NV50_NEW_RASTERIZER) +		so_emit(nvws, nv50->state.rast); +	if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR) +		so_emit(nvws, nv50->state.blend_colour); +	if (nv50->state.dirty & NV50_NEW_STIPPLE) +		so_emit(nvws, nv50->state.stipple); +	if (nv50->state.dirty & NV50_NEW_SCISSOR) +		so_emit(nvws, nv50->state.scissor); +	if (nv50->state.dirty & NV50_NEW_VIEWPORT) +		so_emit(nvws, nv50->state.viewport); +	if (nv50->state.dirty & NV50_NEW_SAMPLER) +		so_emit(nvws, nv50->state.tsc_upload); +	if (nv50->state.dirty & NV50_NEW_TEXTURE) +		so_emit(nvws, nv50->state.tic_upload); +	if (nv50->state.dirty & NV50_NEW_ARRAYS) { +		so_emit(nvws, nv50->state.vtxfmt); +		so_emit(nvws, nv50->state.vtxbuf); +	} +	nv50->state.dirty = 0; + +	so_emit_reloc_markers(nvws, nv50->state.fb); +	so_emit_reloc_markers(nvws, nv50->state.vertprog); +	so_emit_reloc_markers(nvws, nv50->state.fragprog); +	so_emit_reloc_markers(nvws, nv50->state.vtxbuf); +	so_emit_reloc_markers(nvws, nv50->screen->static_init); +} + +boolean +nv50_state_validate(struct nv50_context *nv50) +{ +	const struct pipe_framebuffer_state *fb = &nv50->framebuffer; +	struct nouveau_grobj *tesla = nv50->screen->tesla; +	struct nouveau_stateobj *so; +	unsigned i; + +	for (i = 0; i < fb->num_cbufs; i++) +		fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED; + +	if (fb->zsbuf) +		fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED; + +	if (nv50->dirty & NV50_NEW_FRAMEBUFFER) +		nv50_state_validate_fb(nv50); + +	if (nv50->dirty & NV50_NEW_BLEND) +		so_ref(nv50->blend->so, &nv50->state.blend); + +	if (nv50->dirty & NV50_NEW_ZSA) +		so_ref(nv50->zsa->so, &nv50->state.zsa); + +	if (nv50->dirty & (NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB)) +		nv50_vertprog_validate(nv50); + +	if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB)) +		nv50_fragprog_validate(nv50); + +	if (nv50->dirty & NV50_NEW_RASTERIZER) +		so_ref(nv50->rasterizer->so, &nv50->state.rast); + +	if (nv50->dirty & NV50_NEW_BLEND_COLOUR) { +		so = so_new(5, 0); +		so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4); +		so_data  (so, fui(nv50->blend_colour.color[0])); +		so_data  (so, fui(nv50->blend_colour.color[1])); +		so_data  (so, fui(nv50->blend_colour.color[2])); +		so_data  (so, fui(nv50->blend_colour.color[3])); +		so_ref(so, &nv50->state.blend_colour); +	} + +	if (nv50->dirty & NV50_NEW_STIPPLE) { +		so = so_new(33, 0); +		so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32); +		for (i = 0; i < 32; i++) +			so_data(so, nv50->stipple.stipple[i]); +		so_ref(so, &nv50->state.stipple); +	} + +	if (nv50->dirty & (NV50_NEW_SCISSOR | NV50_NEW_RASTERIZER)) { +		struct pipe_rasterizer_state *rast = &nv50->rasterizer->pipe; +		struct pipe_scissor_state *s = &nv50->scissor; + +		if (nv50->state.scissor && +		    (rast->scissor == 0 && nv50->state.scissor_enabled == 0)) +			goto scissor_uptodate; +		nv50->state.scissor_enabled = rast->scissor; + +		so = so_new(3, 0); +		so_method(so, tesla, 0x0ff4, 2); +		if (nv50->state.scissor_enabled) { +			so_data(so, ((s->maxx - s->minx) << 16) | s->minx); +			so_data(so, ((s->maxy - s->miny) << 16) | s->miny); +		} else { +			so_data(so, (8192 << 16)); +			so_data(so, (8192 << 16)); +		} +		so_ref(so, &nv50->state.scissor); +		nv50->state.dirty |= NV50_NEW_SCISSOR; +	} +scissor_uptodate: + +	if (nv50->dirty & NV50_NEW_VIEWPORT) { +		unsigned bypass; + +		if (!nv50->rasterizer->pipe.bypass_clipping) +			bypass = 0; +		else +			bypass = 1; + +		if (nv50->state.viewport && +		    (bypass || !(nv50->dirty & NV50_NEW_VIEWPORT)) && +		    nv50->state.viewport_bypass == bypass) +			goto viewport_uptodate; +		nv50->state.viewport_bypass = bypass; + +		so = so_new(12, 0); +		if (!bypass) { +			so_method(so, tesla, NV50TCL_VIEWPORT_UNK1(0), 3); +			so_data  (so, fui(nv50->viewport.translate[0])); +			so_data  (so, fui(nv50->viewport.translate[1])); +			so_data  (so, fui(nv50->viewport.translate[2])); +			so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(0), 3); +			so_data  (so, fui(nv50->viewport.scale[0])); +			so_data  (so, fui(-nv50->viewport.scale[1])); +			so_data  (so, fui(nv50->viewport.scale[2])); +			so_method(so, tesla, 0x192c, 1); +			so_data  (so, 1); +			so_method(so, tesla, 0x0f90, 1); +			so_data  (so, 0); +		} else { +			so_method(so, tesla, 0x192c, 1); +			so_data  (so, 0); +			so_method(so, tesla, 0x0f90, 1); +			so_data  (so, 1); +		} + +		so_ref(so, &nv50->state.viewport); +	} +viewport_uptodate: + +	if (nv50->dirty & NV50_NEW_SAMPLER) { +		int i; + +		so = so_new(nv50->sampler_nr * 8 + 3, 0); +		so_method(so, tesla, 0x0f00, 1); +		so_data  (so, NV50_CB_TSC); +		so_method(so, tesla, 0x40000f04, nv50->sampler_nr * 8); +		for (i = 0; i < nv50->sampler_nr; i++) +			so_datap (so, nv50->sampler[i], 8); +		so_ref(so, &nv50->state.tsc_upload); +	} + +	if (nv50->dirty & NV50_NEW_TEXTURE) +		nv50_tex_validate(nv50); + +	if (nv50->dirty & NV50_NEW_ARRAYS) +		nv50_vbo_validate(nv50); + +	nv50->state.dirty |= nv50->dirty; +	nv50->dirty = 0; +	nv50_state_emit(nv50); + +	return TRUE; +} + diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c new file mode 100644 index 0000000000..a9daeee369 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -0,0 +1,123 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "nv50_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_winsys.h" +#include "pipe/p_inlines.h" +#include "util/p_tile.h" + +static void +nv50_surface_copy(struct pipe_context *pipe, boolean flip, +		  struct pipe_surface *dest, unsigned destx, unsigned desty, +		  struct pipe_surface *src, unsigned srcx, unsigned srcy, +		  unsigned width, unsigned height) +{ +	struct nv50_context *nv50 = (struct nv50_context *)pipe; +	struct nouveau_winsys *nvws = nv50->screen->nvws; + +	if (flip) { +		desty += height; +		while (height--) { +			nvws->surface_copy(nvws, dest, destx, desty--, src, +					   srcx, srcy++, width, 1); +		} +	} else { +		nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, +				   width, height); +	} +} + +static void +nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +		  unsigned destx, unsigned desty, unsigned width, +		  unsigned height, unsigned value) +{ +	struct nv50_context *nv50 = (struct nv50_context *)pipe; +	struct nouveau_winsys *nvws = nv50->screen->nvws; + +	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +} + +static void * +nv50_surface_map(struct pipe_screen *screen, struct pipe_surface *ps, +		 unsigned flags ) +{ +	struct nouveau_winsys *nvws = nv50_screen(screen)->nvws; +	struct pipe_winsys *ws = screen->winsys; +	struct nv50_surface *s = nv50_surface(ps); +	struct nv50_surface m = *s; +	void *map; + +	if (!s->untiled) { +		s->untiled = ws->buffer_create(ws, 0, 0, ps->buffer->size); + +		m.base.buffer = s->untiled; +		nvws->surface_copy(nvws, &m.base, 0, 0, &s->base, 0, 0, +					 ps->width, ps->height); +	} + +	/* Map original tiled surface to disallow it being validated while +	 * untiled mirror is mapped. +	 */ +	ws->buffer_map(ws, ps->buffer, flags); + +	map = ws->buffer_map(ws, s->untiled, flags); +	if (!map) +		return NULL; + +	return map; +} + +static void +nv50_surface_unmap(struct pipe_screen *screen, struct pipe_surface *ps) +{ +	struct nouveau_winsys *nvws = nv50_screen(screen)->nvws; +	struct pipe_winsys *ws = screen->winsys; +	struct nv50_surface *s = nv50_surface(ps); +	struct nv50_surface m = *s; + +	ws->buffer_unmap(ws, s->untiled); +	ws->buffer_unmap(ws, ps->buffer); + +	m.base.buffer = s->untiled; +	nvws->surface_copy(nvws, &s->base, 0, 0, &m.base, 0, 0, +				 ps->width, ps->height); + +	pipe_buffer_reference(ws, &s->untiled, NULL); +} + +void +nv50_init_surface_functions(struct nv50_context *nv50) +{ +	nv50->pipe.surface_copy = nv50_surface_copy; +	nv50->pipe.surface_fill = nv50_surface_fill; +} + +void +nv50_surface_init_screen_functions(struct pipe_screen *pscreen) +{ +	pscreen->surface_map = nv50_surface_map; +	pscreen->surface_unmap = nv50_surface_unmap; +} + diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c new file mode 100644 index 0000000000..fde3c97c05 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -0,0 +1,124 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "nv50_context.h" +#include "nv50_texture.h" + +#include "nouveau/nouveau_stateobj.h" + +static int +nv50_tex_construct(struct nouveau_stateobj *so, struct nv50_miptree *mt) +{ +	switch (mt->base.format) { +	case PIPE_FORMAT_A8R8G8B8_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_8_8_8_8); +		break; +	case PIPE_FORMAT_A1R5G5B5_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_1_5_5_5); +		break; +	case PIPE_FORMAT_A4R4G4B4_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_4_4_4_4); +		break; +	case PIPE_FORMAT_R5G6B5_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_5_6_5); +		break; +	case PIPE_FORMAT_L8_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_8); +		break; +	case PIPE_FORMAT_A8_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_8); +		break; +	case PIPE_FORMAT_I8_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_8); +		break; +	case PIPE_FORMAT_A8L8_UNORM: +		so_data(so, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | +			    NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | +			    NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM | +			    NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | +			    NV50TIC_0_0_FMT_8_8); +		break; +	default: +		return 1; +	} + +	so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0); +	so_data (so, 0xd0005000); +	so_data (so, 0x00300000); +	so_data (so, mt->base.width[0]); +	so_data (so, (mt->base.depth[0] << 16) | mt->base.height[0]); +	so_data (so, 0x03000000); +	so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0); + +	return 0; +} + +void +nv50_tex_validate(struct nv50_context *nv50) +{ +	struct nouveau_grobj *tesla = nv50->screen->tesla; +	struct nouveau_stateobj *so; +	int i; + +	so = so_new(nv50->miptree_nr * 8 + 3, nv50->miptree_nr * 2); +	so_method(so, tesla, 0x0f00, 1); +	so_data  (so, NV50_CB_TIC); +	so_method(so, tesla, 0x40000f04, nv50->miptree_nr * 8); +	for (i = 0; i < nv50->miptree_nr; i++) { +		if (nv50_tex_construct(so, nv50->miptree[i])) { +			NOUVEAU_ERR("failed tex validate\n"); +			so_ref(NULL, &so); +			return; +		} +	} + +	so_ref(so, &nv50->state.tic_upload); +} + diff --git a/src/gallium/drivers/nv50/nv50_texture.h b/src/gallium/drivers/nv50/nv50_texture.h new file mode 100644 index 0000000000..6861d67b4d --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_texture.h @@ -0,0 +1,126 @@ +#ifndef __NV50_TEXTURE_H__ +#define __NV50_TEXTURE_H__ + +/* It'd be really nice to have these in nouveau_class.h generated by + * renouveau like the rest of the object header - but not sure it can + * handle non-object stuff nicely - need to look into it. + */ + +/* Texture image control block */ +#define NV50TIC_0_0_MAPA_MASK                                     0x38000000 +#define NV50TIC_0_0_MAPA_ZERO                                     0x00000000 +#define NV50TIC_0_0_MAPA_C0                                       0x10000000 +#define NV50TIC_0_0_MAPA_C1                                       0x18000000 +#define NV50TIC_0_0_MAPA_C2                                       0x20000000 +#define NV50TIC_0_0_MAPA_C3                                       0x28000000 +#define NV50TIC_0_0_MAPA_ONE                                      0x38000000 +#define NV50TIC_0_0_MAPR_MASK                                     0x07000000 +#define NV50TIC_0_0_MAPR_ZERO                                     0x00000000 +#define NV50TIC_0_0_MAPR_C0                                       0x02000000 +#define NV50TIC_0_0_MAPR_C1                                       0x03000000 +#define NV50TIC_0_0_MAPR_C2                                       0x04000000 +#define NV50TIC_0_0_MAPR_C3                                       0x05000000 +#define NV50TIC_0_0_MAPR_ONE                                      0x07000000 +#define NV50TIC_0_0_MAPG_MASK                                     0x00e00000 +#define NV50TIC_0_0_MAPG_ZERO                                     0x00000000 +#define NV50TIC_0_0_MAPG_C0                                       0x00400000 +#define NV50TIC_0_0_MAPG_C1                                       0x00600000 +#define NV50TIC_0_0_MAPG_C2                                       0x00800000 +#define NV50TIC_0_0_MAPG_C3                                       0x00a00000 +#define NV50TIC_0_0_MAPG_ONE                                      0x00e00000 +#define NV50TIC_0_0_MAPB_MASK                                     0x001c0000 +#define NV50TIC_0_0_MAPB_ZERO                                     0x00000000 +#define NV50TIC_0_0_MAPB_C0                                       0x00080000 +#define NV50TIC_0_0_MAPB_C1                                       0x000c0000 +#define NV50TIC_0_0_MAPB_C2                                       0x00100000 +#define NV50TIC_0_0_MAPB_C3                                       0x00140000 +#define NV50TIC_0_0_MAPB_ONE                                      0x001c0000 +#define NV50TIC_0_0_TYPEA_MASK                                    0x00038000 +#define NV50TIC_0_0_TYPEA_UNORM                                   0x00010000 +#define NV50TIC_0_0_TYPER_MASK                                    0x00007000 +#define NV50TIC_0_0_TYPER_UNORM                                   0x00002000 +#define NV50TIC_0_0_TYPEG_MASK                                    0x00000e00 +#define NV50TIC_0_0_TYPEG_UNORM                                   0x00000400 +#define NV50TIC_0_0_TYPEB_MASK                                    0x000001c0 +#define NV50TIC_0_0_TYPEB_UNORM                                   0x00000080 +#define NV50TIC_0_0_FMT_MASK                                      0x0000003c +#define NV50TIC_0_0_FMT_8_8_8_8                                   0x00000008 +#define NV50TIC_0_0_FMT_4_4_4_4                                   0x00000012 +#define NV50TIC_0_0_FMT_1_5_5_5                                   0x00000013 +#define NV50TIC_0_0_FMT_5_6_5                                     0x00000015 +#define NV50TIC_0_0_FMT_8_8                                       0x00000018 +#define NV50TIC_0_0_FMT_8                                         0x0000001d + +#define NV50TIC_0_1_OFFSET_LOW_MASK                               0xffffffff +#define NV50TIC_0_1_OFFSET_LOW_SHIFT                                       0 + +#define NV50TIC_0_2_UNKNOWN_MASK                                  0xffffffff + +#define NV50TIC_0_3_UNKNOWN_MASK                                  0xffffffff + +#define NV50TIC_0_4_WIDTH_MASK                                    0x0000ffff +#define NV50TIC_0_4_WIDTH_SHIFT                                            0 + +#define NV50TIC_0_5_DEPTH_MASK                                    0xffff0000 +#define NV50TIC_0_5_DEPTH_SHIFT                                           16 +#define NV50TIC_0_5_HEIGHT_MASK                                   0x0000ffff +#define NV50TIC_0_5_HEIGHT_SHIFT                                           0 + +#define NV50TIC_0_6_UNKNOWN_MASK                                  0xffffffff + +#define NV50TIC_0_7_OFFSET_HIGH_MASK                              0xffffffff +#define NV50TIC_0_7_OFFSET_HIGH_SHIFT                                      0 + +/* Texture sampler control block */ +#define NV50TSC_1_0_WRAPS_MASK                                   0x00000007 +#define NV50TSC_1_0_WRAPS_REPEAT                                 0x00000000 +#define NV50TSC_1_0_WRAPS_MIRROR_REPEAT                          0x00000001 +#define NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE                          0x00000002 +#define NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER                        0x00000003 +#define NV50TSC_1_0_WRAPS_CLAMP                                  0x00000004 +#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE                   0x00000005 +#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER                 0x00000006 +#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP                           0x00000007 +#define NV50TSC_1_0_WRAPT_MASK                                   0x00000038 +#define NV50TSC_1_0_WRAPT_REPEAT                                 0x00000000 +#define NV50TSC_1_0_WRAPT_MIRROR_REPEAT                          0x00000008 +#define NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE                          0x00000010 +#define NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER                        0x00000018 +#define NV50TSC_1_0_WRAPT_CLAMP                                  0x00000020 +#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_EDGE                   0x00000028 +#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_BORDER                 0x00000030 +#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP                           0x00000038 +#define NV50TSC_1_0_WRAPR_MASK                                   0x000001c0 +#define NV50TSC_1_0_WRAPR_REPEAT                                 0x00000000 +#define NV50TSC_1_0_WRAPR_MIRROR_REPEAT                          0x00000040 +#define NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE                          0x00000080 +#define NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER                        0x000000c0 +#define NV50TSC_1_0_WRAPR_CLAMP                                  0x00000100 +#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_EDGE                   0x00000140 +#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_BORDER                 0x00000180 +#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP                           0x000001c0 + +#define NV50TSC_1_1_MAGF_MASK                                    0x00000003 +#define NV50TSC_1_1_MAGF_NEAREST                                 0x00000001 +#define NV50TSC_1_1_MAGF_LINEAR                                  0x00000002 +#define NV50TSC_1_1_MINF_MASK                                    0x00000030 +#define NV50TSC_1_1_MINF_NEAREST                                 0x00000010 +#define NV50TSC_1_1_MINF_LINEAR                                  0x00000020 +#define NV50TSC_1_1_MIPF_MASK                                    0x000000c0 +#define NV50TSC_1_1_MIPF_NONE                                    0x00000040 +#define NV50TSC_1_1_MIPF_NEAREST                                 0x00000080 +#define NV50TSC_1_1_MIPF_LINEAR                                  0x000000c0 + +#define NV50TSC_1_2_UNKNOWN_MASK                                 0xffffffff + +#define NV50TSC_1_3_UNKNOWN_MASK                                 0xffffffff + +#define NV50TSC_1_4_UNKNOWN_MASK                                 0xffffffff + +#define NV50TSC_1_5_UNKNOWN_MASK                                 0xffffffff + +#define NV50TSC_1_6_UNKNOWN_MASK                                 0xffffffff + +#define NV50TSC_1_7_UNKNOWN_MASK                                 0xffffffff + +#endif diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c new file mode 100644 index 0000000000..8e420ad172 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -0,0 +1,239 @@ +/* + * Copyright 2008 Ben Skeggs + * + * 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 + * THE AUTHORS 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 "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" + +#include "nv50_context.h" + +static INLINE unsigned +nv50_prim(unsigned mode) +{ +	switch (mode) { +	case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS; +	case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES; +	case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP; +	case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP; +	case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES; +	case PIPE_PRIM_TRIANGLE_STRIP: +		return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP; +	case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN; +	case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS; +	case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP; +	case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON; +	default: +		break; +	} + +	NOUVEAU_ERR("invalid primitive type %d\n", mode); +	return NV50TCL_VERTEX_BEGIN_POINTS; +} + +boolean +nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, +		 unsigned count) +{ +	struct nv50_context *nv50 = nv50_context(pipe); + +	nv50_state_validate(nv50); + +	BEGIN_RING(tesla, 0x142c, 1); +	OUT_RING  (0); +	BEGIN_RING(tesla, 0x142c, 1); +	OUT_RING  (0); + +	BEGIN_RING(tesla, NV50TCL_VERTEX_BEGIN, 1); +	OUT_RING  (nv50_prim(mode)); +	BEGIN_RING(tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); +	OUT_RING  (start); +	OUT_RING  (count); +	BEGIN_RING(tesla, NV50TCL_VERTEX_END, 1); +	OUT_RING  (0); + +	pipe->flush(pipe, 0, NULL); +	return TRUE; +} + +static INLINE void +nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map, +			      unsigned start, unsigned count) +{ +	map += start; + +	if (count & 1) { +		BEGIN_RING(tesla, 0x15e8, 1); +		OUT_RING  (map[0]); +		map++; +		count--; +	} + +	while (count) { +		unsigned nr = count > 2046 ? 2046 : count; +		int i; + +		BEGIN_RING(tesla, 0x400015f0, nr >> 1); +		for (i = 0; i < nr; i += 2) +			OUT_RING  ((map[1] << 16) | map[0]); + +		count -= nr; +		map += nr; +	} +} + +static INLINE void +nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map, +			      unsigned start, unsigned count) +{ +	map += start; + +	if (count & 1) { +		BEGIN_RING(tesla, 0x15e8, 1); +		OUT_RING  (map[0]); +		map++; +		count--; +	} + +	while (count) { +		unsigned nr = count > 2046 ? 2046 : count; +		int i; + +		BEGIN_RING(tesla, 0x400015f0, nr >> 1); +		for (i = 0; i < nr; i += 2) +			OUT_RING  ((map[1] << 16) | map[0]); + +		count -= nr; +		map += nr; +	} +} + +static INLINE void +nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint8_t *map, +			      unsigned start, unsigned count) +{ +	map += start; + +	while (count) { +		unsigned nr = count > 2047 ? 2047 : count; + +		BEGIN_RING(tesla, 0x400015e8, nr); +		OUT_RINGp (map, nr); + +		count -= nr; +		map += nr; +	} +} + +boolean +nv50_draw_elements(struct pipe_context *pipe, +		   struct pipe_buffer *indexBuffer, unsigned indexSize, +		   unsigned mode, unsigned start, unsigned count) +{ +	struct nv50_context *nv50 = nv50_context(pipe); +	struct pipe_winsys *ws = pipe->winsys; +	void *map = ws->buffer_map(ws, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); + +	nv50_state_validate(nv50); + +	BEGIN_RING(tesla, 0x142c, 1); +	OUT_RING  (0); +	BEGIN_RING(tesla, 0x142c, 1); +	OUT_RING  (0); + +	BEGIN_RING(tesla, NV50TCL_VERTEX_BEGIN, 1); +	OUT_RING  (nv50_prim(mode)); +	switch (indexSize) { +	case 1: +		nv50_draw_elements_inline_u08(nv50, map, start, count); +		break; +	case 2: +		nv50_draw_elements_inline_u16(nv50, map, start, count); +		break; +	case 4: +		nv50_draw_elements_inline_u32(nv50, map, start, count); +		break; +	default: +		assert(0); +	} +	BEGIN_RING(tesla, NV50TCL_VERTEX_END, 1); +	OUT_RING  (0); + +	pipe->flush(pipe, 0, NULL); +	return TRUE; +} + +void +nv50_vbo_validate(struct nv50_context *nv50) +{ +	struct nouveau_grobj *tesla = nv50->screen->tesla; +	struct nouveau_stateobj *vtxbuf, *vtxfmt; +	int i, vpi = 0; + +	vtxbuf = so_new(nv50->vtxelt_nr * 4, nv50->vtxelt_nr * 2); +	vtxfmt = so_new(nv50->vtxelt_nr + 1, 0); +	so_method(vtxfmt, tesla, 0x1ac0, nv50->vtxelt_nr); + +	for (i = 0; i < nv50->vtxelt_nr; i++) { +		struct pipe_vertex_element *ve = &nv50->vtxelt[i]; +		struct pipe_vertex_buffer *vb = +			&nv50->vtxbuf[ve->vertex_buffer_index]; + +		switch (ve->src_format) { +		case PIPE_FORMAT_R32G32B32A32_FLOAT: +			so_data(vtxfmt, 0x7e080000 | i); +			break; +		case PIPE_FORMAT_R32G32B32_FLOAT: +			so_data(vtxfmt, 0x7e100000 | i); +			break; +		case PIPE_FORMAT_R32G32_FLOAT: +			so_data(vtxfmt, 0x7e200000 | i); +			break; +		case PIPE_FORMAT_R32_FLOAT: +			so_data(vtxfmt, 0x7e900000 | i); +			break; +		case PIPE_FORMAT_R8G8B8A8_UNORM: +			so_data(vtxfmt, 0x24500000 | i); +			break; +		default: +		{ +			char fmt[128]; +			pf_sprint_name(fmt, ve->src_format); +			NOUVEAU_ERR("invalid vbo format %s\n", fmt); +			assert(0); +			return; +		} +		} + +		so_method(vtxbuf, tesla, 0x900 + (i * 16), 3); +		so_data  (vtxbuf, 0x20000000 | vb->pitch); +		so_reloc (vtxbuf, vb->buffer, vb->buffer_offset + +			  ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | +			  NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); +		so_reloc (vtxbuf, vb->buffer, vb->buffer_offset + +			  ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | +			  NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); +	} + +	so_ref (vtxfmt, &nv50->state.vtxfmt); +	so_ref (vtxbuf, &nv50->state.vtxbuf); +} + diff --git a/src/gallium/state_trackers/g3dvl/Makefile b/src/gallium/state_trackers/g3dvl/Makefile new file mode 100644 index 0000000000..c6a22cad4e --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/Makefile @@ -0,0 +1,18 @@ +TARGET		= libg3dvl.a +OBJECTS		= vl_context.o vl_data.o vl_surface.o vl_shader_build.o vl_util.o +GALLIUMDIR	= ../.. + +CFLAGS		+= -g -Wall -fPIC -Werror -I${GALLIUMDIR}/include -I${GALLIUMDIR}/auxiliary -I${GALLIUMDIR}/winsys/g3dvl + +############################################# + +.PHONY	= all clean + +all: ${TARGET} + +${TARGET}: ${OBJECTS} +	ar rcs $@ $^ + +clean: +	rm -rf ${OBJECTS} ${TARGET} + diff --git a/src/gallium/state_trackers/g3dvl/tests/.gitignore b/src/gallium/state_trackers/g3dvl/tests/.gitignore new file mode 100644 index 0000000000..9b1ec4e212 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/.gitignore @@ -0,0 +1,6 @@ +test_context +test_surface +test_i_rendering +test_p_rendering +test_pf_rendering +test_b_rendering diff --git a/src/gallium/state_trackers/g3dvl/tests/Makefile b/src/gallium/state_trackers/g3dvl/tests/Makefile new file mode 100644 index 0000000000..45cefa2e57 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/Makefile @@ -0,0 +1,45 @@ +GALLIUMDIR	= ../../.. + +CFLAGS	+= -g -Wall -Werror				\ +	   -I${GALLIUMDIR}/state_trackers/g3dvl		\ +	   -I${GALLIUMDIR}/winsys/g3dvl			\ +	   -I${GALLIUMDIR}/include			\ +	   -I${GALLIUMDIR}/auxiliary			\ +	   -I${GALLIUMDIR}/drivers +LDFLAGS	+= -L${GALLIUMDIR}/state_trackers/g3dvl		\ +	   -L${GALLIUMDIR}/drivers/softpipe		\ +	   -L${GALLIUMDIR}/auxiliary/tgsi		\ +	   -L${GALLIUMDIR}/auxiliary/draw		\ +	   -L${GALLIUMDIR}/auxiliary/util		\ +	   -L${GALLIUMDIR}/auxiliary/translate		\ +	   -L${GALLIUMDIR}/auxiliary/cso_cache		\ +	   -L${GALLIUMDIR}/auxiliary/rtasm +LIBS	+= -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lX11 -lm + +############################################# + +.PHONY	= all clean + +all: test_context test_surface test_i_rendering test_p_rendering test_pf_rendering test_b_rendering + +test_context: test_context.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_surface: test_surface.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_i_rendering: test_i_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_p_rendering: test_p_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_pf_rendering: test_pf_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_b_rendering: test_b_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +clean: +	rm -rf *.o test_context test_surface test_i_rendering test_p_rendering test_pf_rendering test_b_rendering + diff --git a/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c new file mode 100644 index 0000000000..b78cc851ae --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c @@ -0,0 +1,226 @@ +#include <stdio.h> +#include <X11/Xlib.h> +#include <vl_context.h> +#include <vl_surface.h> +#include <xsp_winsys.h> + +static const unsigned short ycbcr16x16_420[8*8*6] = +{ +	0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5, +	 +	0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F, +	 +	0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E +}; + +static const signed short ycbcr16x16_420_2[8*8*6] = +{ +	-0x00A5,-0x00A5,-0x00A5,-0x0072,-0x00A5,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x00A5,-0x0072,-0x0072,-0x00A5,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x00A5,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	 +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	 +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	 +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x00A5, +	-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x00A5,-0x00A5, +	 +	-0x004F,-0x004F,-0x004F,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2, +	-0x00B2,-0x00B2,-0x004F,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2, +	-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2, +	-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2, +	-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2, +	-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2, +	-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x004F, +	-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x004F,-0x004F, +	 +	-0x003E,-0x003E,-0x003E,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060, +	-0x0060,-0x0060,-0x003E,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060, +	-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060, +	-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060, +	-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060, +	-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060, +	-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x003E, +	-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x003E,-0x003E +}; + +int main(int argc, char **argv) +{ +	const unsigned int	video_width = 32, video_height = 32; +	const unsigned int	window_width = video_width * 2, window_height = video_height * 2; +	int			quit = 0; +	Display			*display; +	Window			root, window; +	Pixmap			framebuffer; +	XEvent			event; +	struct pipe_context	*pipe; +	struct VL_CONTEXT	*ctx; +	struct VL_SURFACE	*sfc, *past_sfc, *future_sfc; +	struct VL_MOTION_VECTOR	motion_vector[2] = +	{ +		{ +			{0, 0}, {0, 0} +		}, +		{ +			{0, 0}, {0, 0} +		} +	}; +	 +	display = XOpenDisplay(NULL); +	root = XDefaultRootWindow(display); +	window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0); +	framebuffer = XCreatePixmap(display, root, window_width, window_height, 24); +	 +	XSelectInput(display, window, ExposureMask | KeyPressMask); +	XMapWindow(display, window); +	XSync(display, 0); +	 +	pipe = create_pipe_context(display); +	vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx); +	vlCreateSurface(ctx, &sfc); +	vlCreateSurface(ctx, &past_sfc); +	vlCreateSurface(ctx, &future_sfc); +	 +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc); +	vlRenderBMacroBlock +	( +		VL_FRAME_PICTURE, +		VL_FIELD_FIRST, +		0, +		0, +		VL_FRAME_MC, +		motion_vector, +		0x3F, +		VL_DCT_FRAME_CODED, +		(short*)ycbcr16x16_420_2, +		past_sfc, +		future_sfc, +		sfc +	); +	vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE); +	 +	puts("Press any key to continue..."); +	 +	while (!quit) +	{ +		XNextEvent(display, &event); +		switch (event.type) +		{ +			case Expose: +			{ +				XCopyArea +				( +					display, +					framebuffer, +					window, +					XDefaultGC(display, XDefaultScreen(display)), +					0, +					0, +					window_width, +					window_height, +					0, +					0 +				); +				break; +			} +			case KeyPress: +			{ +				quit = 1; +				break; +			} +		} +	} +	 +	vlDestroySurface(sfc); +	vlDestroySurface(past_sfc); +	vlDestroySurface(future_sfc); +	vlDestroyContext(ctx); +	 +	XFreePixmap(display, framebuffer); +	XDestroyWindow(display, window); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/tests/test_context.c b/src/gallium/state_trackers/g3dvl/tests/test_context.c new file mode 100644 index 0000000000..2002977ee2 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_context.c @@ -0,0 +1,22 @@ +#include <vl_context.h> +#include <xsp_winsys.h> + +int main(int argc, char **argv) +{ +	const unsigned int	video_width = 32, video_height = 32; +	 +	Display			*display; +	struct pipe_context	*pipe; +	struct VL_CONTEXT	*ctx; +	 +	display = XOpenDisplay(NULL); +	pipe = create_pipe_context(display); +	 +	vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx); +	vlDestroyContext(ctx); +	 +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c new file mode 100644 index 0000000000..1f96471130 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c @@ -0,0 +1,137 @@ +#include <stdio.h> +#include <X11/Xlib.h> +#include <vl_context.h> +#include <vl_surface.h> +#include <xsp_winsys.h> + +static const unsigned short ycbcr16x16_420[8*8*6] = +{ +	0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5, +	 +	0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F, +	 +	0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E +}; + +int main(int argc, char **argv) +{ +	const unsigned int	video_width = 32, video_height = 32; +	const unsigned int	window_width = video_width * 2, window_height = video_height * 2; +	int			quit = 0; +	Display			*display; +	Window			root, window; +	Pixmap			framebuffer; +	XEvent			event; +	struct pipe_context	*pipe; +	struct VL_CONTEXT	*ctx; +	struct VL_SURFACE	*sfc; +	 +	display = XOpenDisplay(NULL); +	root = XDefaultRootWindow(display); +	window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0); +	framebuffer = XCreatePixmap(display, root, window_width, window_height, 24); +	 +	XSelectInput(display, window, ExposureMask | KeyPressMask); +	XMapWindow(display, window); +	XSync(display, 0); +	 +	pipe = create_pipe_context(display); +	vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx); +	vlCreateSurface(ctx, &sfc); +	 +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc); +	vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE); +	 +	puts("Press any key to continue..."); +	 +	while (!quit) +	{ +		XNextEvent(display, &event); +		switch (event.type) +		{ +			case Expose: +			{ +				XCopyArea +				( +					display, +					framebuffer, +					window, +					XDefaultGC(display, XDefaultScreen(display)), +					0, +					0, +					window_width, +					window_height, +					0, +					0 +				); +				break; +			} +			case KeyPress: +			{ +				quit = 1; +				break; +			} +		} +	} +	 +	vlDestroySurface(sfc); +	vlDestroyContext(ctx); +	 +	XFreePixmap(display, framebuffer); +	XDestroyWindow(display, window); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c new file mode 100644 index 0000000000..2203349784 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c @@ -0,0 +1,214 @@ +#include <stdio.h> +#include <X11/Xlib.h> +#include <vl_context.h> +#include <vl_surface.h> +#include <xsp_winsys.h> + +static const unsigned short ycbcr16x16_420[8*8*6] = +{ +	0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5, +	 +	0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F, +	 +	0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E +}; + +static const signed short ycbcr16x16_420_2[8*8*6] = +{ +	-51,-51,-51,  0,-51,  0,  0,  0, +	  0,-51,  0,  0,-51,  0,  0,  0, +	  0,-51,  0,  0,-51,-51,  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, +	  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, + +	 99, 99, 99,  0,  0,  0,  0,  0, +	  0,  0, 99,  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, + +	 33, 33, 33,  0,  0,  0,  0,  0, +	  0,  0, 33,  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 +}; + +int main(int argc, char **argv) +{ +	const unsigned int	video_width = 32, video_height = 32; +	const unsigned int	window_width = video_width * 2, window_height = video_height * 2; +	int			quit = 0; +	Display			*display; +	Window			root, window; +	Pixmap			framebuffer; +	XEvent			event; +	struct pipe_context	*pipe; +	struct VL_CONTEXT	*ctx; +	struct VL_SURFACE	*sfc, *ref_sfc; +	struct VL_MOTION_VECTOR	motion_vector = +	{ +		{0, 0}, {0, 0} +	}; +	 +	display = XOpenDisplay(NULL); +	root = XDefaultRootWindow(display); +	window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0); +	framebuffer = XCreatePixmap(display, root, window_width, window_height, 24); +	 +	XSelectInput(display, window, ExposureMask | KeyPressMask); +	XMapWindow(display, window); +	XSync(display, 0); +	 +	pipe = create_pipe_context(display); +	vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx); +	vlCreateSurface(ctx, &sfc); +	vlCreateSurface(ctx, &ref_sfc); +	 +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderPMacroBlock +	( +		VL_FRAME_PICTURE, +		VL_FIELD_FIRST, +		0, +		0, +		VL_FRAME_MC, +		&motion_vector, +		0x3F, +		VL_DCT_FRAME_CODED, +		(short*)ycbcr16x16_420_2, +		ref_sfc, +		sfc +	); +	vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE); +	 +	puts("Press any key to continue..."); +	 +	while (!quit) +	{ +		XNextEvent(display, &event); +		switch (event.type) +		{ +			case Expose: +			{ +				XCopyArea +				( +					display, +					framebuffer, +					window, +					XDefaultGC(display, XDefaultScreen(display)), +					0, +					0, +					window_width, +					window_height, +					0, +					0 +				); +				break; +			} +			case KeyPress: +			{ +				quit = 1; +				break; +			} +		} +	} +	 +	vlDestroySurface(sfc); +	vlDestroySurface(ref_sfc); +	vlDestroyContext(ctx); +	 +	XFreePixmap(display, framebuffer); +	XDestroyWindow(display, window); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/tests/test_pf_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_pf_rendering.c new file mode 100644 index 0000000000..43586fc553 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_pf_rendering.c @@ -0,0 +1,214 @@ +#include <stdio.h> +#include <X11/Xlib.h> +#include <vl_context.h> +#include <vl_surface.h> +#include <xsp_winsys.h> + +static const unsigned short ycbcr16x16_420[8*8*6] = +{ +	0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072, +	0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	 +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5, +	0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5, +	 +	0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F, +	0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F, +	 +	0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E, +	0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E +}; + +static const signed short ycbcr16x16_420_2[8*8*6] = +{ +	  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,  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,  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 +}; + +int main(int argc, char **argv) +{ +	const unsigned int	video_width = 32, video_height = 32; +	const unsigned int	window_width = video_width * 2, window_height = video_height * 2; +	int			quit = 0; +	Display			*display; +	Window			root, window; +	Pixmap			framebuffer; +	XEvent			event; +	struct pipe_context	*pipe; +	struct VL_CONTEXT	*ctx; +	struct VL_SURFACE	*sfc, *ref_sfc; +	struct VL_MOTION_VECTOR	motion_vector = +	{ +		{0, 0}, {32, 32} +	}; +	 +	display = XOpenDisplay(NULL); +	root = XDefaultRootWindow(display); +	window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0); +	framebuffer = XCreatePixmap(display, root, window_width, window_height, 24); +	 +	XSelectInput(display, window, ExposureMask | KeyPressMask); +	XMapWindow(display, window); +	XSync(display, 0); +	 +	pipe = create_pipe_context(display); +	vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx); +	vlCreateSurface(ctx, &sfc); +	vlCreateSurface(ctx, &ref_sfc); +	 +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc); +	vlRenderPMacroBlock +	( +		VL_FRAME_PICTURE, +		VL_FIELD_FIRST, +		0, +		0, +		VL_FIELD_MC, +		&motion_vector, +		0x3F, +		VL_DCT_FRAME_CODED, +		(short*)ycbcr16x16_420_2, +		ref_sfc, +		sfc +	); +	vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE); +	 +	puts("Press any key to continue..."); +	 +	while (!quit) +	{ +		XNextEvent(display, &event); +		switch (event.type) +		{ +			case Expose: +			{ +				XCopyArea +				( +					display, +					framebuffer, +					window, +					XDefaultGC(display, XDefaultScreen(display)), +					0, +					0, +					window_width, +					window_height, +					0, +					0 +				); +				break; +			} +			case KeyPress: +			{ +				quit = 1; +				break; +			} +		} +	} +	 +	vlDestroySurface(sfc); +	vlDestroySurface(ref_sfc); +	vlDestroyContext(ctx); +	 +	XFreePixmap(display, framebuffer); +	XDestroyWindow(display, window); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/tests/test_surface.c b/src/gallium/state_trackers/g3dvl/tests/test_surface.c new file mode 100644 index 0000000000..4d1946396a --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_surface.c @@ -0,0 +1,26 @@ +#include <vl_context.h> +#include <vl_surface.h> +#include <xsp_winsys.h> + +int main(int argc, char **argv) +{ +	const unsigned int	video_width = 32, video_height = 32; +	 +	Display			*display; +	struct pipe_context	*pipe; +	struct VL_CONTEXT	*ctx; +	struct VL_SURFACE	*sfc; +	 +	display = XOpenDisplay(NULL); +	pipe = create_pipe_context(display); +	 +	vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx); +	vlCreateSurface(ctx, &sfc); +	vlDestroySurface(sfc); +	vlDestroyContext(ctx); +	 +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/vl_context.c b/src/gallium/state_trackers/g3dvl/vl_context.c new file mode 100644 index 0000000000..d446d218a4 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_context.c @@ -0,0 +1,2282 @@ +#include "vl_context.h" +#include <assert.h> +#include <stdlib.h> +#include <pipe/p_context.h> +#include <pipe/p_winsys.h> +#include <pipe/p_screen.h> +#include <pipe/p_state.h> +#include <pipe/p_inlines.h> +#include <pipe/p_shader_tokens.h> +#include <tgsi/util/tgsi_parse.h> +#include <tgsi/util/tgsi_build.h> +#include "vl_shader_build.h" +#include "vl_data.h" +#include "vl_defs.h" +#include "vl_util.h" + +static int vlCreateVertexShaderFrameIDCT(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 50; + +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; +	 +	/* +	 * decl i0		; Vertex pos +	 * decl i1		; Vertex texcoords +	 */ +	for (i = 0; i < 2; i++) +	{ +		decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl o0		; Vertex pos +	 * decl o1		; Vertex texcoords +	 */ +	for (i = 0; i < 2; i++) +	{ +		decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * mov o0, i0		; Move pos in to pos out +	 * mov o1, i1		; Move texcoord in to texcoord out */ +	for (i = 0; i < 2; ++i) +	{ +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	//context->states.idct.frame_vs = pipe->create_fs_state(pipe, &fs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateFragmentShaderFrameIDCT(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 50; + +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; + +	/* decl i0		; Texcoords for s0 */ +	decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* decl o0		; Fragment color */ +	decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl s0		; Sampler for tex containing picture to display */ +	decl = vl_decl_samplers(0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* tex2d t0, i0, s0	; Read src pixel */ +	inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* sub t0, t0, c0	; Subtract bias vector from pixel */ +	inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * dp4 o0.x, t0, c1	; Multiply pixel by the color conversion matrix +	 * dp4 o0.y, t0, c2 +	 * dp4 o0.z, t0, c3 +	 * dp4 o0.w, t0, c4	; XXX: Don't need 4th coefficient +	 */ +	for (i = 0; i < 4; ++i) +	{ +		inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 1); +		inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	//context->states.idct.frame_fs = pipe->create_fs_state(pipe, &fs); +	free(tokens); +	 +	return 0; +} + +static int vlInitIDCT(struct VL_CONTEXT *context) +{ +	struct pipe_context		*pipe; +	struct pipe_sampler_state	sampler; +	struct pipe_texture		template; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	context->states.idct.viewport.scale[0] = VL_BLOCK_WIDTH; +	context->states.idct.viewport.scale[1] = VL_BLOCK_HEIGHT; +	context->states.idct.viewport.scale[2] = 1; +	context->states.idct.viewport.scale[3] = 1; +	context->states.idct.viewport.translate[0] = 0; +	context->states.idct.viewport.translate[1] = 0; +	context->states.idct.viewport.translate[2] = 0; +	context->states.idct.viewport.translate[3] = 0; +	 +	context->states.idct.render_target.width = VL_BLOCK_WIDTH; +	context->states.idct.render_target.height = VL_BLOCK_HEIGHT; +	context->states.idct.render_target.num_cbufs = 1; +	context->states.idct.render_target.zsbuf = NULL; +	 +	sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +	sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +	sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +	sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; +	sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; +	sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; +	sampler.compare_mode = PIPE_TEX_COMPARE_NONE; +	sampler.compare_func = PIPE_FUNC_ALWAYS; +	sampler.normalized_coords = 1; +	/*sampler.prefilter = ;*/ +	/*sampler.shadow_ambient = ;*/ +	/*sampler.lod_bias = ;*/ +	sampler.min_lod = 0; +	/*sampler.max_lod = ;*/ +	/*sampler.border_color[i] = ;*/ +	/*sampler.max_anisotropy = ;*/ +	context->states.idct.sampler = pipe->create_sampler_state(pipe, &sampler); +	 +	memset(&template, 0, sizeof(struct pipe_texture)); +	template.target = PIPE_TEXTURE_2D; +	template.format = PIPE_FORMAT_A8L8_UNORM; +	template.last_level = 0; +	template.width[0] = 8; +	template.height[0] = 8; +	template.depth[0] = 1; +	template.compressed = 0; +	pf_get_block(template.format, &template.block); +	 +	context->states.idct.texture = pipe->screen->texture_create(pipe->screen, &template); +	 +	template.format = PIPE_FORMAT_A8R8G8B8_UNORM; +	template.width[0] = 16; +	template.height[0] = 1; +	 +	context->states.idct.basis = pipe->screen->texture_create(pipe->screen, &template); +	 +	for (i = 0; i < 2; ++i) +	{ +		context->states.idct.vertex_bufs[i] = &context->states.csc.vertex_bufs[i]; +		context->states.idct.vertex_buf_elems[i] = &context->states.csc.vertex_buf_elems[i]; +		/* +		context->states.idct.vertex_bufs[i].pitch = sizeof(struct VL_VERTEX2F); +		context->states.idct.vertex_bufs[i].max_index = 3; +		context->states.idct.vertex_bufs[i].buffer_offset = 0; +		context->states.idct.vertex_bufs[i].buffer = pipe->winsys->buffer_create +		( +			pipe->winsys, +			1, +			PIPE_BUFFER_USAGE_VERTEX, +			sizeof(struct VL_VERTEX2F) * 4 +		); +	 +		context->states.idct.vertex_buf_elems[i].src_offset = 0; +		context->states.idct.vertex_buf_elems[i].vertex_buffer_index = i; +		context->states.idct.vertex_buf_elems[i].nr_components = 2; +		context->states.idct.vertex_buf_elems[i].src_format = PIPE_FORMAT_R32G32_FLOAT; +		*/ +	} +	 +	vlCreateVertexShaderFrameIDCT(context); +	vlCreateFragmentShaderFrameIDCT(context); +	 +	return 0; +} + +static int vlDestroyIDCT(struct VL_CONTEXT *context) +{ +	//unsigned int i; +	 +	assert(context); +	 +	context->pipe->delete_sampler_state(context->pipe, context->states.idct.sampler); +	 +	//for (i = 0; i < 2; ++i) +		//context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.idct.vertex_bufs[i].buffer); +	 +	pipe_texture_release(&context->states.idct.texture); +	pipe_texture_release(&context->states.idct.basis); +	 +	//context->pipe->delete_vs_state(context->pipe, context->states.idct.frame_vs); +	//context->pipe->delete_fs_state(context->pipe, context->states.idct.frame_fs); +	 +	//context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.idct.vs_const_buf.buffer); +	//context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.idct.fs_const_buf.buffer); +	 +	return 0; +} + +static int vlCreateVertexShaderIMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 50; +	 +	struct pipe_context		*pipe; +	struct pipe_shader_state	vs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; +	 +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + +	ti = 3; + +	/* +	 * decl i0		; Vertex pos +	 * decl i1		; Luma texcoords +	 * decl i2		; Chroma texcoords +	 */ +	for (i = 0; i < 3; i++) +	{ +		decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0		; Scaling vector to scale unit rect to macroblock size +	 * decl c1		; Translation vector to move macroblock into position +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* +	 * decl o0		; Vertex pos +	 * decl o1		; Luma texcoords +	 * decl o2		; Chroma texcoords +	 */ +	for (i = 0; i < 3; i++) +	{ +		decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl t0 */ +	decl = vl_decl_temps(0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t0, i0, c0	; Scale unit rect to normalized MB size */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* add o0, t0, c1	; Translate rect into position */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * mov o1, i1		; Move input luma texcoords to output +	 * mov o2, i2		; Move input chroma texcoords to output +	 */ +	for (i = 1; i < 3; ++i) +	{ +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	vs.tokens = tokens; +	context->states.mc.i_vs = pipe->create_vs_state(pipe, &vs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateFragmentShaderIMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 100; +	 +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; + +	/* +	 * decl i0			; Texcoords for s0 +	 * decl i1			; Texcoords for s1, s2 +	 */ +	for (i = 0; i < 2; ++i) +	{ +		decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl c0			; Scaling factor, rescales 16-bit snorm to 9-bit snorm */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* decl o0			; Fragment color */ +	decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl t0, t1 */ +	decl = vl_decl_temps(0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * decl s0			; Sampler for luma texture +	 * decl s1			; Sampler for chroma Cb texture +	 * decl s2			; Sampler for chroma Cr texture +	 */ +	for (i = 0; i < 3; ++i) +	{ +		decl = vl_decl_samplers(i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header,max_tokens - ti); +	} +	 +	/* +	 * tex2d t1, i0, s0		; Read texel from luma texture +	 * mov t0.x, t1.x		; Move luma sample into .x component +	 * tex2d t1, i1, s1		; Read texel from chroma Cb texture +	 * mov t0.y, t1.x		; Move Cb sample into .y component +	 * tex2d t1, i1, s2		; Read texel from chroma Cr texture +	 * mov t0.z, t1.x		; Move Cr sample into .z component +	 */ +	for (i = 0; i < 3; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +		inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +		inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +	} +	 +	/* mul o0, t0, c0		; Rescale texel to correct range */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	context->states.mc.i_fs = pipe->create_fs_state(pipe, &fs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateVertexShaderFramePMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 100; +	 +	struct pipe_context		*pipe; +	struct pipe_shader_state	vs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; +	 +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + +	ti = 3; + +	/* +	 * decl i0		; Vertex pos +	 * decl i1		; Luma texcoords +	 * decl i2		; Chroma texcoords +	 */ +	for (i = 0; i < 3; i++) +	{ +		decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0		; Scaling vector to scale unit rect to macroblock size +	 * decl c1		; Translation vector to move macroblock into position +	 * decl c2		; Unused +	 * decl c3		; Translation vector to move ref macroblock texcoords into position +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* +	 * decl o0		; Vertex pos +	 * decl o1		; Luma texcoords +	 * decl o2		; Chroma texcoords +	 * decl o3		; Ref macroblock texcoords +	 */ +	for (i = 0; i < 4; i++) +	{ +		decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl t0 */ +	decl = vl_decl_temps(0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t0, i0, c0	; Scale unit rect to normalized MB size */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* add o0, t0, c1	; Translate rect into position */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * mov o1, i1		; Move input luma texcoords to output +	 * mov o2, i2		; Move input chroma texcoords to output +	 */ +	for (i = 1; i < 3; ++i) +	{ +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} + +	/* add o3, t0, c3	; Translate rect into position on ref macroblock */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 3); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	vs.tokens = tokens; +	context->states.mc.p_vs[0] = pipe->create_vs_state(pipe, &vs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateVertexShaderFieldPMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 100; +	 +	struct pipe_context		*pipe; +	struct pipe_shader_state	vs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; +	 +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + +	ti = 3; + +	/* +	 * decl i0		; Vertex pos +	 * decl i1		; Luma texcoords +	 * decl i2		; Chroma texcoords +	 */ +	for (i = 0; i < 3; i++) +	{ +		decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration +		( +			&decl, +			&tokens[ti], +			header, +			max_tokens - ti +		); +	} +	 +	/* +	 * decl c0		; Scaling vector to scale unit rect to macroblock size +	 * decl c1		; Translation vector to move macroblock into position +	 * decl c2		; Denorm coefficients +	 * decl c3		; Translation vector to move top field ref macroblock texcoords into position +	 * decl c4		; Translation vector to move bottom field ref macroblock texcoords into position +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 4); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* +	 * decl o0		; Vertex pos +	 * decl o1		; Luma texcoords +	 * decl o2		; Chroma texcoords +	 * decl o3		; Top field ref macroblock texcoords +	 * decl o4		; Bottom field ref macroblock texcoords +	 * decl o5		; Denormalized vertex pos +	 */ +	for (i = 0; i < 6; i++) +	{ +		decl = vl_decl_output((i == 0 || i == 5) ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl t0, t1 */ +	decl = vl_decl_temps(0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t0, i0, c0	; Scale unit rect to normalized MB size */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* add t1, t0, c1	; Translate rect into position */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* mov o0, t1		; Move vertex pos to output */ +	inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	mov o1, i1		; Move input luma texcoords to output +	mov o2, i2		; Move input chroma texcoords to output +	*/ +	for (i = 1; i < 3; ++i) +	{ +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} + +	/* add o3, t0, c3	; Translate top field rect into position on ref macroblock +	   add o4, t0, c4	; Translate bottom field rect into position on ref macroblock */ +	for (i = 0; i < 2; ++i) +	{ +		inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 3); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* mul o5, t1, c2	; Denorm vertex pos */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 5, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 2); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	vs.tokens = tokens; +	context->states.mc.p_vs[1] = pipe->create_vs_state(pipe, &vs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateFragmentShaderFramePMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 100; + +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; + +	/* +	 * decl i0			; Texcoords for s0 +	 * decl i1			; Texcoords for s1, s2 +	 * decl i2			; Texcoords for s3 +	 */ +	for (i = 0; i < 3; ++i) +	{ +		decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl c0			; Scaling factor, rescales 16-bit snorm to 9-bit snorm */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* decl o0			; Fragment color */ +	decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl t0, t1 */ +	decl = vl_decl_temps(0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * decl s0			; Sampler for luma texture +	 * decl s1			; Sampler for chroma Cb texture +	 * decl s2			; Sampler for chroma Cr texture +	 * decl s3			; Sampler for ref surface texture +	 */ +	for (i = 0; i < 4; ++i) +	{ +		decl = vl_decl_samplers(i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * tex2d t1, i0, s0		; Read texel from luma texture +	 * mov t0.x, t1.x		; Move luma sample into .x component +	 * tex2d t1, i1, s1		; Read texel from chroma Cb texture +	 * mov t0.y, t1.x		; Move Cb sample into .y component +	 * tex2d t1, i1, s2		; Read texel from chroma Cr texture +	 * mov t0.z, t1.x		; Move Cr sample into .z component +	 */ +	for (i = 0; i < 3; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +		inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +		inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +	} +	 +	/* mul t0, t0, c0		; Rescale texel to correct range */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* tex2d t1, i2, s3		; Read texel from ref macroblock */ +	inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, 2, TGSI_FILE_SAMPLER, 3); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* add o0, t0, t1		; Add ref and differential to form final output */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	context->states.mc.p_fs[0] = pipe->create_fs_state(pipe, &fs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateFragmentShaderFieldPMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 200; + +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; + +	/* +	 * decl i0			; Texcoords for s0 +	 * decl i1			; Texcoords for s1, s2 +	 * decl i2			; Texcoords for s3 +	 * decl i3			; Texcoords for s3 +	 * decl i4			; Denormalized vertex pos +	 */ +	for (i = 0; i < 5; ++i) +	{ +		decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0			; Scaling factor, rescales 16-bit snorm to 9-bit snorm +	 * decl c1			; Constants 1/2 & 2 in .x, .y channels for Y-mod-2 top/bottom field selection +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* decl o0			; Fragment color */ +	decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl t0-t4 */ +	decl = vl_decl_temps(0, 4); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * decl s0			; Sampler for luma texture +	 * decl s1			; Sampler for chroma Cb texture +	 * decl s2			; Sampler for chroma Cr texture +	 * decl s3			; Sampler for ref surface texture +	 */ +	for (i = 0; i < 4; ++i) +	{ +		decl = vl_decl_samplers(i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * tex2d t1, i0, s0		; Read texel from luma texture +	 * mov t0.x, t1.x		; Move luma sample into .x component +	 * tex2d t1, i1, s1		; Read texel from chroma Cb texture +	 * mov t0.y, t1.x		; Move Cb sample into .y component +	 * tex2d t1, i1, s2		; Read texel from chroma Cr texture +	 * mov t0.z, t1.x		; Move Cr sample into .z component +	 */ +	for (i = 0; i < 3; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +		inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +		inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +	} +	 +	/* mul t0, t0, c0		; Rescale texel to correct range */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * tex2d t1, i2, s3		; Read texel from ref macroblock top field +	 * tex2d t2, i3, s3		; Read texel from ref macroblock bottom field +	 */ +	for (i = 0; i < 2; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 2, TGSI_FILE_SAMPLER, 3); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* XXX: Pos values off by 0.5? */ +	/* sub t4, i4.y, c1.x		; Sub 0.5 from denormalized pos */ +	inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 4, TGSI_FILE_CONSTANT, 1); +	inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t3, t4, c1.x		; Multiply pos Y-coord by 1/2 */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 1); +	inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* floor t3, t3			; Get rid of fractional part */ +	inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t3, t3, c1.y		; Multiply by 2 */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1); +	inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* sub t3, t4, t3		; Subtract from original Y to get Y % 2 */ +	inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* TODO: Move to conditional tex fetch on t3 instead of lerp */ +	/* lerp t1, t3, t1, t2		; Choose between top and bottom fields based on Y % 2 */ +	inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* add o0, t0, t1		; Add ref and differential to form final output */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	context->states.mc.p_fs[1] = pipe->create_fs_state(pipe, &fs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateVertexShaderFrameBMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 100; +	 +	struct pipe_context		*pipe; +	struct pipe_shader_state	vs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; +	 +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + +	ti = 3; + +	/* +	 * decl i0		; Vertex pos +	 * decl i1		; Luma texcoords +	 * decl i2		; Chroma texcoords +	 */ +	for (i = 0; i < 3; i++) +	{ +		decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0		; Scaling vector to scale unit rect to macroblock size +	 * decl c1		; Translation vector to move macroblock into position +	 * decl c2		; Unused +	 * decl c3		; Translation vector to move past ref macroblock texcoords into position +	 * decl c4		; Unused +	 * decl c5		; Translation vector to move future ref macroblock texcoords into position +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 5); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* +	 * decl o0		; Vertex pos +	 * decl o1		; Luma texcoords +	 * decl o2		; Chroma texcoords +	 * decl o3		; Past ref macroblock texcoords +	 * decl o4		; Future ref macroblock texcoords +	 */ +	for (i = 0; i < 5; i++) +	{ +		decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl t0 */ +	decl = vl_decl_temps(0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t0, i0, c0	; Scale unit rect to normalized MB size */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* add o0, t0, c1	; Translate rect into position */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * mov o1, i1		; Move input luma texcoords to output +	 * mov o2, i2		; Move input chroma texcoords to output +	 */ +	for (i = 1; i < 3; ++i) +	{ +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* add o3, t0, c3	; Translate rect into position on past ref macroblock +	   add o4, t0, c5	; Translate rect into position on future ref macroblock */ +	for (i = 0; i < 2; ++i) +	{ +		inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i * 2 + 3); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	vs.tokens = tokens; +	context->states.mc.b_vs[0] = pipe->create_vs_state(pipe, &vs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateVertexShaderFieldBMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 100; +	 +	struct pipe_context		*pipe; +	struct pipe_shader_state	vs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; +	 +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe;	 +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + +	ti = 3; + +	/* +	 * decl i0		; Vertex pos +	 * decl i1		; Luma texcoords +	 * decl i2		; Chroma texcoords +	 */ +	for (i = 0; i < 3; i++) +	{ +		decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0		; Scaling vector to scale unit rect to macroblock size +	 * decl c1		; Translation vector to move macroblock into position +	 * decl c2		; Denorm coefficients +	 * decl c3		; Translation vector to move top field past ref macroblock texcoords into position +	 * decl c4		; Translation vector to move bottom field past ref macroblock texcoords into position +	 * decl c5		; Translation vector to move top field future ref macroblock texcoords into position +	 * decl c6		; Translation vector to move bottom field future ref macroblock texcoords into position +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 6); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* +	 * decl o0		; Vertex pos +	 * decl o1		; Luma texcoords +	 * decl o2		; Chroma texcoords +	 * decl o3		; Top field past ref macroblock texcoords +	 * decl o4		; Bottom field past ref macroblock texcoords +	 * decl o5		; Top field future ref macroblock texcoords +	 * decl o6		; Bottom field future ref macroblock texcoords +	 * decl o7		; Denormalized vertex pos +	 */ +	for (i = 0; i < 8; i++) +	{ +		decl = vl_decl_output((i == 0 || i == 7) ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl t0, t1 */ +	decl = vl_decl_temps(0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t0, i0, c0	; Scale unit rect to normalized MB size */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* add t1, t0, c1	; Translate rect into position */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* mov o0, t1		; Move vertex pos to output */ +	inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * mov o1, i1		; Move input luma texcoords to output +	 * mov o2, i2		; Move input chroma texcoords to output +	 */ +	for (i = 1; i < 3; ++i) +	{ +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} + +	/* +	 * add o3, t0, c3	; Translate top field rect into position on past ref macroblock +	 * add o4, t0, c4	; Translate bottom field rect into position on past ref macroblock +	 * add o5, t0, c5	; Translate top field rect into position on future ref macroblock +	 * add o6, t0, c6	; Translate bottom field rect into position on future ref macroblock +	 */ +	for (i = 0; i < 4; ++i) +	{ +		inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 3); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* mul o7, t1, c2	; Denorm vertex pos */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 7, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 2); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	vs.tokens = tokens; +	context->states.mc.b_vs[1] = pipe->create_vs_state(pipe, &vs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateFragmentShaderFrameBMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 100; + +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; + +	/* +	 * decl i0			; Texcoords for s0 +	 * decl i1			; Texcoords for s1, s2 +	 * decl i2			; Texcoords for s3 +	 * decl i3			; Texcoords for s4 +	 */ +	for (i = 0; i < 4; ++i) +	{ +		decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0			; Scaling factor, rescales 16-bit snorm to 9-bit snorm +	 * decl c1			; Constant 1/2 in .x channel to use as weight to blend past and future texels +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* decl o0			; Fragment color */ +	decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl t0-t2 */ +	decl = vl_decl_temps(0, 2); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * decl s0			; Sampler for luma texture +	 * decl s1			; Sampler for chroma Cb texture +	 * decl s2			; Sampler for chroma Cr texture +	 * decl s3			; Sampler for past ref surface texture +	 * decl s4			; Sampler for future ref surface texture +	 */ +	for (i = 0; i < 5; ++i) +	{ +		decl = vl_decl_samplers(i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * tex2d t1, i0, s0		; Read texel from luma texture +	 * mov t0.x, t1.x		; Move luma sample into .x component +	 * tex2d t1, i1, s1		; Read texel from chroma Cb texture +	 * mov t0.y, t1.x		; Move Cb sample into .y component +	 * tex2d t1, i1, s2		; Read texel from chroma Cr texture +	 * mov t0.z, t1.x		; Move Cr sample into .z component +	 */ +	for (i = 0; i < 3; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +		inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +		inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +	} +	 +	/* mul t0, t0, c0		; Rescale texel to correct range */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * tex2d t1, i2, s3		; Read texel from past ref macroblock +	 * tex2d t2, i3, s4		; Read texel from future ref macroblock +	 */ +	for (i = 0; i < 2; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 2, TGSI_FILE_SAMPLER, i + 3); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* lerp t1, c1.x, t1, t2	; Blend past and future texels */ +	inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); +	inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* add o0, t0, t1		; Add past/future ref and differential to form final output */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	context->states.mc.b_fs[0] = pipe->create_fs_state(pipe, &fs); +	free(tokens); +	 +	return 0; +} + +static int vlCreateFragmentShaderFieldBMC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 200; + +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; + +	/* +	 * decl i0			; Texcoords for s0 +	 * decl i1			; Texcoords for s1, s2 +	 * decl i2			; Texcoords for s3 +	 * decl i3			; Texcoords for s3 +	 * decl i4			; Texcoords for s4 +	 * decl i5			; Texcoords for s4 +	 * decl i6			; Denormalized vertex pos +	 */ +	for (i = 0; i < 7; ++i) +	{ +		decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0			; Scaling factor, rescales 16-bit snorm to 9-bit snorm +	 * decl c1			; Constants 1/2 & 2 in .x, .y channels to use as weight to blend past and future texels +	 *				; and for Y-mod-2 top/bottom field selection +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* decl o0			; Fragment color */ +	decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl t0-t5 */ +	decl = vl_decl_temps(0, 5); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * decl s0			; Sampler for luma texture +	 * decl s1			; Sampler for chroma Cb texture +	 * decl s2			; Sampler for chroma Cr texture +	 * decl s3			; Sampler for past ref surface texture +	 * decl s4			; Sampler for future ref surface texture +	 */ +	for (i = 0; i < 5; ++i) +	{ +		decl = vl_decl_samplers(i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * tex2d t1, i0, s0		; Read texel from luma texture +	 * mov t0.x, t1.x		; Move luma sample into .x component +	 * tex2d t1, i1, s1		; Read texel from chroma Cb texture +	 * mov t0.y, t1.x		; Move Cb sample into .y component +	 * tex2d t1, i1, s2		; Read texel from chroma Cr texture +	 * mov t0.z, t1.x		; Move Cr sample into .z component +	 */ +	for (i = 0; i < 3; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +		inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +		inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +		inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +		inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +		 +	} +	 +	/* mul t0, t0, c0		; Rescale texel to correct range */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* XXX: Pos values off by 0.5? */ +	/* sub t4, i6.y, c1.x		; Sub 0.5 from denormalized pos */ +	inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 6, TGSI_FILE_CONSTANT, 1); +	inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t3, t4, c1.x		; Multiply pos Y-coord by 1/2 */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 1); +	inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* floor t3, t3			; Get rid of fractional part */ +	inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t3, t3, c1.y		; Multiply by 2 */ +	inst = vl_inst3( TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1); +	inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; +	inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* sub t3, t4, t3		; Subtract from original Y to get Y % 2 */ +	inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * tex2d t1, i2, s3		; Read texel from past ref macroblock top field +	 * tex2d t2, i3, s3		; Read texel from past ref macroblock bottom field +	 */ +	for (i = 0; i < 2; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 2, TGSI_FILE_SAMPLER, 3); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* TODO: Move to conditional tex fetch on t3 instead of lerp */ +	/* lerp t1, t3, t1, t2		; Choose between top and bottom fields based on Y % 2 */ +	inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * tex2d t4, i4, s4		; Read texel from future ref macroblock top field +	 * tex2d t5, i5, s4		; Read texel from future ref macroblock bottom field +	 */ +	for (i = 0; i < 2; ++i) +	{ +		inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 4, TGSI_FILE_INPUT, i + 4, TGSI_FILE_SAMPLER, 4); +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* TODO: Move to conditional tex fetch on t3 instead of lerp */ +	/* lerp t2, t3, t4, t5		; Choose between top and bottom fields based on Y % 2 */ +	inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 2, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 5); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* lerp t1, c1.x, t1, t2	; Blend past and future texels */ +	inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); +	inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; +	inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* add o0, t0, t1		; Add past/future ref and differential to form final output */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	context->states.mc.b_fs[1] = pipe->create_fs_state(pipe, &fs); +	free(tokens); +	 +	return 0; +} + +int vlCreateDataBufsMC(struct VL_CONTEXT *context) +{ +	struct pipe_context	*pipe; +	unsigned int		i; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	/* Create our vertex buffer and vertex buffer element */ +	context->states.mc.vertex_bufs[0].pitch = sizeof(struct VL_VERTEX2F); +	context->states.mc.vertex_bufs[0].max_index = 23; +	context->states.mc.vertex_bufs[0].buffer_offset = 0; +	context->states.mc.vertex_bufs[0].buffer = pipe->winsys->buffer_create +	( +		pipe->winsys, +		1, +		PIPE_BUFFER_USAGE_VERTEX, +		sizeof(struct VL_VERTEX2F) * 24 +	); +	 +	context->states.mc.vertex_buf_elems[0].src_offset = 0; +	context->states.mc.vertex_buf_elems[0].vertex_buffer_index = 0; +	context->states.mc.vertex_buf_elems[0].nr_components = 2; +	context->states.mc.vertex_buf_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; +	 +	/* Create our texcoord buffers and texcoord buffer elements */ +	for (i = 1; i < 3; ++i) +	{ +		context->states.mc.vertex_bufs[i].pitch = sizeof(struct VL_TEXCOORD2F); +		context->states.mc.vertex_bufs[i].max_index = 23; +		context->states.mc.vertex_bufs[i].buffer_offset = 0; +		context->states.mc.vertex_bufs[i].buffer = pipe->winsys->buffer_create +		( +			pipe->winsys, +			1, +			PIPE_BUFFER_USAGE_VERTEX, +			sizeof(struct VL_TEXCOORD2F) * 24 +		); +	 +		context->states.mc.vertex_buf_elems[i].src_offset = 0; +		context->states.mc.vertex_buf_elems[i].vertex_buffer_index = i; +		context->states.mc.vertex_buf_elems[i].nr_components = 2; +		context->states.mc.vertex_buf_elems[i].src_format = PIPE_FORMAT_R32G32_FLOAT; +	} +	 +	/* Fill buffers */ +	memcpy +	( +		pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +		vl_chroma_420_texcoords, +		sizeof(struct VL_VERTEX2F) * 24 +	); +	memcpy +	( +		pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +		vl_luma_texcoords, +		sizeof(struct VL_TEXCOORD2F) * 24 +	); +	/* TODO: Accomodate 422, 444 */ +	memcpy +	( +		pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[2].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +		vl_chroma_420_texcoords, +		sizeof(struct VL_TEXCOORD2F) * 24 +	); +	 +	for (i = 0; i < 3; ++i) +		pipe->winsys->buffer_unmap(pipe->winsys, context->states.mc.vertex_bufs[i].buffer); +	 +	/* Create our constant buffer */ +	context->states.mc.vs_const_buf.size = sizeof(struct VL_MC_VS_CONSTS); +	context->states.mc.vs_const_buf.buffer = pipe->winsys->buffer_create +	( +		pipe->winsys, +		1, +		PIPE_BUFFER_USAGE_CONSTANT, +		context->states.mc.vs_const_buf.size +	); +	 +	context->states.mc.fs_const_buf.size = sizeof(struct VL_MC_FS_CONSTS); +	context->states.mc.fs_const_buf.buffer = pipe->winsys->buffer_create +	( +		pipe->winsys, +		1, +		PIPE_BUFFER_USAGE_CONSTANT, +		context->states.mc.fs_const_buf.size +	); +	 +	memcpy +	( +		pipe->winsys->buffer_map(pipe->winsys, context->states.mc.fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +		&vl_mc_fs_consts, +		sizeof(struct VL_MC_FS_CONSTS) +	); +	 +	pipe->winsys->buffer_unmap(pipe->winsys, context->states.mc.fs_const_buf.buffer); +	 +	return 0; +} + +static int vlInitMC(struct VL_CONTEXT *context) +{	 +	struct pipe_context		*pipe; +	struct pipe_sampler_state	sampler; +	struct pipe_texture		template; +	unsigned int			filters[5]; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	/* For MC we render to textures, which are rounded up to nearest POT */ +	context->states.mc.viewport.scale[0] = vlRoundUpPOT(context->video_width); +	context->states.mc.viewport.scale[1] = vlRoundUpPOT(context->video_height); +	context->states.mc.viewport.scale[2] = 1; +	context->states.mc.viewport.scale[3] = 1; +	context->states.mc.viewport.translate[0] = 0; +	context->states.mc.viewport.translate[1] = 0; +	context->states.mc.viewport.translate[2] = 0; +	context->states.mc.viewport.translate[3] = 0; +	 +	context->states.mc.render_target.width = vlRoundUpPOT(context->video_width); +	context->states.mc.render_target.height = vlRoundUpPOT(context->video_height); +	context->states.mc.render_target.num_cbufs = 1; +	/* FB for MC stage is a VL_SURFACE, set in vlSetRenderSurface() */ +	context->states.mc.render_target.zsbuf = NULL; +	 +	filters[0] = PIPE_TEX_FILTER_NEAREST; +	filters[1] = context->video_format == VL_FORMAT_YCBCR_444 ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; +	filters[2] = context->video_format == VL_FORMAT_YCBCR_444 ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; +	filters[3] = PIPE_TEX_FILTER_LINEAR; +	filters[4] = PIPE_TEX_FILTER_LINEAR; +	 +	for (i = 0; i < 5; ++i) +	{ +		sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +		sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +		sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +		sampler.min_img_filter = filters[i]; +		sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; +		sampler.mag_img_filter = filters[i]; +		sampler.compare_mode = PIPE_TEX_COMPARE_NONE; +		sampler.compare_func = PIPE_FUNC_ALWAYS; +		sampler.normalized_coords = 1; +		/*sampler.prefilter = ;*/ +		/*sampler.shadow_ambient = ;*/ +		/*sampler.lod_bias = ;*/ +		sampler.min_lod = 0; +		/*sampler.max_lod = ;*/ +		/*sampler.border_color[i] = ;*/ +		/*sampler.max_anisotropy = ;*/ +		context->states.mc.samplers[i] = pipe->create_sampler_state(pipe, &sampler); +	} +	 +	memset(&template, 0, sizeof(struct pipe_texture)); +	template.target = PIPE_TEXTURE_2D; +	template.format = PIPE_FORMAT_R16_SNORM; +	template.last_level = 0; +	template.width[0] = 8; +	template.height[0] = 8 * 4; +	template.depth[0] = 1; +	template.compressed = 0; +	pf_get_block(template.format, &template.block); +	 +	context->states.mc.textures[0] = pipe->screen->texture_create(pipe->screen, &template); +	 +	if (context->video_format == VL_FORMAT_YCBCR_420) +		template.height[0] = 8; +	else if (context->video_format == VL_FORMAT_YCBCR_422) +		template.height[0] = 8 * 2; +	else if (context->video_format == VL_FORMAT_YCBCR_444) +		template.height[0] = 8 * 4; +	else +		assert(0); +		 +	context->states.mc.textures[1] = pipe->screen->texture_create(pipe->screen, &template); +	context->states.mc.textures[2] = pipe->screen->texture_create(pipe->screen, &template); +	 +	/* textures[3] & textures[4] are assigned from VL_SURFACEs for P and B macroblocks at render time */ +	 +	vlCreateVertexShaderIMC(context); +	vlCreateFragmentShaderIMC(context); +	vlCreateVertexShaderFramePMC(context); +	vlCreateVertexShaderFieldPMC(context); +	vlCreateFragmentShaderFramePMC(context); +	vlCreateFragmentShaderFieldPMC(context); +	vlCreateVertexShaderFrameBMC(context); +	vlCreateVertexShaderFieldBMC(context); +	vlCreateFragmentShaderFrameBMC(context); +	vlCreateFragmentShaderFieldBMC(context); +	vlCreateDataBufsMC(context); +	 +	return 0; +} + +static int vlDestroyMC(struct VL_CONTEXT *context) +{ +	unsigned int i; +	 +	assert(context); +	 +	for (i = 0; i < 5; ++i) +		context->pipe->delete_sampler_state(context->pipe, context->states.mc.samplers[i]); +	 +	for (i = 0; i < 3; ++i) +		context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.vertex_bufs[i].buffer); +	 +	/* Textures 3 & 4 are not created directly, no need to release them here */ +	for (i = 0; i < 3; ++i) +		pipe_texture_release(&context->states.mc.textures[i]); +	 +	context->pipe->delete_vs_state(context->pipe, context->states.mc.i_vs); +	context->pipe->delete_fs_state(context->pipe, context->states.mc.i_fs); +	 +	for (i = 0; i < 2; ++i) +	{ +		context->pipe->delete_vs_state(context->pipe, context->states.mc.p_vs[i]); +		context->pipe->delete_fs_state(context->pipe, context->states.mc.p_fs[i]); +		context->pipe->delete_vs_state(context->pipe, context->states.mc.b_vs[i]); +		context->pipe->delete_fs_state(context->pipe, context->states.mc.b_fs[i]); +	} +	 +	context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.vs_const_buf.buffer); +	context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.fs_const_buf.buffer); +	 +	return 0; +} + +static int vlCreateVertexShaderCSC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 50; +	 +	struct pipe_context		*pipe; +	struct pipe_shader_state	vs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; +	 +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + +	ti = 3; + +	/* +	 * decl i0		; Vertex pos +	 * decl i1		; Vertex texcoords +	 */ +	for (i = 0; i < 2; i++) +	{ +		decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* +	 * decl c0		; Scaling vector to scale texcoord rect to source size +	 * decl c1		; Translation vector to move texcoord rect into position +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* +	 * decl o0		; Vertex pos +	 * decl o1		; Vertex texcoords +	 */ +	for (i = 0; i < 2; i++) +	{ +		decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); +		ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	} +	 +	/* decl t0 */ +	decl = vl_decl_temps(0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* mov o0, i0		; Move pos in to pos out */ +	inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, 0, TGSI_FILE_INPUT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* mul t0, i1, c0	; Scale unit texcoord rect to source size */ +	inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 1, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* add o1, t0, c1	; Translate texcoord rect into position */ +	inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 1, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	vs.tokens = tokens; +	context->states.csc.vertex_shader = pipe->create_vs_state(pipe, &vs); +	//free(tokens); +	 +	return 0; +} + +static int vlCreateFragmentShaderCSC(struct VL_CONTEXT *context) +{ +	const unsigned int		max_tokens = 50; + +	struct pipe_context		*pipe; +	struct pipe_shader_state	fs; +	struct tgsi_token		*tokens; +	struct tgsi_header		*header; + +	struct tgsi_full_declaration	decl; +	struct tgsi_full_instruction	inst; +	 +	unsigned int			ti; +	unsigned int			i; +	 +	assert(context); +	 +	pipe = context->pipe; +	tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + +	/* Version */ +	*(struct tgsi_version*)&tokens[0] = tgsi_build_version(); +	/* Header */ +	header = (struct tgsi_header*)&tokens[1]; +	*header = tgsi_build_header(); +	/* Processor */ +	*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + +	ti = 3; + +	/* decl i0		; Texcoords for s0 */ +	decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * decl c0		; Bias vector for CSC +	 * decl c1-c4		; CSC matrix c1-c4 +	 */ +	decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 4); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + +	/* decl o0		; Fragment color */ +	decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl t0 */ +	decl = vl_decl_temps(0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* decl s0		; Sampler for tex containing picture to display */ +	decl = vl_decl_samplers(0, 0); +	ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); +	 +	/* tex2d t0, i0, s0	; Read src pixel */ +	inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* sub t0, t0, c0	; Subtract bias vector from pixel */ +	inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	 +	/* +	 * dp4 o0.x, t0, c1	; Multiply pixel by the color conversion matrix +	 * dp4 o0.y, t0, c2 +	 * dp4 o0.z, t0, c3 +	 * dp4 o0.w, t0, c4	; XXX: Don't need 4th coefficient +	 */ +	for (i = 0; i < 4; ++i) +	{ +		inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 1); +		inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; +		ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); +	} + +	/* end */ +	inst = vl_end(); +	ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + +	fs.tokens = tokens; +	context->states.csc.fragment_shader = pipe->create_fs_state(pipe, &fs); +	//free(tokens); +	 +	return 0; +} + +static int vlCreateDataBufsCSC(struct VL_CONTEXT *context) +{ +	struct pipe_context *pipe; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	/* +	Create our vertex buffer and vertex buffer element +	VB contains 4 vertices that render a quad covering the entire window +	to display a rendered surface +	Quad is rendered as a tri strip +	*/ +	context->states.csc.vertex_bufs[0].pitch = sizeof(struct VL_VERTEX2F); +	context->states.csc.vertex_bufs[0].max_index = 3; +	context->states.csc.vertex_bufs[0].buffer_offset = 0; +	context->states.csc.vertex_bufs[0].buffer = pipe->winsys->buffer_create +	( +		pipe->winsys, +		1, +		PIPE_BUFFER_USAGE_VERTEX, +		sizeof(struct VL_VERTEX2F) * 4 +	); +	 +	memcpy +	( +		pipe->winsys->buffer_map(pipe->winsys, context->states.csc.vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +		vl_surface_vertex_positions, +		sizeof(struct VL_VERTEX2F) * 4 +	); +	 +	pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.vertex_bufs[0].buffer); +	 +	context->states.csc.vertex_buf_elems[0].src_offset = 0; +	context->states.csc.vertex_buf_elems[0].vertex_buffer_index = 0; +	context->states.csc.vertex_buf_elems[0].nr_components = 2; +	context->states.csc.vertex_buf_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; +	 +	/* +	Create our texcoord buffer and texcoord buffer element +	Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices +	*/ +	context->states.csc.vertex_bufs[1].pitch = sizeof(struct VL_TEXCOORD2F); +	context->states.csc.vertex_bufs[1].max_index = 3; +	context->states.csc.vertex_bufs[1].buffer_offset = 0; +	context->states.csc.vertex_bufs[1].buffer = pipe->winsys->buffer_create +	( +		pipe->winsys, +		1, +		PIPE_BUFFER_USAGE_VERTEX, +		sizeof(struct VL_TEXCOORD2F) * 4 +	); +	 +	memcpy +	( +		pipe->winsys->buffer_map(pipe->winsys, context->states.csc.vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +		vl_surface_texcoords, +		sizeof(struct VL_TEXCOORD2F) * 4 +	); +	 +	pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.vertex_bufs[1].buffer); +	 +	context->states.csc.vertex_buf_elems[1].src_offset = 0; +	context->states.csc.vertex_buf_elems[1].vertex_buffer_index = 1; +	context->states.csc.vertex_buf_elems[1].nr_components = 2; +	context->states.csc.vertex_buf_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; +	 +	/* +	Create our vertex shader's constant buffer +	Const buffer contains scaling and translation vectors +	*/ +	context->states.csc.vs_const_buf.size = sizeof(struct VL_CSC_VS_CONSTS); +	context->states.csc.vs_const_buf.buffer = pipe->winsys->buffer_create +	( +		pipe->winsys, +		1, +		PIPE_BUFFER_USAGE_CONSTANT, +		context->states.csc.vs_const_buf.size +	); +	 +	/* +	Create our fragment shader's constant buffer +	Const buffer contains the color conversion matrix and bias vectors +	*/ +	context->states.csc.fs_const_buf.size = sizeof(struct VL_CSC_FS_CONSTS); +	context->states.csc.fs_const_buf.buffer = pipe->winsys->buffer_create +	( +		pipe->winsys, +		1, +		PIPE_BUFFER_USAGE_CONSTANT, +		context->states.csc.fs_const_buf.size +	); +	 +	/* +	TODO: Refactor this into a seperate function, +	allow changing the CSC matrix at runtime to switch between regular & full versions +	*/ +	memcpy +	( +		pipe->winsys->buffer_map(pipe->winsys, context->states.csc.fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), +		&vl_csc_fs_consts_601, +		sizeof(struct VL_CSC_FS_CONSTS) +	); +	 +	pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.fs_const_buf.buffer); +	 +	return 0; +} + +static int vlInitCSC(struct VL_CONTEXT *context) +{	 +	struct pipe_context		*pipe; +	struct pipe_sampler_state	sampler; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	/* Delay creating the FB until vlPutSurface() so we know window size */ +	context->states.csc.framebuffer.num_cbufs = 1; +	context->states.csc.framebuffer.cbufs[0] = NULL; +	context->states.csc.framebuffer.zsbuf = NULL; + +	sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +	sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +	sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +	sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; +	sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; +	sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; +	sampler.compare_mode = PIPE_TEX_COMPARE_NONE; +	sampler.compare_func = PIPE_FUNC_ALWAYS; +	sampler.normalized_coords = 1; +	/*sampler.prefilter = ;*/ +	/*sampler.shadow_ambient = ;*/ +	/*sampler.lod_bias = ;*/ +	/*sampler.min_lod = ;*/ +	/*sampler.max_lod = ;*/ +	/*sampler.border_color[i] = ;*/ +	/*sampler.max_anisotropy = ;*/ +	context->states.csc.sampler = pipe->create_sampler_state(pipe, &sampler); +	 +	vlCreateVertexShaderCSC(context); +	vlCreateFragmentShaderCSC(context); +	vlCreateDataBufsCSC(context); +	 +	return 0; +} + +static int vlDestroyCSC(struct VL_CONTEXT *context) +{ +	assert(context); +	 +	/* +	Since we create the final FB when we display our first surface, +	it may not be created if vlPutSurface() is never called +	*/ +	if (context->states.csc.framebuffer.cbufs[0]) +		context->pipe->winsys->surface_release(context->pipe->winsys, &context->states.csc.framebuffer.cbufs[0]); +	context->pipe->delete_sampler_state(context->pipe, context->states.csc.sampler); +	context->pipe->delete_vs_state(context->pipe, context->states.csc.vertex_shader); +	context->pipe->delete_fs_state(context->pipe, context->states.csc.fragment_shader); +	context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vertex_bufs[0].buffer); +	context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vertex_bufs[1].buffer); +	context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vs_const_buf.buffer); +	context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.fs_const_buf.buffer); +	 +	return 0; +} + +static int vlInitCommon(struct VL_CONTEXT *context) +{ +	struct pipe_context			*pipe; +	struct pipe_rasterizer_state		rast; +	struct pipe_blend_state			blend; +	struct pipe_depth_stencil_alpha_state	dsa; +	unsigned int				i; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	rast.flatshade = 1; +	rast.flatshade_first = 0; +	rast.light_twoside = 0; +	rast.front_winding = PIPE_WINDING_CCW; +	rast.cull_mode = PIPE_WINDING_CW; +	rast.fill_cw = PIPE_POLYGON_MODE_FILL; +	rast.fill_ccw = PIPE_POLYGON_MODE_FILL; +	rast.offset_cw = 0; +	rast.offset_ccw = 0; +	rast.scissor = 0; +	rast.poly_smooth = 0; +	rast.poly_stipple_enable = 0; +	rast.point_sprite = 0; +	rast.point_size_per_vertex = 0; +	rast.multisample = 0; +	rast.line_smooth = 0; +	rast.line_stipple_enable = 0; +	rast.line_stipple_factor = 0; +	rast.line_stipple_pattern = 0; +	rast.line_last_pixel = 0; +	/* Don't need clipping, but viewport mapping done here */ +	rast.bypass_clipping = 0; +	rast.bypass_vs = 0; +	rast.origin_lower_left = 0; +	rast.line_width = 1; +	rast.point_smooth = 0; +	rast.point_size = 1; +	rast.offset_units = 1; +	rast.offset_scale = 1; +	/*rast.sprite_coord_mode[i] = ;*/ +	context->states.common.raster = pipe->create_rasterizer_state(pipe, &rast); +	pipe->bind_rasterizer_state(pipe, context->states.common.raster); +	 +	blend.blend_enable = 0; +	blend.rgb_func = PIPE_BLEND_ADD; +	blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; +	blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE; +	blend.alpha_func = PIPE_BLEND_ADD; +	blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; +	blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE; +	blend.logicop_enable = 0; +	blend.logicop_func = PIPE_LOGICOP_CLEAR; +	/* Needed to allow color writes to FB, even if blending disabled */ +	blend.colormask = PIPE_MASK_RGBA; +	blend.dither = 0; +	context->states.common.blend = pipe->create_blend_state(pipe, &blend); +	pipe->bind_blend_state(pipe, context->states.common.blend); +	 +	dsa.depth.enabled = 0; +	dsa.depth.writemask = 0; +	dsa.depth.func = PIPE_FUNC_ALWAYS; +	dsa.depth.occlusion_count = 0; +	for (i = 0; i < 2; ++i) +	{ +		dsa.stencil[i].enabled = 0; +		dsa.stencil[i].func = PIPE_FUNC_ALWAYS; +		dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP; +		dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; +		dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP; +		dsa.stencil[i].ref_value = 0; +		dsa.stencil[i].value_mask = 0; +		dsa.stencil[i].write_mask = 0; +	} +	dsa.alpha.enabled = 0; +	dsa.alpha.func = PIPE_FUNC_ALWAYS; +	dsa.alpha.ref = 0; +	context->states.common.dsa = pipe->create_depth_stencil_alpha_state(pipe, &dsa); +	pipe->bind_depth_stencil_alpha_state(pipe, context->states.common.dsa); +	 +	return 0; +} + +static int vlDestroyCommon(struct VL_CONTEXT *context) +{ +	assert(context); +	 +	context->pipe->delete_blend_state(context->pipe, context->states.common.blend); +	context->pipe->delete_rasterizer_state(context->pipe, context->states.common.raster); +	context->pipe->delete_depth_stencil_alpha_state(context->pipe, context->states.common.dsa); +	 +	return 0; +} + +static int vlInit(struct VL_CONTEXT *context) +{ +	assert(context); +	 +	vlInitCommon(context); +	vlInitCSC(context); +	vlInitMC(context); +	vlInitIDCT(context); +	 +	return 0; +} + +static int vlDestroy(struct VL_CONTEXT *context) +{ +	assert(context); +	 +	/* XXX: Must unbind shaders before we can delete them for some reason */ +	context->pipe->bind_vs_state(context->pipe, NULL); +	context->pipe->bind_fs_state(context->pipe, NULL); +	 +	vlDestroyCommon(context); +	vlDestroyCSC(context); +	vlDestroyMC(context); +	vlDestroyIDCT(context); +	 +	return 0; +} + +int vlCreateContext +( +	Display *display, +	struct pipe_context *pipe, +	unsigned int video_width, +	unsigned int video_height, +	enum VL_FORMAT video_format, +	struct VL_CONTEXT **context +) +{ +	struct VL_CONTEXT *ctx; +	 +	assert(display); +	assert(pipe); +	assert(context); +	 +	ctx = calloc(1, sizeof(struct VL_CONTEXT)); +	 +	ctx->display = display; +	ctx->pipe = pipe; +	ctx->video_width = video_width; +	ctx->video_height = video_height; +	ctx->video_format = video_format; +	 +	vlInit(ctx); +	 +	/* Since we only change states in vlPutSurface() we need to start in render mode */ +	vlBeginRender(ctx); +	 +	*context = ctx; +	 +	return 0; +} + +int vlDestroyContext(struct VL_CONTEXT *context) +{ +	assert(context); +	 +	vlDestroy(context); +	 +	free(context); +	 +	return 0; +} + +int vlBeginRender(struct VL_CONTEXT *context) +{ +	struct pipe_context	*pipe; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	/* Frame buffer set in vlRender*Macroblock() */ +	/* Shaders, samplers, textures set in vlRender*Macroblock() */ +	pipe->set_vertex_buffers(pipe, 3, context->states.mc.vertex_bufs); +	pipe->set_vertex_elements(pipe, 3, context->states.mc.vertex_buf_elems); +	pipe->set_viewport_state(pipe, &context->states.mc.viewport); +	pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->states.mc.vs_const_buf); +	pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->states.mc.fs_const_buf); +	 +	return 0; +} + +int vlEndRender(struct VL_CONTEXT *context) +{ +	struct pipe_context *pipe; +	 +	assert(context); +	 +	pipe = context->pipe; +	 +	pipe->set_framebuffer_state(pipe, &context->states.csc.framebuffer); +	pipe->set_viewport_state(pipe, &context->states.csc.viewport); +	pipe->bind_sampler_states(pipe, 1, (void**)&context->states.csc.sampler); +	/* Source texture set in vlPutSurface() */ +	pipe->bind_vs_state(pipe, context->states.csc.vertex_shader); +	pipe->bind_fs_state(pipe, context->states.csc.fragment_shader); +	pipe->set_vertex_buffers(pipe, 2, context->states.csc.vertex_bufs); +	pipe->set_vertex_elements(pipe, 2, context->states.csc.vertex_buf_elems); +	pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->states.csc.vs_const_buf); +	pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->states.csc.fs_const_buf); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/vl_context.h b/src/gallium/state_trackers/g3dvl/vl_context.h new file mode 100644 index 0000000000..bff318854a --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_context.h @@ -0,0 +1,83 @@ +#ifndef vl_context_h +#define vl_context_h + +#include <X11/Xlib.h> +#include <pipe/p_state.h> +#include "vl_types.h" + +struct pipe_context; + +struct VL_CONTEXT +{ +	Display			*display; +	struct pipe_context	*pipe; +	unsigned int		video_width; +	unsigned int		video_height; +	enum VL_FORMAT		video_format; +	 +	struct +	{ +		struct +		{ +			struct pipe_rasterizer_state		*raster; +			struct pipe_depth_stencil_alpha_state	*dsa; +			struct pipe_blend_state			*blend; +		} common; +		 +		struct +		{ +			struct pipe_viewport_state		viewport; +			struct pipe_framebuffer_state		render_target; +			struct pipe_sampler_state		*sampler; +			struct pipe_texture			*texture; +			struct pipe_texture			*basis; +			struct pipe_shader_state		*frame_vs; +			struct pipe_shader_state		*frame_fs; +			struct pipe_vertex_buffer 		*vertex_bufs[2]; +			struct pipe_vertex_element		*vertex_buf_elems[2]; +			//struct pipe_constant_buffer		vs_const_buf, fs_const_buf; +		} idct; +		 +		struct +		{ +			struct pipe_viewport_state		viewport; +			struct pipe_framebuffer_state		render_target; +			struct pipe_sampler_state		*samplers[5]; +			struct pipe_texture			*textures[5]; +			struct pipe_shader_state		*i_vs, *p_vs[2], *b_vs[2]; +			struct pipe_shader_state		*i_fs, *p_fs[2], *b_fs[2]; +			struct pipe_vertex_buffer 		vertex_bufs[3]; +			struct pipe_vertex_element		vertex_buf_elems[3]; +			struct pipe_constant_buffer		vs_const_buf, fs_const_buf; +		} mc; +		 +		struct +		{ +			struct pipe_viewport_state		viewport; +			struct pipe_framebuffer_state		framebuffer; +			struct pipe_sampler_state		*sampler; +			struct pipe_shader_state		*vertex_shader, *fragment_shader; +			struct pipe_vertex_buffer 		vertex_bufs[2]; +			struct pipe_vertex_element		vertex_buf_elems[2]; +			struct pipe_constant_buffer		vs_const_buf, fs_const_buf; +		} csc; +	} states; +}; + +int vlCreateContext +( +	Display *display, +	struct pipe_context *pipe, +	unsigned int video_width, +	unsigned int video_height, +	enum VL_FORMAT video_format, +	struct VL_CONTEXT **context +); + +int vlDestroyContext(struct VL_CONTEXT *context); + +int vlBeginRender(struct VL_CONTEXT *context); +int vlEndRender(struct VL_CONTEXT *context); + +#endif + diff --git a/src/gallium/state_trackers/g3dvl/vl_data.c b/src/gallium/state_trackers/g3dvl/vl_data.c new file mode 100644 index 0000000000..0e5c8c77f9 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_data.c @@ -0,0 +1,180 @@ +#include "vl_data.h" + +/* + * Represents 8 triangles (4 quads, 1 per block) in noormalized coords + * that render a macroblock. + * Need to be scaled to cover mbW*mbH macroblock pixels and translated into + * position on target surface. + */ +const struct VL_VERTEX2F vl_mb_vertex_positions[24] = +{ +	{0.0f, 0.0f}, {0.0f, 0.5f}, {0.5f, 0.0f}, +	{0.5f, 0.0f}, {0.0f, 0.5f}, {0.5f, 0.5f}, +	 +	{0.5f, 0.0f}, {0.5f, 0.5f}, {1.0f, 0.0f}, +	{1.0f, 0.0f}, {0.5f, 0.5f}, {1.0f, 0.5f}, +	 +	{0.0f, 0.5f}, {0.0f, 1.0f}, {0.5f, 0.5f}, +	{0.5f, 0.5f}, {0.0f, 1.0f}, {0.5f, 1.0f}, +	 +	{0.5f, 0.5f}, {0.5f, 1.0f}, {1.0f, 0.5f}, +	{1.0f, 0.5f}, {0.5f, 1.0f}, {1.0f, 1.0f} +}; + +/* + * Represents texcoords for the above for rendering 4 luma blocks arranged + * in a bW*(bH*4) texture. First luma block located at 0,0->bW,bH; second at + * 0,bH->bW,2bH; third at 0,2bH->bW,3bH; fourth at 0,3bH->bW,4bH. + */ +const struct VL_TEXCOORD2F vl_luma_texcoords[24] = +{ +	{0.0f, 0.0f}, {0.0f, 0.25f}, {1.0f, 0.0f}, +	{1.0f, 0.0f}, {0.0f, 0.25f}, {1.0f, 0.25f}, +	 +	{0.0f, 0.25f}, {0.0f, 0.5f}, {1.0f, 0.25f}, +	{1.0f, 0.25f}, {0.0f, 0.5f}, {1.0f, 0.5f}, +	 +	{0.0f, 0.5f}, {0.0f, 0.75f}, {1.0f, 0.5f}, +	{1.0f, 0.5f}, {0.0f, 0.75f}, {1.0f, 0.75f}, +	 +	{0.0f, 0.75f}, {0.0f, 1.0f}, {1.0f, 0.75f}, +	{1.0f, 0.75f}, {0.0f, 1.0f}, {1.0f, 1.0f} +}; + +/* + * Represents texcoords for the above for rendering 1 chroma block. + * Straight forward 0,0->1,1 mapping so we can reuse the MB pos vectors. + */ +const struct VL_TEXCOORD2F *vl_chroma_420_texcoords = (const struct VL_TEXCOORD2F*)vl_mb_vertex_positions; + +/* + * Represents texcoords for the above for rendering 2 chroma blocks arranged + * in a bW*(bH*2) texture. First chroma block located at 0,0->bW,bH; second at + * 0,bH->bW,2bH. We can render this with 0,0->1,1 mapping. + * Straight forward 0,0->1,1 mapping so we can reuse MB pos vectors. + */ +const struct VL_TEXCOORD2F *vl_chroma_422_texcoords = (const struct VL_TEXCOORD2F*)vl_mb_vertex_positions; + +/* + * Represents texcoords for the above for rendering 4 chroma blocks. + * Same case as 4 luma blocks. + */ +const struct VL_TEXCOORD2F *vl_chroma_444_texcoords = vl_luma_texcoords; + +/* + * Represents 2 triangles in a strip in normalized coords. + * Used to render the surface onto the frame buffer. + */ +const struct VL_VERTEX2F vl_surface_vertex_positions[4] = +{ +	{0.0f, 0.0f}, +	{0.0f, 1.0f}, +	{1.0f, 0.0f}, +	{1.0f, 1.0f} +}; + +/* + * Represents texcoords for the above. We can use the position values directly. + */ +const struct VL_TEXCOORD2F *vl_surface_texcoords = (const struct VL_TEXCOORD2F*)vl_surface_vertex_positions; + +/* + * Used when rendering P and B macroblocks, multiplier is applied to the A channel, + * which is then added to the L channel, then the bias is subtracted from that to + * get back the differential. The differential is then added to the samples from the + * reference surface(s). + */ +const struct VL_MC_FS_CONSTS vl_mc_fs_consts = +{ +	{32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f}, +	{0.5f, 2.0f, 0.0f, 0.0f} +}; + +/* + * Identity color conversion constants, for debugging + */ +const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_identity = +{ +	{ +		0.0f, 0.0f, 0.0f, 0.0f +	}, +	{ +		1.0f, 0.0f, 0.0f, 0.0f, +		0.0f, 1.0f, 0.0f, 0.0f, +		0.0f, 0.0f, 1.0f, 0.0f, +		0.0f, 0.0f, 0.0f, 1.0f +	} +}; + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601 = +{ +	{ +		0.0f,		0.501960784f,	0.501960784f,	0.0f +	}, +	{ +		1.0f,		0.0f,		1.371f,		0.0f, +		1.0f,		-0.336f,	-0.698f,	0.0f, +		1.0f,		1.732f,		0.0f,		0.0f, +		0.0f,		0.0f,		0.0f,		1.0f +	} +}; + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601_full = +{ +	{ +		0.062745098f,	0.501960784f,	0.501960784f,	0.0f +	}, +	{ +		1.164f,		0.0f,		1.596f,		0.0f, +		1.164f,		-0.391f,	-0.813f,	0.0f, +		1.164f,		2.018f,		0.0f,		0.0f, +		0.0f,		0.0f,		0.0f,		1.0f +	} +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709 = +{ +	{ +		0.0f,		0.501960784f,	0.501960784f,	0.0f +	}, +	{ +		1.0f,		0.0f,		1.540f,		0.0f, +		1.0f,		-0.183f,	-0.459f,	0.0f, +		1.0f,		1.816f,		0.0f,		0.0f, +		0.0f,		0.0f,		0.0f,		1.0f +	} +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709_full = +{ +	{ +		0.062745098f,	0.501960784f,	0.501960784f,	0.0f +	}, +	{ +		1.164f,		0.0f,		1.793f,		0.0f, +		1.164f,		-0.213f,	-0.534f,	0.0f, +		1.164f,		2.115f,		0.0f,		0.0f, +		0.0f,		0.0f,		0.0f,		1.0f +	} +}; + diff --git a/src/gallium/state_trackers/g3dvl/vl_data.h b/src/gallium/state_trackers/g3dvl/vl_data.h new file mode 100644 index 0000000000..8f347273ad --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_data.h @@ -0,0 +1,24 @@ +#ifndef vl_data_h +#define vl_data_h + +#include "vl_types.h" + +extern const struct VL_VERTEX2F vl_mb_vertex_positions[24]; +extern const struct VL_TEXCOORD2F vl_luma_texcoords[24]; +extern const struct VL_TEXCOORD2F *vl_chroma_420_texcoords; +extern const struct VL_TEXCOORD2F *vl_chroma_422_texcoords; +extern const struct VL_TEXCOORD2F *vl_chroma_444_texcoords; + +extern const struct VL_VERTEX2F vl_surface_vertex_positions[4]; +extern const struct VL_TEXCOORD2F *vl_surface_texcoords; + +extern const struct VL_MC_FS_CONSTS vl_mc_fs_consts; + +extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_identity; +extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601; +extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601_full; +extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709; +extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709_full; + +#endif + diff --git a/src/gallium/state_trackers/g3dvl/vl_defs.h b/src/gallium/state_trackers/g3dvl/vl_defs.h new file mode 100644 index 0000000000..e668a7a10e --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_defs.h @@ -0,0 +1,12 @@ +#ifndef vl_defs_h +#define vl_defs_h + +#define VL_BLOCK_WIDTH		8 +#define VL_BLOCK_HEIGHT		8 +#define VL_BLOCK_SIZE		(VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT) +#define VL_MACROBLOCK_WIDTH	16 +#define VL_MACROBLOCK_HEIGHT	16 +#define VL_MACROBLOCK_SIZE	(VL_MACROBLOCK_WIDTH * VL_MACROBLOCK_HEIGHT) + +#endif + diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.c b/src/gallium/state_trackers/g3dvl/vl_shader_build.c new file mode 100644 index 0000000000..1dc5be6fdb --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.c @@ -0,0 +1,216 @@ +#include "vl_shader_build.h" +#include <assert.h> +#include <tgsi/util/tgsi_parse.h> +#include <tgsi/util/tgsi_build.h> + +struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last) +{ +	struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + +	decl.Declaration.File = TGSI_FILE_INPUT; +	decl.Declaration.Semantic = 1; +	decl.Semantic.SemanticName = name; +	decl.Semantic.SemanticIndex = index; +	decl.DeclarationRange.First = first; +	decl.DeclarationRange.Last = last; +	 +	return decl; +} + +struct tgsi_full_declaration vl_decl_interpolated_input +( +	unsigned int name, +	unsigned int index, +	unsigned int first, +	unsigned int last, +	int interpolation +) +{ +	struct tgsi_full_declaration decl = tgsi_default_full_declaration(); +	 +	assert +	( +		interpolation == TGSI_INTERPOLATE_CONSTANT || +		interpolation == TGSI_INTERPOLATE_LINEAR || +		interpolation == TGSI_INTERPOLATE_PERSPECTIVE +	); + +	decl.Declaration.File = TGSI_FILE_INPUT; +	decl.Declaration.Semantic = 1; +	decl.Semantic.SemanticName = name; +	decl.Semantic.SemanticIndex = index; +	decl.Declaration.Interpolate = interpolation;; +	decl.DeclarationRange.First = first; +	decl.DeclarationRange.Last = last; +	 +	return decl; +} + +struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last) +{ +	struct tgsi_full_declaration decl = tgsi_default_full_declaration(); +	 +	decl.Declaration.File = TGSI_FILE_CONSTANT; +	decl.Declaration.Semantic = 1; +	decl.Semantic.SemanticName = name; +	decl.Semantic.SemanticIndex = index; +	decl.DeclarationRange.First = first; +	decl.DeclarationRange.Last = last; +	 +	return decl; +} + +struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last) +{ +	struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + +	decl.Declaration.File = TGSI_FILE_OUTPUT; +	decl.Declaration.Semantic = 1; +	decl.Semantic.SemanticName = name; +	decl.Semantic.SemanticIndex = index; +	decl.DeclarationRange.First = first; +	decl.DeclarationRange.Last = last; +	 +	return decl; +} + +struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last) +{ +	struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + +	decl = tgsi_default_full_declaration(); +	decl.Declaration.File = TGSI_FILE_TEMPORARY; +	decl.DeclarationRange.First = first; +	decl.DeclarationRange.Last = last; +	 +	return decl; +} + +struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last) +{ +	struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + +	decl = tgsi_default_full_declaration(); +	decl.Declaration.File = TGSI_FILE_SAMPLER; +	decl.DeclarationRange.First = first; +	decl.DeclarationRange.Last = last; +	 +	return decl; +} + +struct tgsi_full_instruction vl_inst2 +( +	int opcode, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src_file, +	unsigned int src_index +) +{ +	struct tgsi_full_instruction inst = tgsi_default_full_instruction(); +	 +	inst.Instruction.Opcode = opcode; +	inst.Instruction.NumDstRegs = 1; +	inst.FullDstRegisters[0].DstRegister.File = dst_file; +	inst.FullDstRegisters[0].DstRegister.Index = dst_index; +	inst.Instruction.NumSrcRegs = 1; +	inst.FullSrcRegisters[0].SrcRegister.File = src_file; +	inst.FullSrcRegisters[0].SrcRegister.Index = src_index; +	 +	return inst; +} + +struct tgsi_full_instruction vl_inst3 +( +	int opcode, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src1_file, +	unsigned int src1_index, +	enum tgsi_file_type src2_file, +	unsigned int src2_index +) +{ +	struct tgsi_full_instruction inst = tgsi_default_full_instruction(); +	 +	inst.Instruction.Opcode = opcode; +	inst.Instruction.NumDstRegs = 1; +	inst.FullDstRegisters[0].DstRegister.File = dst_file; +	inst.FullDstRegisters[0].DstRegister.Index = dst_index; +	inst.Instruction.NumSrcRegs = 2; +	inst.FullSrcRegisters[0].SrcRegister.File = src1_file; +	inst.FullSrcRegisters[0].SrcRegister.Index = src1_index; +	inst.FullSrcRegisters[1].SrcRegister.File = src2_file; +	inst.FullSrcRegisters[1].SrcRegister.Index = src2_index; +	 +	return inst; +} + +struct tgsi_full_instruction vl_tex +( +	int tex, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src1_file, +	unsigned int src1_index, +	enum tgsi_file_type src2_file, +	unsigned int src2_index +) +{ +	struct tgsi_full_instruction inst = tgsi_default_full_instruction(); +	 +	inst.Instruction.Opcode = TGSI_OPCODE_TEX; +	inst.Instruction.NumDstRegs = 1; +	inst.FullDstRegisters[0].DstRegister.File = dst_file; +	inst.FullDstRegisters[0].DstRegister.Index = dst_index; +	inst.Instruction.NumSrcRegs = 2; +	inst.InstructionExtTexture.Texture = tex; +	inst.FullSrcRegisters[0].SrcRegister.File = src1_file; +	inst.FullSrcRegisters[0].SrcRegister.Index = src1_index; +	inst.FullSrcRegisters[1].SrcRegister.File = src2_file; +	inst.FullSrcRegisters[1].SrcRegister.Index = src2_index; +	 +	return inst; +} + +struct tgsi_full_instruction vl_inst4 +( +	int opcode, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src1_file, +	unsigned int src1_index, +	enum tgsi_file_type src2_file, +	unsigned int src2_index, +	enum tgsi_file_type src3_file, +	unsigned int src3_index +) +{ +	struct tgsi_full_instruction inst = tgsi_default_full_instruction(); +	 +	inst.Instruction.Opcode = opcode; +	inst.Instruction.NumDstRegs = 1; +	inst.FullDstRegisters[0].DstRegister.File = dst_file; +	inst.FullDstRegisters[0].DstRegister.Index = dst_index; +	inst.Instruction.NumSrcRegs = 3; +	inst.FullSrcRegisters[0].SrcRegister.File = src1_file; +	inst.FullSrcRegisters[0].SrcRegister.Index = src1_index; +	inst.FullSrcRegisters[1].SrcRegister.File = src2_file; +	inst.FullSrcRegisters[1].SrcRegister.Index = src2_index; +	inst.FullSrcRegisters[2].SrcRegister.File = src3_file; +	inst.FullSrcRegisters[2].SrcRegister.Index = src3_index; +	 +	return inst; +} + +struct tgsi_full_instruction vl_end(void) +{ +	struct tgsi_full_instruction inst = tgsi_default_full_instruction(); +	 +	inst.Instruction.Opcode = TGSI_OPCODE_END; +	inst.Instruction.NumDstRegs = 0; +	inst.Instruction.NumSrcRegs = 0; +	 +	return inst; +} + diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.h b/src/gallium/state_trackers/g3dvl/vl_shader_build.h new file mode 100644 index 0000000000..878d7e2c45 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.h @@ -0,0 +1,62 @@ +#ifndef vl_shader_build_h +#define vl_shader_build_h + +#include <pipe/p_shader_tokens.h> + +struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_interpolated_input +( +	unsigned int name, +	unsigned int index, +	unsigned int first, +	unsigned int last, +	int interpolation +); +struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last); +struct tgsi_full_instruction vl_inst2 +( +	int opcode, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src_file, +	unsigned int src_index +); +struct tgsi_full_instruction vl_inst3 +( +	int opcode, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src1_file, +	unsigned int src1_index, +	enum tgsi_file_type src2_file, +	unsigned int src2_index +); +struct tgsi_full_instruction vl_tex +( +	int tex, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src1_file, +	unsigned int src1_index, +	enum tgsi_file_type src2_file, +	unsigned int src2_index +); +struct tgsi_full_instruction vl_inst4 +( +	int opcode, +	enum tgsi_file_type dst_file, +	unsigned int dst_index, +	enum tgsi_file_type src1_file, +	unsigned int src1_index, +	enum tgsi_file_type src2_file, +	unsigned int src2_index, +	enum tgsi_file_type src3_file, +	unsigned int src3_index +); +struct tgsi_full_instruction vl_end(void); + +#endif + diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c new file mode 100644 index 0000000000..1386b1107c --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_surface.c @@ -0,0 +1,628 @@ +#include "vl_surface.h" +#include <assert.h> +#include <stdlib.h> +#include <pipe/p_context.h> +#include <pipe/p_state.h> +#include <pipe/p_format.h> +#include <pipe/p_inlines.h> +#include <vl_winsys.h> +#include "vl_context.h" +#include "vl_defs.h" +#include "vl_util.h" + +/*#define DO_IDCT*/ + +#ifdef DO_IDCT +static int vlTransformBlock(short *src, short *dst, short bias) +{ +	static const float basis[8][8] = +	{ +		{0.3536,   0.4904,   0.4619,   0.4157,   0.3536,   0.2778,   0.1913,   0.0975}, +		{0.3536,   0.4157,   0.1913,  -0.0975,  -0.3536,  -0.4904,  -0.4619,  -0.2778}, +		{0.3536,   0.2778,  -0.1913,  -0.4904,  -0.3536,   0.0975,   0.4619,   0.4157}, +		{0.3536,   0.0975,  -0.4619,  -0.2778,   0.3536,   0.4157,  -0.1913,  -0.4904}, +		{0.3536,  -0.0975,  -0.4619,   0.2778,   0.3536,  -0.4157,  -0.1913,   0.4904}, +		{0.3536,  -0.2778,  -0.1913,   0.4904,  -0.3536,  -0.0975,   0.4619,  -0.4157}, +		{0.3536,  -0.4157,   0.1913,   0.0975,  -0.3536,   0.4904,  -0.4619,   0.2778}, +		{0.3536,  -0.4904,   0.4619,  -0.4157,   0.3536,  -0.2778,   0.1913,  -0.0975} +	}; +	 +	unsigned int	x, y; +	short		tmp[64]; +	 +	for (y = 0; y < VL_BLOCK_HEIGHT; ++y) +		for (x = 0; x < VL_BLOCK_WIDTH; ++x) +			tmp[y * VL_BLOCK_WIDTH + x] = (short) +			( +				src[y * VL_BLOCK_WIDTH + 0] * basis[x][0] + +				src[y * VL_BLOCK_WIDTH + 1] * basis[x][1] + +				src[y * VL_BLOCK_WIDTH + 2] * basis[x][2] + +				src[y * VL_BLOCK_WIDTH + 3] * basis[x][3] + +				src[y * VL_BLOCK_WIDTH + 4] * basis[x][4] + +				src[y * VL_BLOCK_WIDTH + 5] * basis[x][5] + +				src[y * VL_BLOCK_WIDTH + 6] * basis[x][6] + +				src[y * VL_BLOCK_WIDTH + 7] * basis[x][7] +			); + +	for (x = 0; x < VL_BLOCK_WIDTH; ++x) +		for (y = 0; y < VL_BLOCK_HEIGHT; ++y) +		{ +			dst[y * VL_BLOCK_WIDTH + x] = bias + (short) +			( +				tmp[0 * VL_BLOCK_WIDTH + x] * basis[y][0] + +				tmp[1 * VL_BLOCK_WIDTH + x] * basis[y][1] + +				tmp[2 * VL_BLOCK_WIDTH + x] * basis[y][2] + +				tmp[3 * VL_BLOCK_WIDTH + x] * basis[y][3] + +				tmp[4 * VL_BLOCK_WIDTH + x] * basis[y][4] + +				tmp[5 * VL_BLOCK_WIDTH + x] * basis[y][5] + +				tmp[6 * VL_BLOCK_WIDTH + x] * basis[y][6] + +				tmp[7 * VL_BLOCK_WIDTH + x] * basis[y][7] +			); +			if (dst[y * VL_BLOCK_WIDTH + x] > 255) +				dst[y * VL_BLOCK_WIDTH + x] = 255; +			else if (bias > 0 && dst[y * VL_BLOCK_WIDTH + x] < 0) +				dst[y * VL_BLOCK_WIDTH + x] = 0; +		} +	return 0; +} +#endif + +static int vlGrabFrameCodedBlock(short *src, short *dst, unsigned int dst_pitch) +{ +	unsigned int y; +	 +	for (y = 0; y < VL_BLOCK_HEIGHT; ++y) +		memcpy +		( +			dst + y * dst_pitch, +			src + y * VL_BLOCK_WIDTH, +			VL_BLOCK_WIDTH * 2 +		); +	 +	return 0; +} + +static int vlGrabFieldCodedBlock(short *src, short *dst, unsigned int dst_pitch) +{ +	unsigned int y; +	 +	for (y = 0; y < VL_BLOCK_HEIGHT / 2; ++y) +		memcpy +		( +			dst + y * dst_pitch * 2, +			src + y * VL_BLOCK_WIDTH, +			VL_BLOCK_WIDTH * 2 +		); +	 +	dst += VL_BLOCK_HEIGHT * dst_pitch; +	 +	for (; y < VL_BLOCK_HEIGHT; ++y) +		memcpy +		( +			dst + y * dst_pitch * 2, +			src + y * VL_BLOCK_WIDTH, +			VL_BLOCK_WIDTH * 2 +		); +	 +	return 0; +} + +static int vlGrabNoBlock(short *dst, unsigned int dst_pitch) +{ +	unsigned int y; +	 +	for (y = 0; y < VL_BLOCK_HEIGHT; ++y) +		memset +		( +			dst + y * dst_pitch, +			0, +			VL_BLOCK_WIDTH * 2 +		); +	 +	return 0; +} + +static int vlGrabBlocks +( +	struct VL_CONTEXT *context, +	unsigned int coded_block_pattern, +	enum VL_DCT_TYPE dct_type, +	enum VL_SAMPLE_TYPE sample_type, +	short *blocks +) +{ +	struct pipe_surface	*tex_surface; +	short			*texels; +	unsigned int		tex_pitch; +	unsigned int		tb, sb = 0; +	 +	assert(context); +	assert(blocks); +	 +	tex_surface = context->pipe->screen->get_tex_surface +	( +		context->pipe->screen, +		context->states.mc.textures[0], +		0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE +	); +	 +	texels = pipe_surface_map(tex_surface, PIPE_BUFFER_USAGE_CPU_WRITE); +	tex_pitch = tex_surface->stride / tex_surface->block.size; +	 +	for (tb = 0; tb < 4; ++tb) +	{ +		if ((coded_block_pattern >> (5 - tb)) & 1) +		{ +			short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; +			 +#ifdef DO_IDCT +			vlTransformBlock(cur_block, cur_block, sample_type == VL_FULL_SAMPLE ? 128 : 0); +#endif +			 +			if (dct_type == VL_DCT_FRAME_CODED) +				vlGrabFrameCodedBlock +				( +					cur_block, +					texels + tb * tex_pitch * VL_BLOCK_HEIGHT, +					tex_pitch +				); +			else +				vlGrabFieldCodedBlock +				( +					cur_block, +					texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch, +					tex_pitch +				); +			 +			++sb; +		} +		else +			vlGrabNoBlock(texels + tb * tex_pitch * VL_BLOCK_HEIGHT, tex_pitch); +	} +	 +	pipe_surface_unmap(tex_surface); +	 +	/* TODO: Implement 422, 444 */ +	for (tb = 0; tb < 2; ++tb) +	{ +		tex_surface = context->pipe->screen->get_tex_surface +			( +				context->pipe->screen, +				context->states.mc.textures[tb + 1], +				0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE +			); +	 +		texels = pipe_surface_map(tex_surface, PIPE_BUFFER_USAGE_CPU_WRITE); +		tex_pitch = tex_surface->stride / tex_surface->block.size; +		 +		if ((coded_block_pattern >> (1 - tb)) & 1) +		{ +			short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; +			 +#ifdef DO_IDCT +			vlTransformBlock(cur_block, cur_block, sample_type == VL_FULL_SAMPLE ? 128 : 0); +#endif +			 +			vlGrabFrameCodedBlock +			( +				cur_block, +				texels, +				tex_pitch +			); +			 +			++sb; +		} +		else +			vlGrabNoBlock(texels, tex_pitch); +		 +		pipe_surface_unmap(tex_surface); +	} +	 +	return 0; +} + +int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface) +{ +	struct pipe_context	*pipe; +	struct pipe_texture	template; +	struct VL_SURFACE	*sfc; +	 +	assert(context); +	assert(surface); +	 +	pipe = context->pipe; +	 +	sfc = calloc(1, sizeof(struct VL_SURFACE)); +	 +	sfc->context = context; +	sfc->width = vlRoundUpPOT(context->video_width); +	sfc->height = vlRoundUpPOT(context->video_height); +	sfc->format = context->video_format; +	 +	memset(&template, 0, sizeof(struct pipe_texture)); +	template.target = PIPE_TEXTURE_2D; +	template.format = PIPE_FORMAT_A8R8G8B8_UNORM; +	template.last_level = 0; +	template.width[0] = sfc->width; +	template.height[0] = sfc->height; +	template.depth[0] = 1; +	template.compressed = 0; +	pf_get_block(template.format, &template.block); +	/* XXX: Needed? */ +	template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET; +	 +	sfc->texture = pipe->screen->texture_create(pipe->screen, &template); +	 +	*surface = sfc; +	 +	return 0; +} + +int vlDestroySurface(struct VL_SURFACE *surface) +{ +	assert(surface); +	pipe_texture_release(&surface->texture); +	free(surface); +	 +	return 0; +} + +int vlRenderIMacroBlock +( +	enum VL_PICTURE picture_type, +	enum VL_FIELD_ORDER field_order, +	unsigned int mbx, +	unsigned int mby, +	unsigned int coded_block_pattern, +	enum VL_DCT_TYPE dct_type, +	short *blocks, +	struct VL_SURFACE *surface +) +{ +	struct pipe_context	*pipe; +	struct VL_MC_VS_CONSTS	*vs_consts; +	 +	assert(blocks); +	assert(surface); +	 +	/* TODO: Implement interlaced rendering */ +	if (picture_type != VL_FRAME_PICTURE) +		return 0; +	 +	vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_FULL_SAMPLE, blocks); +	 +	pipe = surface->context->pipe; +	 +	vs_consts = pipe->winsys->buffer_map +	( +		pipe->winsys, +		surface->context->states.mc.vs_const_buf.buffer, +		PIPE_BUFFER_USAGE_CPU_WRITE +	); +	 +	vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width; +	vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height; +	vs_consts->scale.z = 1.0f; +	vs_consts->scale.w = 1.0f; +	vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width; +	vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height; +	vs_consts->mb_pos_trans.z = 0.0f; +	vs_consts->mb_pos_trans.w = 0.0f; +	 +	pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer); +	 +	surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface +	( +		pipe->screen, +		surface->texture, +		0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE +	); +	pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target); +	pipe->set_sampler_textures(pipe, 3, surface->context->states.mc.textures); +	pipe->bind_sampler_states(pipe, 3, (void**)surface->context->states.mc.samplers); +	pipe->bind_vs_state(pipe, surface->context->states.mc.i_vs); +	pipe->bind_fs_state(pipe, surface->context->states.mc.i_fs); +	 +	pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24); +	 +	return 0; +} + +int vlRenderPMacroBlock +( +	enum VL_PICTURE picture_type, +	enum VL_FIELD_ORDER field_order, +	unsigned int mbx, +	unsigned int mby, +	enum VL_MC_TYPE mc_type, +	struct VL_MOTION_VECTOR *motion_vector, +	unsigned int coded_block_pattern, +	enum VL_DCT_TYPE dct_type, +	short *blocks, +	struct VL_SURFACE *ref_surface, +	struct VL_SURFACE *surface +) +{ +	struct pipe_context	*pipe; +	struct VL_MC_VS_CONSTS	*vs_consts; +	 +	assert(motion_vectors); +	assert(blocks); +	assert(ref_surface); +	assert(surface); +	 +	/* TODO: Implement interlaced rendering */ +	if (picture_type != VL_FRAME_PICTURE) +		return 0; +	/* TODO: Implement other MC types */ +	if (mc_type != VL_FRAME_MC && mc_type != VL_FIELD_MC) +		return 0; +	 +	vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks); +	 +	pipe = surface->context->pipe; +	 +	vs_consts = pipe->winsys->buffer_map +	( +		pipe->winsys, +		surface->context->states.mc.vs_const_buf.buffer, +		PIPE_BUFFER_USAGE_CPU_WRITE +	); +	 +	vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width; +	vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height; +	vs_consts->scale.z = 1.0f; +	vs_consts->scale.w = 1.0f; +	vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width; +	vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height; +	vs_consts->mb_pos_trans.z = 0.0f; +	vs_consts->mb_pos_trans.w = 0.0f; +	vs_consts->mb_tc_trans[0].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->top_field.x * 0.5f) / (float)surface->width; +	vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->top_field.y * 0.5f) / (float)surface->height; +	vs_consts->mb_tc_trans[0].top_field.z = 0.0f; +	vs_consts->mb_tc_trans[0].top_field.w = 0.0f; +	 +	if (mc_type == VL_FIELD_MC) +	{ +		vs_consts->denorm.x = (float)surface->width; +		vs_consts->denorm.y = (float)surface->height; +		 +		vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->bottom_field.x * 0.5f) / (float)surface->width; +		vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->bottom_field.y * 0.5f) / (float)surface->height; +		vs_consts->mb_tc_trans[0].bottom_field.z = 0.0f; +		vs_consts->mb_tc_trans[0].bottom_field.w = 0.0f; +		 +		pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs[1]); +		pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs[1]); +	} +	else +	{ +		pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs[0]); +		pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs[0]); +	} +	 +	pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer); +	 +	surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface +	( +		pipe->screen, +		surface->texture, +		0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE +	); +	pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target); +	 +	surface->context->states.mc.textures[3] = ref_surface->texture; +	pipe->set_sampler_textures(pipe, 4, surface->context->states.mc.textures); +	pipe->bind_sampler_states(pipe, 4, (void**)surface->context->states.mc.samplers); +	 +	pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24); +	 +	return 0; +} + +int vlRenderBMacroBlock +( +	enum VL_PICTURE picture_type, +	enum VL_FIELD_ORDER field_order, +	unsigned int mbx, +	unsigned int mby, +	enum VL_MC_TYPE mc_type, +	struct VL_MOTION_VECTOR *motion_vector, +	unsigned int coded_block_pattern, +	enum VL_DCT_TYPE dct_type, +	short *blocks, +	struct VL_SURFACE *past_surface, +	struct VL_SURFACE *future_surface, +	struct VL_SURFACE *surface +) +{ +	struct pipe_context	*pipe; +	struct VL_MC_VS_CONSTS	*vs_consts; +	 +	assert(motion_vectors); +	assert(blocks); +	assert(ref_surface); +	assert(surface); +	 +	/* TODO: Implement interlaced rendering */ +	if (picture_type != VL_FRAME_PICTURE) +		return 0; +	/* TODO: Implement other MC types */ +	if (mc_type != VL_FRAME_MC && mc_type != VL_FIELD_MC) +		return 0; +	 +	vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks); +	 +	pipe = surface->context->pipe; +	 +	vs_consts = pipe->winsys->buffer_map +	( +		pipe->winsys, +		surface->context->states.mc.vs_const_buf.buffer, +		PIPE_BUFFER_USAGE_CPU_WRITE +	); +	 +	vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width; +	vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height; +	vs_consts->scale.z = 1.0f; +	vs_consts->scale.w = 1.0f; +	vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width; +	vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height; +	vs_consts->mb_pos_trans.z = 0.0f; +	vs_consts->mb_pos_trans.w = 0.0f; +	vs_consts->mb_tc_trans[0].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].top_field.x * 0.5f) / (float)surface->width; +	vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].top_field.y * 0.5f) / (float)surface->height; +	vs_consts->mb_tc_trans[0].top_field.z = 0.0f; +	vs_consts->mb_tc_trans[0].top_field.w = 0.0f; +	vs_consts->mb_tc_trans[1].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].top_field.x * 0.5f) / (float)surface->width; +	vs_consts->mb_tc_trans[1].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].top_field.y * 0.5f) / (float)surface->height; +	vs_consts->mb_tc_trans[1].top_field.z = 0.0f; +	vs_consts->mb_tc_trans[1].top_field.w = 0.0f; +	 +	if (mc_type == VL_FIELD_MC) +	{ +		vs_consts->denorm.x = (float)surface->width; +		vs_consts->denorm.y = (float)surface->height; +		 +		vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].bottom_field.x * 0.5f) / (float)surface->width; +		vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].bottom_field.y * 0.5f) / (float)surface->height; +		vs_consts->mb_tc_trans[0].bottom_field.z = 0.0f; +		vs_consts->mb_tc_trans[0].bottom_field.w = 0.0f; +		vs_consts->mb_tc_trans[1].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].bottom_field.x * 0.5f) / (float)surface->width; +		vs_consts->mb_tc_trans[1].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].bottom_field.y * 0.5f) / (float)surface->height; +		vs_consts->mb_tc_trans[1].bottom_field.z = 0.0f; +		vs_consts->mb_tc_trans[1].bottom_field.w = 0.0f; +		 +		pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs[1]); +		pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs[1]); +	} +	else +	{ +		pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs[0]); +		pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs[0]); +	} +	 +	pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer); +	 +	surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface +	( +		pipe->screen, +		surface->texture, +		0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE +	); +	pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target); +	 +	surface->context->states.mc.textures[3] = past_surface->texture; +	surface->context->states.mc.textures[4] = future_surface->texture; +	pipe->set_sampler_textures(pipe, 5, surface->context->states.mc.textures); +	pipe->bind_sampler_states(pipe, 5, (void**)surface->context->states.mc.samplers); +	 +	pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24); +	 +	return 0; +} + +int vlPutSurface +( +	struct VL_SURFACE *surface, +	Drawable drawable, +	unsigned int srcx, +	unsigned int srcy, +	unsigned int srcw, +	unsigned int srch, +	unsigned int destx, +	unsigned int desty, +	unsigned int destw, +	unsigned int desth, +	enum VL_PICTURE picture_type +) +{ +	unsigned int		create_fb = 0; +	struct pipe_context	*pipe; +	struct VL_CSC_VS_CONSTS	*vs_consts; +	 +	assert(surface); +	 +	pipe = surface->context->pipe; +	 +	if (!surface->context->states.csc.framebuffer.cbufs[0]) +		create_fb = 1; +	else if +	( +		surface->context->states.csc.framebuffer.width != destw || +		surface->context->states.csc.framebuffer.height != desth +	) +	{ +		pipe->winsys->surface_release +		( +			pipe->winsys, +			&surface->context->states.csc.framebuffer.cbufs[0] +		); +		 +		create_fb = 1; +	} +	 +	if (create_fb) +	{ +		surface->context->states.csc.viewport.scale[0] = destw; +		surface->context->states.csc.viewport.scale[1] = desth; +		surface->context->states.csc.viewport.scale[2] = 1; +		surface->context->states.csc.viewport.scale[3] = 1; +		surface->context->states.csc.viewport.translate[0] = 0; +		surface->context->states.csc.viewport.translate[1] = 0; +		surface->context->states.csc.viewport.translate[2] = 0; +		surface->context->states.csc.viewport.translate[3] = 0; +		 +		surface->context->states.csc.framebuffer.width = destw; +		surface->context->states.csc.framebuffer.height = desth; +		surface->context->states.csc.framebuffer.cbufs[0] = pipe->winsys->surface_alloc(pipe->winsys); +		pipe->winsys->surface_alloc_storage +		( +			pipe->winsys, +			surface->context->states.csc.framebuffer.cbufs[0], +			destw, +			desth, +			PIPE_FORMAT_A8R8G8B8_UNORM, +			/* XXX: SoftPipe doesn't change GPU usage to CPU like it does for textures */ +			PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE, +			0 +		); +	} +	 +	vlEndRender(surface->context); +	 +	vs_consts = pipe->winsys->buffer_map +	( +		pipe->winsys, +		surface->context->states.csc.vs_const_buf.buffer, +		PIPE_BUFFER_USAGE_CPU_WRITE +	); +	 +	vs_consts->src_scale.x = srcw / (float)surface->width; +	vs_consts->src_scale.y = srch / (float)surface->height; +	vs_consts->src_scale.z = 1; +	vs_consts->src_scale.w = 1; +	vs_consts->src_trans.x = srcx / (float)surface->width; +	vs_consts->src_trans.y = srcy / (float)surface->height; +	vs_consts->src_trans.z = 0; +	vs_consts->src_trans.w = 0; +	 +	pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.csc.vs_const_buf.buffer); +	 +	pipe->set_sampler_textures(pipe, 1, &surface->texture); +	pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); +	pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); +	bind_pipe_drawable(pipe, drawable); +	/* TODO: Need to take destx, desty into consideration */ +	pipe->winsys->flush_frontbuffer +	( +		pipe->winsys, +		surface->context->states.csc.framebuffer.cbufs[0], +		pipe->priv +	); +	 +	vlBeginRender(surface->context); +	 +	return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.h b/src/gallium/state_trackers/g3dvl/vl_surface.h new file mode 100644 index 0000000000..9f56b77e1e --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_surface.h @@ -0,0 +1,81 @@ +#ifndef vl_surface_h +#define vl_surface_h + +#include <X11/Xlib.h> +#include "vl_types.h" + +struct pipe_texture; + +struct VL_SURFACE +{ +	struct VL_CONTEXT	*context; +	unsigned int		width; +	unsigned int		height; +	enum VL_FORMAT		format; +	struct pipe_texture	*texture; +}; + +int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface); + +int vlDestroySurface(struct VL_SURFACE *surface); + +int vlRenderIMacroBlock +( +	enum VL_PICTURE picture_type, +	enum VL_FIELD_ORDER field_order, +	unsigned int mbx, +	unsigned int mby, +	unsigned int coded_block_pattern, +	enum VL_DCT_TYPE dct_type, +	short *blocks, +	struct VL_SURFACE *surface +); + +int vlRenderPMacroBlock +( +	enum VL_PICTURE picture_type, +	enum VL_FIELD_ORDER field_order, +	unsigned int mbx, +	unsigned int mby, +	enum VL_MC_TYPE mc_type, +	struct VL_MOTION_VECTOR *motion_vector, +	unsigned int coded_block_pattern, +	enum VL_DCT_TYPE dct_type, +	short *blocks, +	struct VL_SURFACE *ref_surface, +	struct VL_SURFACE *surface +); + +int vlRenderBMacroBlock +( +	enum VL_PICTURE picture_type, +	enum VL_FIELD_ORDER field_order, +	unsigned int mbx, +	unsigned int mby, +	enum VL_MC_TYPE mc_type, +	struct VL_MOTION_VECTOR *motion_vector, +	unsigned int coded_block_pattern, +	enum VL_DCT_TYPE dct_type, +	short *blocks, +	struct VL_SURFACE *past_surface, +	struct VL_SURFACE *future_surface, +	struct VL_SURFACE *surface +); + +int vlPutSurface +( +	struct VL_SURFACE *surface, +	Drawable drawable, +	unsigned int srcx, +	unsigned int srcy, +	unsigned int srcw, +	unsigned int srch, +	unsigned int destx, +	unsigned int desty, +	unsigned int destw, +	unsigned int desth, +	enum VL_PICTURE picture_type +); + +#endif + diff --git a/src/gallium/state_trackers/g3dvl/vl_types.h b/src/gallium/state_trackers/g3dvl/vl_types.h new file mode 100644 index 0000000000..4d210c9e0a --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_types.h @@ -0,0 +1,102 @@ +#ifndef vl_types_h +#define vl_types_h + +enum VL_FORMAT +{ +	VL_FORMAT_YCBCR_420, +	VL_FORMAT_YCBCR_422, +	VL_FORMAT_YCBCR_444 +}; + +enum VL_PICTURE +{ +	VL_TOP_FIELD, +	VL_BOTTOM_FIELD, +	VL_FRAME_PICTURE +}; + +enum VL_FIELD_ORDER +{ +	VL_FIELD_FIRST, +	VL_FIELD_SECOND +}; + +enum VL_DCT_TYPE +{ +	VL_DCT_FIELD_CODED, +	VL_DCT_FRAME_CODED +}; + +enum VL_SAMPLE_TYPE +{ +	VL_FULL_SAMPLE, +	VL_DIFFERENCE_SAMPLE +}; + +enum VL_MC_TYPE +{ +	VL_FIELD_MC, +	VL_FRAME_MC, +	VL_DUAL_PRIME_MC, +	VL_16x8_MC = VL_FRAME_MC +}; + +struct VL_VERTEX4F +{ +	float x, y, z, w; +}; + +struct VL_VERTEX2F +{ +	float x, y; +}; + +struct VL_TEXCOORD2F +{ +	float s, t; +}; + +struct VL_MC_VS_CONSTS +{ +	struct VL_VERTEX4F	scale; +	struct VL_VERTEX4F	mb_pos_trans; +	struct VL_VERTEX4F	denorm; +	struct +	{ +		struct VL_VERTEX4F	top_field; +		struct VL_VERTEX4F	bottom_field; +	} mb_tc_trans[2]; +}; + +struct VL_MC_FS_CONSTS +{ +	struct VL_VERTEX4F	multiplier; +	struct VL_VERTEX4F	bias; +	struct VL_VERTEX4F	y_divider; +}; + +struct VL_CSC_VS_CONSTS +{ +	struct VL_VERTEX4F	src_scale; +	struct VL_VERTEX4F	src_trans; +}; + +struct VL_CSC_FS_CONSTS +{ +	struct VL_VERTEX4F	bias; +	float			matrix[16]; +}; + +struct VL_MOTION_VECTOR +{ +	struct +	{ +		int x, y; +	} top_field, bottom_field; +}; + +struct VL_CONTEXT; +struct VL_SURFACE; + +#endif + diff --git a/src/gallium/state_trackers/g3dvl/vl_util.c b/src/gallium/state_trackers/g3dvl/vl_util.c new file mode 100644 index 0000000000..2421ae2210 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_util.c @@ -0,0 +1,17 @@ +#include "vl_util.h" +#include <assert.h> + +unsigned int vlRoundUpPOT(unsigned int x) +{ +	unsigned int i; +	 +	assert(x > 0); +	 +	--x; +	 +	for (i = 1; i < sizeof(unsigned int) * 8; i <<= 1) +		x |= x >> i; +	 +	return x + 1; +} + diff --git a/src/gallium/state_trackers/g3dvl/vl_util.h b/src/gallium/state_trackers/g3dvl/vl_util.h new file mode 100644 index 0000000000..e4b72c4f87 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_util.h @@ -0,0 +1,7 @@ +#ifndef vl_util_h +#define vl_util_h + +unsigned int vlRoundUpPOT(unsigned int x); + +#endif + diff --git a/src/gallium/winsys/dri/nouveau/Makefile b/src/gallium/winsys/dri/nouveau/Makefile new file mode 100644 index 0000000000..be630ff6d1 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/Makefile @@ -0,0 +1,45 @@ + +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = nouveau_dri.so + +MINIGLX_SOURCES = + +PIPE_DRIVERS = \ +	$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ +	$(TOP)/src/gallium/drivers/nv04/libnv04.a \ +	$(TOP)/src/gallium/drivers/nv10/libnv10.a \ +	$(TOP)/src/gallium/drivers/nv30/libnv30.a \ +	$(TOP)/src/gallium/drivers/nv40/libnv40.a \ +	$(TOP)/src/gallium/drivers/nv50/libnv50.a + +DRIVER_SOURCES = \ +	nouveau_bo.c \ +	nouveau_channel.c \ +	nouveau_context.c \ +	nouveau_device.c \ +	nouveau_dma.c \ +	nouveau_fence.c \ +	nouveau_grobj.c \ +	nouveau_lock.c \ +	nouveau_notifier.c \ +	nouveau_pushbuf.c \ +	nouveau_resource.c \ +	nouveau_screen.c \ +	nouveau_swapbuffers.c \ +	nouveau_winsys.c \ +	nouveau_winsys_pipe.c \ +	nouveau_winsys_softpipe.c \ +	nv04_surface.c \ +	nv50_surface.c + +C_SOURCES = \ +	$(COMMON_GALLIUM_SOURCES) \ +	$(DRIVER_SOURCES) + +ASM_SOURCES =  + +include ../Makefile.template + +symlinks: diff --git a/src/gallium/winsys/dri/nouveau/nouveau_bo.c b/src/gallium/winsys/dri/nouveau/nouveau_bo.c new file mode 100644 index 0000000000..b5942994d9 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_bo.c @@ -0,0 +1,470 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdint.h> +#include <stdlib.h> +#include <errno.h> +#include <assert.h> + +#include "nouveau_drmif.h" +#include "nouveau_dma.h" +#include "nouveau_local.h" + +static void +nouveau_mem_free(struct nouveau_device *dev, struct drm_nouveau_mem_alloc *ma, +		 void **map) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(dev); +	struct drm_nouveau_mem_free mf; + +	if (map && *map) { +		drmUnmap(*map, ma->size); +		*map = NULL; +	} + +	if (ma->size) { +		mf.offset = ma->offset; +		mf.flags = ma->flags; +		drmCommandWrite(nvdev->fd, DRM_NOUVEAU_MEM_FREE, +				&mf, sizeof(mf)); +		ma->size = 0; +	} +} + +static int +nouveau_mem_alloc(struct nouveau_device *dev, unsigned size, unsigned align, +		  uint32_t flags, struct drm_nouveau_mem_alloc *ma, void **map) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(dev); +	int ret; + +	ma->alignment = align; +	ma->size = size; +	ma->flags = flags; +	if (map) +		ma->flags |= NOUVEAU_MEM_MAPPED; +	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_MEM_ALLOC, ma, +				  sizeof(struct drm_nouveau_mem_alloc)); +	if (ret) +		return ret; + +	if (map) { +		ret = drmMap(nvdev->fd, ma->map_handle, ma->size, map); +		if (ret) { +			*map = NULL; +			nouveau_mem_free(dev, ma, map); +			return ret; +		} +	} + +	return 0; +} + +static void +nouveau_bo_tmp_del(void *priv) +{ +	struct nouveau_resource *r = priv; + +	nouveau_fence_ref(NULL, (struct nouveau_fence **)&r->priv); +	nouveau_resource_free(&r); +} + +static unsigned +nouveau_bo_tmp_max(struct nouveau_device_priv *nvdev) +{ +	struct nouveau_resource *r = nvdev->sa_heap; +	unsigned max = 0; + +	while (r) { +		if (r->in_use && !nouveau_fence(r->priv)->emitted) { +			r = r->next; +			continue; +		} + +		if (max < r->size) +			max = r->size; +		r = r->next; +	} + +	return max; +} + +static struct nouveau_resource * +nouveau_bo_tmp(struct nouveau_channel *chan, unsigned size, +	       struct nouveau_fence *fence) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(chan->device); +	struct nouveau_resource *r = NULL; +	struct nouveau_fence *ref = NULL; + +	if (fence) +		nouveau_fence_ref(fence, &ref); +	else +		nouveau_fence_new(chan, &ref); +	assert(ref); + +	while (nouveau_resource_alloc(nvdev->sa_heap, size, ref, &r)) { +		if (nouveau_bo_tmp_max(nvdev) < size) { +			nouveau_fence_ref(NULL, &ref); +			return NULL; +		} + +		nouveau_fence_flush(chan); +	} +	nouveau_fence_signal_cb(ref, nouveau_bo_tmp_del, r); + +	return r; +} + +int +nouveau_bo_init(struct nouveau_device *dev) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(dev); +	int ret; + +	ret = nouveau_mem_alloc(dev, 128*1024, 0, NOUVEAU_MEM_AGP | +				NOUVEAU_MEM_PCI, &nvdev->sa, &nvdev->sa_map); +	if (ret) +		return ret; + +	ret = nouveau_resource_init(&nvdev->sa_heap, 0, nvdev->sa.size); +	if (ret) { +		nouveau_mem_free(dev, &nvdev->sa, &nvdev->sa_map); +		return ret; +	} + +	return 0; +} + +void +nouveau_bo_takedown(struct nouveau_device *dev) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(dev); + +	nouveau_mem_free(dev, &nvdev->sa, &nvdev->sa_map); +} + +int +nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align, +	       int size, struct nouveau_bo **bo) +{ +	struct nouveau_bo_priv *nvbo; +	int ret; + +	if (!dev || !bo || *bo) +		return -EINVAL; + +	nvbo = calloc(1, sizeof(struct nouveau_bo_priv)); +	if (!nvbo) +		return -ENOMEM; +	nvbo->base.device = dev; +	nvbo->base.size = size; +	nvbo->base.handle = bo_to_ptr(nvbo); +	nvbo->drm.alignment = align; +	nvbo->refcount = 1; + +	if (flags & NOUVEAU_BO_TILED) { +		nvbo->tiled = 1; +		if (flags & NOUVEAU_BO_ZTILE) +			nvbo->tiled |= 2; +		flags &= ~NOUVEAU_BO_TILED; +	} + +	ret = nouveau_bo_set_status(&nvbo->base, flags); +	if (ret) { +		free(nvbo); +		return ret; +	} + +	*bo = &nvbo->base; +	return 0; +} + +int +nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size, +		struct nouveau_bo **bo) +{ +	struct nouveau_bo_priv *nvbo; + +	if (!dev || !bo || *bo) +		return -EINVAL; + +	nvbo = calloc(1, sizeof(*nvbo)); +	if (!nvbo) +		return -ENOMEM; +	nvbo->base.device = dev; +	 +	nvbo->sysmem = ptr; +	nvbo->user = 1; + +	nvbo->base.size = size; +	nvbo->base.offset = nvbo->drm.offset; +	nvbo->base.handle = bo_to_ptr(nvbo); +	nvbo->refcount = 1; +	*bo = &nvbo->base; +	return 0; +} + +int +nouveau_bo_ref(struct nouveau_device *dev, uint64_t handle, +	       struct nouveau_bo **bo) +{ +	struct nouveau_bo_priv *nvbo = ptr_to_bo(handle); + +	if (!dev || !bo || *bo) +		return -EINVAL; + +	nvbo->refcount++; +	*bo = &nvbo->base; +	return 0; +} + +static void +nouveau_bo_del_cb(void *priv) +{ +	struct nouveau_bo_priv *nvbo = priv; + +	nouveau_fence_ref(NULL, &nvbo->fence); +	nouveau_mem_free(nvbo->base.device, &nvbo->drm, &nvbo->map); +	if (nvbo->sysmem && !nvbo->user) +		free(nvbo->sysmem); +	free(nvbo); +} + +void +nouveau_bo_del(struct nouveau_bo **bo) +{ +	struct nouveau_bo_priv *nvbo; + +	if (!bo || !*bo) +		return; +	nvbo = nouveau_bo(*bo); +	*bo = NULL; + +	if (--nvbo->refcount) +		return; + +	if (nvbo->pending) +		nouveau_pushbuf_flush(nvbo->pending->channel, 0); + +	if (nvbo->fence) +		nouveau_fence_signal_cb(nvbo->fence, nouveau_bo_del_cb, nvbo); +	else +		nouveau_bo_del_cb(nvbo); +} + +int +nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags) +{ +	struct nouveau_bo_priv *nvbo = nouveau_bo(bo); + +	if (!nvbo) +		return -EINVAL; + +	if (nvbo->pending && +	    (nvbo->pending->flags & NOUVEAU_BO_WR || flags & NOUVEAU_BO_WR)) { +		nouveau_pushbuf_flush(nvbo->pending->channel, 0); +	} + +	if (flags & NOUVEAU_BO_WR) +		nouveau_fence_wait(&nvbo->fence); +	else +		nouveau_fence_wait(&nvbo->wr_fence); + +	if (nvbo->sysmem) +		bo->map = nvbo->sysmem; +	else +		bo->map = nvbo->map; +	return 0; +} + +void +nouveau_bo_unmap(struct nouveau_bo *bo) +{ +	bo->map = NULL; +} + +static int +nouveau_bo_upload(struct nouveau_bo_priv *nvbo) +{ +	if (nvbo->fence) +		nouveau_fence_wait(&nvbo->fence); +	memcpy(nvbo->map, nvbo->sysmem, nvbo->drm.size); +	return 0; +} + +int +nouveau_bo_set_status(struct nouveau_bo *bo, uint32_t flags) +{ +	struct nouveau_bo_priv *nvbo = nouveau_bo(bo); +	struct drm_nouveau_mem_alloc new; +	void *new_map = NULL, *new_sysmem = NULL; +	unsigned new_flags = 0, ret; + +	assert(!bo->map); + +	/* Check current memtype vs requested, if they match do nothing */ +	if ((nvbo->drm.flags & NOUVEAU_MEM_FB) && (flags & NOUVEAU_BO_VRAM)) +		return 0; +	if ((nvbo->drm.flags & (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI)) && +	    (flags & NOUVEAU_BO_GART)) +		return 0; +	if (nvbo->drm.size == 0 && nvbo->sysmem && (flags & NOUVEAU_BO_LOCAL)) +		return 0; + +	memset(&new, 0x00, sizeof(new)); + +	/* Allocate new memory */ +	if (flags & NOUVEAU_BO_VRAM) +		new_flags |= NOUVEAU_MEM_FB; +	else +	if (flags & NOUVEAU_BO_GART) +		new_flags |= (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI); +	 +	if (nvbo->tiled && flags) { +		new_flags |= NOUVEAU_MEM_TILE; +		if (nvbo->tiled & 2) +			new_flags |= NOUVEAU_MEM_TILE_ZETA; +	} + +	if (new_flags) { +		ret = nouveau_mem_alloc(bo->device, bo->size, +					nvbo->drm.alignment, new_flags, +					&new, &new_map); +		if (ret) +			return ret; +	} else +	if (!nvbo->user) { +		new_sysmem = malloc(bo->size); +	} + +	/* Copy old -> new */ +	/*XXX: use M2MF */ +	if (nvbo->sysmem || nvbo->map) { +		struct nouveau_pushbuf_bo *pbo = nvbo->pending; +		nvbo->pending = NULL; +		nouveau_bo_map(bo, NOUVEAU_BO_RD); +		memcpy(new_map, bo->map, bo->size); +		nouveau_bo_unmap(bo); +		nvbo->pending = pbo; +	} + +	/* Free old memory */ +	if (nvbo->fence) +		nouveau_fence_wait(&nvbo->fence); +	nouveau_mem_free(bo->device, &nvbo->drm, &nvbo->map); +	if (nvbo->sysmem && !nvbo->user) +		free(nvbo->sysmem); + +	nvbo->drm = new; +	nvbo->map = new_map; +	if (!nvbo->user) +		nvbo->sysmem = new_sysmem; +	bo->flags = flags; +	bo->offset = nvbo->drm.offset; +	return 0; +} + +static int +nouveau_bo_validate_user(struct nouveau_channel *chan, struct nouveau_bo *bo, +			 struct nouveau_fence *fence, uint32_t flags) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_device_priv *nvdev = nouveau_device(chan->device); +	struct nouveau_bo_priv *nvbo = nouveau_bo(bo); +	struct nouveau_resource *r; + +	if (nvchan->user_charge + bo->size > nvdev->sa.size) +		return 1; + +	if (!(flags & NOUVEAU_BO_GART)) +		return 1; + +	r = nouveau_bo_tmp(chan, bo->size, fence); +	if (!r) +		return 1; +	nvchan->user_charge += bo->size; + +	memcpy(nvdev->sa_map + r->start, nvbo->sysmem, bo->size); + +	nvbo->offset = nvdev->sa.offset + r->start; +	nvbo->flags = NOUVEAU_BO_GART; +	return 0; +} + +static int +nouveau_bo_validate_bo(struct nouveau_channel *chan, struct nouveau_bo *bo, +		       struct nouveau_fence *fence, uint32_t flags) +{ +	struct nouveau_bo_priv *nvbo = nouveau_bo(bo); +	int ret; + +	ret = nouveau_bo_set_status(bo, flags); +	if (ret) { +		nouveau_fence_flush(chan); + +		ret = nouveau_bo_set_status(bo, flags); +		if (ret) +			return ret; +	} + +	if (nvbo->user) +		nouveau_bo_upload(nvbo); + +	nvbo->offset = nvbo->drm.offset; +	if (nvbo->drm.flags & (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI)) +		nvbo->flags = NOUVEAU_BO_GART; +	else +		nvbo->flags = NOUVEAU_BO_VRAM; + +	return 0; +} + +int +nouveau_bo_validate(struct nouveau_channel *chan, struct nouveau_bo *bo, +		    uint32_t flags) +{ +	struct nouveau_bo_priv *nvbo = nouveau_bo(bo); +	struct nouveau_fence *fence = nouveau_pushbuf(chan->pushbuf)->fence; +	int ret; + +	assert(bo->map == NULL); + +	if (nvbo->user) { +		ret = nouveau_bo_validate_user(chan, bo, fence, flags); +		if (ret) { +			ret = nouveau_bo_validate_bo(chan, bo, fence, flags); +			if (ret) +				return ret; +		} +	} else { +		ret = nouveau_bo_validate_bo(chan, bo, fence, flags); +		if (ret) +			return ret; +	} + +	if (flags & NOUVEAU_BO_WR) +		nouveau_fence_ref(fence, &nvbo->wr_fence); +	nouveau_fence_ref(fence, &nvbo->fence); +	return 0; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_channel.c b/src/gallium/winsys/dri/nouveau/nouveau_channel.c new file mode 100644 index 0000000000..3b4dcd1ecf --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_channel.c @@ -0,0 +1,126 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "nouveau_drmif.h" +#include "nouveau_dma.h" + +int +nouveau_channel_alloc(struct nouveau_device *dev, uint32_t fb_ctxdma, +		      uint32_t tt_ctxdma, struct nouveau_channel **chan) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(dev); +	struct nouveau_channel_priv *nvchan; +	int ret; + +	if (!nvdev || !chan || *chan) +	    return -EINVAL; + +	nvchan = calloc(1, sizeof(struct nouveau_channel_priv)); +	if (!nvchan) +		return -ENOMEM; +	nvchan->base.device = dev; + +	nvchan->drm.fb_ctxdma_handle = fb_ctxdma; +	nvchan->drm.tt_ctxdma_handle = tt_ctxdma; +	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_CHANNEL_ALLOC, +				  &nvchan->drm, sizeof(nvchan->drm)); +	if (ret) { +		free(nvchan); +		return ret; +	} + +	nvchan->base.id = nvchan->drm.channel; +	if (nouveau_grobj_ref(&nvchan->base, nvchan->drm.fb_ctxdma_handle, +			      &nvchan->base.vram) || +	    nouveau_grobj_ref(&nvchan->base, nvchan->drm.tt_ctxdma_handle, +		    	      &nvchan->base.gart)) { +		nouveau_channel_free((void *)&nvchan); +		return -EINVAL; +	} + +	ret = drmMap(nvdev->fd, nvchan->drm.ctrl, nvchan->drm.ctrl_size, +		     (void*)&nvchan->user); +	if (ret) { +		nouveau_channel_free((void *)&nvchan); +		return ret; +	} +	nvchan->put     = &nvchan->user[0x40/4]; +	nvchan->get     = &nvchan->user[0x44/4]; +	nvchan->ref_cnt = &nvchan->user[0x48/4]; + +	ret = drmMap(nvdev->fd, nvchan->drm.notifier, nvchan->drm.notifier_size, +		     (drmAddressPtr)&nvchan->notifier_block); +	if (ret) { +		nouveau_channel_free((void *)&nvchan); +		return ret; +	} + +	ret = drmMap(nvdev->fd, nvchan->drm.cmdbuf, nvchan->drm.cmdbuf_size, +		     (void*)&nvchan->pushbuf); +	if (ret) { +		nouveau_channel_free((void *)&nvchan); +		return ret; +	} + +	ret = nouveau_grobj_alloc(&nvchan->base, 0x00000000, 0x0030, +				  &nvchan->base.nullobj); +	if (ret) { +		nouveau_channel_free((void *)&nvchan); +		return ret; +	} + +	nouveau_dma_channel_init(&nvchan->base); +	nouveau_pushbuf_init(&nvchan->base); + +	*chan = &nvchan->base; +	return 0; +} + +void +nouveau_channel_free(struct nouveau_channel **chan) +{ +	struct nouveau_channel_priv *nvchan; +	struct nouveau_device_priv *nvdev; +	struct drm_nouveau_channel_free cf; + +	if (!chan || !*chan) +		return; +	nvchan = nouveau_channel(*chan); +	*chan = NULL; +	nvdev = nouveau_device(nvchan->base.device); +	 +	FIRE_RING_CH(&nvchan->base); + +	nouveau_grobj_free(&nvchan->base.vram); +	nouveau_grobj_free(&nvchan->base.gart); +	nouveau_grobj_free(&nvchan->base.nullobj); + +	cf.channel = nvchan->drm.channel; +	drmCommandWrite(nvdev->fd, DRM_NOUVEAU_CHANNEL_FREE, &cf, sizeof(cf)); +	free(nvchan); +} + + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.c b/src/gallium/winsys/dri/nouveau/nouveau_context.c new file mode 100644 index 0000000000..74413c408f --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_context.c @@ -0,0 +1,346 @@ +#include "main/glheader.h" +#include "glapi/glthread.h" +#include <GL/internal/glcore.h> +#include "utils.h" + +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_context.h" +#include "pipe/p_screen.h" + +#include "nouveau_context.h" +#include "nouveau_dri.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_winsys_pipe.h" + +#ifdef DEBUG +static const struct dri_debug_control debug_control[] = { +	{ "bo", DEBUG_BO }, +	{ NULL, 0 } +}; +int __nouveau_debug = 0; +#endif + +static void +nouveau_channel_context_destroy(struct nouveau_channel_context *nvc) +{ +	nouveau_grobj_free(&nvc->NvCtxSurf2D); +	nouveau_grobj_free(&nvc->NvImageBlit); +	nouveau_grobj_free(&nvc->NvGdiRect); +	nouveau_grobj_free(&nvc->NvM2MF); +	nouveau_grobj_free(&nvc->Nv2D); +	nouveau_grobj_free(&nvc->NvSwzSurf); +	nouveau_grobj_free(&nvc->NvSIFM); + +	nouveau_notifier_free(&nvc->sync_notifier); + +	nouveau_channel_free(&nvc->channel); + +	FREE(nvc); +} + +static struct nouveau_channel_context * +nouveau_channel_context_create(struct nouveau_device *dev) +{ +	struct nouveau_channel_context *nvc; +	int ret; + +	nvc = CALLOC_STRUCT(nouveau_channel_context); +	if (!nvc) +		return NULL; + +	if ((ret = nouveau_channel_alloc(dev, 0x8003d001, 0x8003d002, +					 &nvc->channel))) { +		NOUVEAU_ERR("Error creating GPU channel: %d\n", ret); +		nouveau_channel_context_destroy(nvc); +		return NULL; +	} + +	nvc->next_handle = 0x80000000; + +	if ((ret = nouveau_notifier_alloc(nvc->channel, nvc->next_handle++, 1, +					  &nvc->sync_notifier))) { +		NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret); +		nouveau_channel_context_destroy(nvc); +		return NULL; +	} + +	switch (dev->chipset & 0xf0) { +	case 0x50: +	case 0x80: +	case 0x90: +		ret = nouveau_surface_channel_create_nv50(nvc); +		break; +	default: +		ret = nouveau_surface_channel_create_nv04(nvc); +		break; +	} + +	if (ret) { +		NOUVEAU_ERR("Error initialising surface objects: %d\n", ret); +		nouveau_channel_context_destroy(nvc); +		return NULL; +	} + +	return nvc; +} + +GLboolean +nouveau_context_create(const __GLcontextModes *glVis, +		       __DRIcontextPrivate *driContextPriv, +		       void *sharedContextPrivate) +{ +	__DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv; +	struct nouveau_screen  *nv_screen = driScrnPriv->private; +	struct nouveau_context *nv = CALLOC_STRUCT(nouveau_context); +	struct pipe_context *pipe = NULL; +	struct st_context *st_share = NULL; +	struct nouveau_channel_context *nvc = NULL; +	struct nouveau_device *dev = nv_screen->device; +	int i; + +	if (sharedContextPrivate) { +		st_share = ((struct nouveau_context *)sharedContextPrivate)->st; +	} + +	switch (dev->chipset & 0xf0) { +	case 0x10: +	case 0x20: +		/* NV10 */ +	case 0x30: +		/* NV30 */ +	case 0x40: +	case 0x60: +		/* NV40 */ +	case 0x50: +	case 0x80: +	case 0x90: +		/* G80 */ +		break; +	default: +		NOUVEAU_ERR("Unsupported chipset: NV%02x\n", dev->chipset); +		return GL_FALSE; +	} + +	driContextPriv->driverPrivate = (void *)nv; +	nv->nv_screen  = nv_screen; +	nv->dri_screen = driScrnPriv; + +	{ +		struct nouveau_device_priv *nvdev = nouveau_device(dev); + +		nvdev->ctx  = driContextPriv->hHWContext; +		nvdev->lock = (drmLock *)&driScrnPriv->pSAREA->lock; +	} + +	driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache, +			    nv->dri_screen->myNum, "nouveau"); +#ifdef DEBUG +	__nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"), +					      debug_control); +#endif + +	/*XXX: Hack up a fake region and buffer object for front buffer. +	 *     This will go away with TTM, replaced with a simple reference +	 *     of the front buffer handle passed to us by the DDX. +	 */ +	{ +		struct pipe_surface *fb_surf; +		struct nouveau_pipe_buffer *fb_buf; +		struct nouveau_bo_priv *fb_bo; + +		fb_bo = calloc(1, sizeof(struct nouveau_bo_priv)); +		fb_bo->drm.offset = nv_screen->front_offset; +		fb_bo->drm.flags = NOUVEAU_MEM_FB; +		fb_bo->drm.size = nv_screen->front_pitch *  +				  nv_screen->front_height; +		fb_bo->refcount = 1; +		fb_bo->base.flags = NOUVEAU_BO_PIN | NOUVEAU_BO_VRAM; +		fb_bo->base.offset = fb_bo->drm.offset; +		fb_bo->base.handle = (unsigned long)fb_bo; +		fb_bo->base.size = fb_bo->drm.size; +		fb_bo->base.device = nv_screen->device; + +		fb_buf = calloc(1, sizeof(struct nouveau_pipe_buffer)); +		fb_buf->bo = &fb_bo->base; + +		fb_surf = calloc(1, sizeof(struct pipe_surface)); +		if (nv_screen->front_cpp == 2) +			fb_surf->format = PIPE_FORMAT_R5G6B5_UNORM; +		else +			fb_surf->format = PIPE_FORMAT_A8R8G8B8_UNORM; +		pf_get_block(fb_surf->format, &fb_surf->block); +		fb_surf->width = nv_screen->front_pitch / nv_screen->front_cpp; +		fb_surf->height = nv_screen->front_height; +		fb_surf->stride = fb_surf->width * fb_surf->block.size; +		fb_surf->refcount = 1; +		fb_surf->buffer = &fb_buf->base; + +		nv->frontbuffer = fb_surf; +	} + +	/* Attempt to share a single channel between multiple contexts from +	 * a single process. +	 */ +	nvc = nv_screen->nvc; +	if (!nvc && st_share) { +		struct nouveau_context *snv = st_share->pipe->priv; +		if (snv) { +			nvc = snv->nvc; +		} +	} + +	/*XXX: temporary - disable multi-context/single-channel on pre-NV4x */ +	switch (dev->chipset & 0xf0) { +	case 0x40: +	case 0x60: +		/* NV40 class */ +	case 0x50: +	case 0x80: +	case 0x90: +		/* G80 class */ +		break; +	default: +		nvc = NULL; +		break; +	} + +	if (!nvc) { +		nvc = nouveau_channel_context_create(dev); +		if (!nvc) { +			NOUVEAU_ERR("Failed initialising GPU context\n"); +			return GL_FALSE; +		} +		nv_screen->nvc = nvc; +	} + +	nvc->refcount++; +	nv->nvc = nvc; + +	/* Find a free slot for a pipe context, allocate a new one if needed */ +	nv->pctx_id = -1; +	for (i = 0; i < nvc->nr_pctx; i++) { +		if (nvc->pctx[i] == NULL) { +			nv->pctx_id = i; +			break; +		} +	} + +	if (nv->pctx_id < 0) { +		nv->pctx_id = nvc->nr_pctx++; +		nvc->pctx = +			realloc(nvc->pctx, +				sizeof(struct pipe_context *) * nvc->nr_pctx); +	} + +	/* Create pipe */ +	switch (dev->chipset & 0xf0) { +	case 0x50: +	case 0x80: +	case 0x90: +		if (nouveau_surface_init_nv50(nv)) +			return GL_FALSE; +		break; +	default: +		if (nouveau_surface_init_nv04(nv)) +			return GL_FALSE; +		break; +	} + +	if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) { +		struct pipe_screen *pscreen; + +		pipe = nouveau_pipe_create(nv); +		if (!pipe) +			NOUVEAU_ERR("Couldn't create hw pipe\n"); +		pscreen = nvc->pscreen; + +		nv->cap.hw_vertex_buffer = +			pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF); +		nv->cap.hw_index_buffer = +			pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF); +	} + +	if (!pipe) { +		NOUVEAU_MSG("Using softpipe\n"); +		pipe = nouveau_create_softpipe(nv); +		if (!pipe) { +			NOUVEAU_ERR("Error creating pipe, bailing\n"); +			return GL_FALSE; +		} +	} + +	pipe->priv = nv; +	nv->st = st_create_context(pipe, glVis, st_share); +	return GL_TRUE; +} + +void +nouveau_context_destroy(__DRIcontextPrivate *driContextPriv) +{ +	struct nouveau_context *nv = driContextPriv->driverPrivate; +	struct nouveau_channel_context *nvc = nv->nvc; + +	assert(nv); + +	st_finish(nv->st); +	st_destroy_context(nv->st); + +	if (nv->pctx_id >= 0) { +		nvc->pctx[nv->pctx_id] = NULL; +		if (--nvc->refcount <= 0) { +			nouveau_channel_context_destroy(nvc); +			nv->nv_screen->nvc = NULL; +		} +	} + +	free(nv); +} + +GLboolean +nouveau_context_bind(__DRIcontextPrivate *driContextPriv, +		     __DRIdrawablePrivate *driDrawPriv, +		     __DRIdrawablePrivate *driReadPriv) +{ +	struct nouveau_context *nv; +	struct nouveau_framebuffer *draw, *read; + +	if (!driContextPriv) { +		st_make_current(NULL, NULL, NULL); +		return GL_TRUE; +	} + +	nv = driContextPriv->driverPrivate; +	draw = driDrawPriv->driverPrivate; +	read = driReadPriv->driverPrivate; + +	st_make_current(nv->st, draw->stfb, read->stfb); + +	if ((nv->dri_drawable != driDrawPriv) || +	    (nv->last_stamp != driDrawPriv->lastStamp)) { +		nv->dri_drawable = driDrawPriv; +		st_resize_framebuffer(draw->stfb, driDrawPriv->w, +				      driDrawPriv->h); +		nv->last_stamp = driDrawPriv->lastStamp; +	} + +	if (driDrawPriv != driReadPriv) { +		st_resize_framebuffer(read->stfb, driReadPriv->w, +				      driReadPriv->h); +	} + +	return GL_TRUE; +} + +GLboolean +nouveau_context_unbind(__DRIcontextPrivate *driContextPriv) +{ +	struct nouveau_context *nv = driContextPriv->driverPrivate; +	(void)nv; + +	st_flush(nv->st, 0, NULL); +	return GL_TRUE; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.h b/src/gallium/winsys/dri/nouveau/nouveau_context.h new file mode 100644 index 0000000000..77e2147a2c --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_context.h @@ -0,0 +1,113 @@ +#ifndef __NOUVEAU_CONTEXT_H__ +#define __NOUVEAU_CONTEXT_H__ + +#include "dri_util.h" +#include "xmlconfig.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau_drmif.h" +#include "nouveau_dma.h" + +struct nouveau_framebuffer { +	struct st_framebuffer *stfb; +}; + +struct nouveau_channel_context { +	struct pipe_screen *pscreen; +	int refcount; + +	unsigned cur_pctx; +	unsigned nr_pctx; +	struct pipe_context **pctx; + +	struct nouveau_channel  *channel; + +	struct nouveau_notifier *sync_notifier; + +	/* Common */ +	struct nouveau_grobj    *NvM2MF; +	/* NV04-NV40 */ +	struct nouveau_grobj    *NvCtxSurf2D; +	struct nouveau_grobj	*NvSwzSurf; +	struct nouveau_grobj    *NvImageBlit; +	struct nouveau_grobj    *NvGdiRect; +	struct nouveau_grobj	*NvSIFM; +	/* G80 */ +	struct nouveau_grobj    *Nv2D; + +	uint32_t                 next_handle; +	uint32_t                 next_subchannel; +	uint32_t                 next_sequence; +}; + +struct nouveau_context { +	struct st_context *st; + +	/* DRI stuff */ +	__DRIscreenPrivate    *dri_screen; +	__DRIdrawablePrivate  *dri_drawable; +	unsigned int           last_stamp; +	driOptionCache         dri_option_cache; +	drm_context_t          drm_context; +	drmLock                drm_lock; +	GLboolean              locked; +	struct nouveau_screen *nv_screen; +	struct pipe_surface *frontbuffer; + +	struct { +		int hw_vertex_buffer; +		int hw_index_buffer; +	} cap; + +	/* Hardware context */ +	struct nouveau_channel_context *nvc; +	int pctx_id; + +	/* pipe_surface accel */ +	struct pipe_surface *surf_src, *surf_dst; +	unsigned surf_src_offset, surf_dst_offset; +	int  (*surface_copy_prep)(struct nouveau_context *, +				  struct pipe_surface *dst, +				  struct pipe_surface *src); +	void (*surface_copy)(struct nouveau_context *, unsigned dx, unsigned dy, +			     unsigned sx, unsigned sy, unsigned w, unsigned h); +	void (*surface_copy_done)(struct nouveau_context *); +	int (*surface_fill)(struct nouveau_context *, struct pipe_surface *, +			    unsigned, unsigned, unsigned, unsigned, unsigned); +}; + +extern GLboolean nouveau_context_create(const __GLcontextModes *, +					__DRIcontextPrivate *, void *); +extern void nouveau_context_destroy(__DRIcontextPrivate *); +extern GLboolean nouveau_context_bind(__DRIcontextPrivate *, +				      __DRIdrawablePrivate *draw, +				      __DRIdrawablePrivate *read); +extern GLboolean nouveau_context_unbind(__DRIcontextPrivate *); + +#ifdef DEBUG +extern int __nouveau_debug; + +#define DEBUG_BO (1 << 0) + +#define DBG(flag, ...) do {                   \ +	if (__nouveau_debug & (DEBUG_##flag)) \ +		NOUVEAU_ERR(__VA_ARGS__);     \ +} while(0) +#else +#define DBG(flag, ...) +#endif + +extern void LOCK_HARDWARE(struct nouveau_context *); +extern void UNLOCK_HARDWARE(struct nouveau_context *); + +extern int +nouveau_surface_channel_create_nv04(struct nouveau_channel_context *); +extern int +nouveau_surface_channel_create_nv50(struct nouveau_channel_context *); +extern int nouveau_surface_init_nv04(struct nouveau_context *); +extern int nouveau_surface_init_nv50(struct nouveau_context *); + +extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int); +extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *); + +#endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_device.c b/src/gallium/winsys/dri/nouveau/nouveau_device.c new file mode 100644 index 0000000000..0b452fcd02 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_device.c @@ -0,0 +1,159 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdlib.h> +#include <errno.h> + +#include "nouveau_drmif.h" + +int +nouveau_device_open_existing(struct nouveau_device **dev, int close, +			     int fd, drm_context_t ctx) +{ +	struct nouveau_device_priv *nvdev; +	int ret; + +	if (!dev || *dev) +	    return -EINVAL; + +	nvdev = calloc(1, sizeof(*nvdev)); +	if (!nvdev) +	    return -ENOMEM; +	nvdev->fd = fd; +	nvdev->ctx = ctx; +	nvdev->needs_close = close; + +	drmCommandNone(nvdev->fd, DRM_NOUVEAU_CARD_INIT); + +	if ((ret = nouveau_bo_init(&nvdev->base))) { +		nouveau_device_close((void *)&nvdev); +		return ret; +	} + +	{ +		uint64_t value; + +		ret = nouveau_device_get_param(&nvdev->base, +					       NOUVEAU_GETPARAM_CHIPSET_ID, +					       &value); +		if (ret) { +			nouveau_device_close((void *)&nvdev); +			return ret; +		} +		nvdev->base.chipset = value; +	} + +	*dev = &nvdev->base; +	return 0; +} + +int +nouveau_device_open(struct nouveau_device **dev, const char *busid) +{ +	drm_context_t ctx; +	int fd, ret; + +	if (!dev || *dev) +		return -EINVAL; + +	fd = drmOpen("nouveau", busid); +	if (fd < 0) +		return -EINVAL; + +	ret = drmCreateContext(fd, &ctx); +	if (ret) { +		drmClose(fd); +		return ret; +	} + +	ret = nouveau_device_open_existing(dev, 1, fd, ctx); +	if (ret) { +	    drmDestroyContext(fd, ctx); +	    drmClose(fd); +	    return ret; +	} + +	return 0; +} + +void +nouveau_device_close(struct nouveau_device **dev) +{ +	struct nouveau_device_priv *nvdev; + +	if (dev || !*dev) +		return; +	nvdev = nouveau_device(*dev); +	*dev = NULL; + +	nouveau_bo_takedown(&nvdev->base); + +	if (nvdev->needs_close) { +		drmDestroyContext(nvdev->fd, nvdev->ctx); +		drmClose(nvdev->fd); +	} +	free(nvdev); +} + +int +nouveau_device_get_param(struct nouveau_device *dev, +			 uint64_t param, uint64_t *value) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(dev); +	struct drm_nouveau_getparam g; +	int ret; + +	if (!nvdev || !value) +		return -EINVAL; + +	g.param = param; +	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM, +				  &g, sizeof(g)); +	if (ret) +		return ret; + +	*value = g.value; +	return 0; +} + +int +nouveau_device_set_param(struct nouveau_device *dev, +			 uint64_t param, uint64_t value) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(dev); +	struct drm_nouveau_setparam s; +	int ret; + +	if (!nvdev) +		return -EINVAL; + +	s.param = param; +	s.value = value; +	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM, +				  &s, sizeof(s)); +	if (ret) +		return ret; + +	return 0; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_dma.c b/src/gallium/winsys/dri/nouveau/nouveau_dma.c new file mode 100644 index 0000000000..f8a8ba04f6 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_dma.c @@ -0,0 +1,219 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdint.h> +#include <assert.h> +#include <errno.h> + +#include "nouveau_drmif.h" +#include "nouveau_dma.h" +#include "nouveau_local.h" + +static inline uint32_t +READ_GET(struct nouveau_channel_priv *nvchan) +{ +	return *nvchan->get; +} + +static inline void +WRITE_PUT(struct nouveau_channel_priv *nvchan, uint32_t val) +{ +	uint32_t put = ((val << 2) + nvchan->dma->base); +	volatile int dum; + +	NOUVEAU_DMA_BARRIER; +	dum = READ_GET(nvchan); + +	*nvchan->put = put; +	nvchan->dma->put = val; +#ifdef NOUVEAU_DMA_TRACE +	NOUVEAU_MSG("WRITE_PUT %d/0x%08x\n", nvchan->drm.channel, put); +#endif + +	NOUVEAU_DMA_BARRIER; +} + +static inline int +LOCAL_GET(struct nouveau_dma_priv *dma, uint32_t *val) +{ +	uint32_t get = *val; + +	if (get >= dma->base && get <= (dma->base + (dma->max << 2))) { +		*val = (get - dma->base) >> 2; +		return 1; +	} + +	return 0; +} + +void +nouveau_dma_channel_init(struct nouveau_channel *chan) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	int i; + +	nvchan->dma = &nvchan->dma_master; +	nvchan->dma->base = nvchan->drm.put_base; +	nvchan->dma->cur  = nvchan->dma->put = 0; +	nvchan->dma->max  = (nvchan->drm.cmdbuf_size >> 2) - 2; +	nvchan->dma->free = nvchan->dma->max - nvchan->dma->cur; + +	RING_SPACE_CH(chan, RING_SKIPS); +	for (i = 0; i < RING_SKIPS; i++) +		OUT_RING_CH(chan, 0); +} + +#define CHECK_TIMEOUT() do {                                                   \ +	if ((NOUVEAU_TIME_MSEC() - t_start) > NOUVEAU_DMA_TIMEOUT)             \ +		return - EBUSY;                                                \ +} while(0) + +int +nouveau_dma_wait(struct nouveau_channel *chan, int size) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_dma_priv *dma = nvchan->dma; +	uint32_t get, t_start; + +	FIRE_RING_CH(chan); + +	t_start = NOUVEAU_TIME_MSEC(); +	while (dma->free < size) { +		CHECK_TIMEOUT(); + +		get = READ_GET(nvchan); +		if (!LOCAL_GET(dma, &get)) +			continue; + +		if (dma->put >= get) { +			dma->free = dma->max - dma->cur; + +			if (dma->free < size) { +#ifdef NOUVEAU_DMA_DEBUG +				dma->push_free = 1; +#endif +				OUT_RING_CH(chan, 0x20000000 | dma->base); +				if (get <= RING_SKIPS) { +					/*corner case - will be idle*/ +					if (dma->put <= RING_SKIPS) +						WRITE_PUT(nvchan, +							  RING_SKIPS + 1); + +					do { +						CHECK_TIMEOUT(); +						get = READ_GET(nvchan); +						if (!LOCAL_GET(dma, &get)) +							get = 0; +					} while (get <= RING_SKIPS); +				} + +				WRITE_PUT(nvchan, RING_SKIPS); +				dma->cur  = dma->put = RING_SKIPS; +				dma->free = get - (RING_SKIPS + 1); +			} +		} else { +			dma->free = get - dma->cur - 1; +		} +	} + +	return 0; +} + +#ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF +static void +nouveau_dma_parse_pushbuf(struct nouveau_channel *chan, int get, int put) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	unsigned mthd_count = 0; +	 +	while (get != put) { +		uint32_t gpuget = (get << 2) + nvchan->drm.put_base; +		uint32_t data; + +		if (get < 0 || get >= nvchan->drm.cmdbuf_size) { +			NOUVEAU_ERR("DMA_PT 0x%08x\n", gpuget); +			assert(0); +		} +		data = nvchan->pushbuf[get++]; + +		if (mthd_count) { +			NOUVEAU_MSG("0x%08x 0x%08x\n", gpuget, data); +			mthd_count--; +			continue; +		} + +		switch (data & 0x60000000) { +		case 0x00000000: +			mthd_count = (data >> 18) & 0x7ff; +			NOUVEAU_MSG("0x%08x 0x%08x MTHD " +				    "Sc %d Mthd 0x%04x Size %d\n", +				    gpuget, data, (data>>13) & 7, data & 0x1ffc, +				    mthd_count); +			break; +		case 0x20000000: +			get = (data & 0x1ffffffc) >> 2; +			NOUVEAU_MSG("0x%08x 0x%08x JUMP 0x%08x\n", +				    gpuget, data, data & 0x1ffffffc); +			continue; +		case 0x40000000: +			mthd_count = (data >> 18) & 0x7ff; +			NOUVEAU_MSG("0x%08x 0x%08x NINC " +				    "Sc %d Mthd 0x%04x Size %d\n", +				    gpuget, data, (data>>13) & 7, data & 0x1ffc, +				    mthd_count); +			break; +		case 0x60000000: +			/* DMA_OPCODE_CALL apparently, doesn't seem to work on +			 * my NV40 at least.. +			 */ +			/* fall-through */ +		default: +			NOUVEAU_MSG("DMA_PUSHER 0x%08x 0x%08x\n", +				    gpuget, data); +			assert(0); +		} +	} +} +#endif + +void +nouveau_dma_kickoff(struct nouveau_channel *chan) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_dma_priv *dma = nvchan->dma; + +	if (dma->cur == dma->put) +		return; + +#ifdef NOUVEAU_DMA_DEBUG +	if (dma->push_free) { +		NOUVEAU_ERR("Packet incomplete: %d left\n", dma->push_free); +		return; +	} +#endif + +#ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF +	nouveau_dma_parse_pushbuf(chan, dma->put, dma->cur); +#endif + +	WRITE_PUT(nvchan, dma->cur); +} diff --git a/src/gallium/winsys/dri/nouveau/nouveau_dma.h b/src/gallium/winsys/dri/nouveau/nouveau_dma.h new file mode 100644 index 0000000000..cfa6d26e82 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_dma.h @@ -0,0 +1,143 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_DMA_H__ +#define __NOUVEAU_DMA_H__ + +#include <string.h> +#include "nouveau_drmif.h" +#include "nouveau_local.h" + +#define RING_SKIPS 8 + +extern int  nouveau_dma_wait(struct nouveau_channel *chan, int size); +extern void nouveau_dma_subc_bind(struct nouveau_grobj *); +extern void nouveau_dma_channel_init(struct nouveau_channel *); +extern void nouveau_dma_kickoff(struct nouveau_channel *); + +#ifdef NOUVEAU_DMA_DEBUG +static char faulty[1024]; +#endif + +static inline void +nouveau_dma_out(struct nouveau_channel *chan, uint32_t data) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_dma_priv *dma = nvchan->dma; + +#ifdef NOUVEAU_DMA_DEBUG +	if (dma->push_free == 0) { +		NOUVEAU_ERR("No space left in packet at %s\n", faulty); +		return; +	} +	dma->push_free--; +#endif +#ifdef NOUVEAU_DMA_TRACE +	{ +		uint32_t offset = (dma->cur << 2) + dma->base; +		NOUVEAU_MSG("\tOUT_RING %d/0x%08x -> 0x%08x\n", +			    nvchan->drm.channel, offset, data); +	} +#endif +	nvchan->pushbuf[dma->cur + (dma->base - nvchan->drm.put_base)/4] = data; +	dma->cur++; +} + +static inline void +nouveau_dma_outp(struct nouveau_channel *chan, uint32_t *ptr, int size) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_dma_priv *dma = nvchan->dma; +	(void)dma; + +#ifdef NOUVEAU_DMA_DEBUG +	if (dma->push_free < size) { +		NOUVEAU_ERR("Packet too small.  Free=%d, Need=%d\n", +			    dma->push_free, size); +		return; +	} +#endif +#ifdef NOUVEAU_DMA_TRACE +	while (size--) { +		nouveau_dma_out(chan, *ptr); +		ptr++; +	} +#else +	memcpy(&nvchan->pushbuf[dma->cur], ptr, size << 2); +#ifdef NOUVEAU_DMA_DEBUG +	dma->push_free -= size; +#endif +	dma->cur += size; +#endif +} + +static inline void +nouveau_dma_space(struct nouveau_channel *chan, int size) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_dma_priv *dma = nvchan->dma; + +	if (dma->free < size) { +		if (nouveau_dma_wait(chan, size) && chan->hang_notify) +			chan->hang_notify(chan); +	} +	dma->free -= size; +#ifdef NOUVEAU_DMA_DEBUG +	dma->push_free = size; +#endif +} + +static inline void +nouveau_dma_begin(struct nouveau_channel *chan, struct nouveau_grobj *grobj, +		  int method, int size, const char* file, int line) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_dma_priv *dma = nvchan->dma; +	(void)dma; + +#ifdef NOUVEAU_DMA_TRACE +	NOUVEAU_MSG("BEGIN_RING %d/%08x/%d/0x%04x/%d\n", nvchan->drm.channel, +		    grobj->handle, grobj->subc, method, size); +#endif + +#ifdef NOUVEAU_DMA_DEBUG +	if (dma->push_free) { +		NOUVEAU_ERR("Previous packet incomplete: %d left at %s\n", +			    dma->push_free, faulty); +		return; +	} +	sprintf(faulty,"%s:%d",file,line); +#endif + +	nouveau_dma_space(chan, (size + 1)); +	nouveau_dma_out(chan, (size << 18) | (grobj->subc << 13) | method); +} + +#define RING_SPACE_CH(ch,sz)         nouveau_dma_space((ch), (sz)) +#define BEGIN_RING_CH(ch,gr,m,sz)    nouveau_dma_begin((ch), (gr), (m), (sz), __FUNCTION__, __LINE__ ) +#define OUT_RING_CH(ch, data)        nouveau_dma_out((ch), (data)) +#define OUT_RINGp_CH(ch,ptr,dwords)  nouveau_dma_outp((ch), (void*)(ptr),      \ +						      (dwords)) +#define FIRE_RING_CH(ch)             nouveau_dma_kickoff((ch)) +#define WAIT_RING_CH(ch,sz)          nouveau_dma_wait((ch), (sz)) +		 +#endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_dri.h b/src/gallium/winsys/dri/nouveau/nouveau_dri.h new file mode 100644 index 0000000000..1207c2d609 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_dri.h @@ -0,0 +1,28 @@ +#ifndef _NOUVEAU_DRI_ +#define _NOUVEAU_DRI_ + +#include "xf86drm.h" +#include "drm.h" +#include "nouveau_drm.h" + +struct nouveau_dri { +	uint32_t device_id;	/**< \brief PCI device ID */ +	uint32_t width;		/**< \brief width in pixels of display */ +	uint32_t height;	/**< \brief height in scanlines of display */ +	uint32_t depth;		/**< \brief depth of display (8, 15, 16, 24) */ +	uint32_t bpp;		/**< \brief bit depth of display (8, 16, 24, 32) */ + +	uint32_t bus_type;	/**< \brief ths bus type */ +	uint32_t bus_mode;	/**< \brief bus mode (used for AGP, maybe also for PCI-E ?) */ + +	uint32_t front_offset;	/**< \brief front buffer offset */ +	uint32_t front_pitch;	/**< \brief front buffer pitch */ +	uint32_t back_offset;	/**< \brief private back buffer offset */ +	uint32_t back_pitch;	/**< \brief private back buffer pitch */ +	uint32_t depth_offset;	/**< \brief private depth buffer offset */ +	uint32_t depth_pitch;	/**< \brief private depth buffer pitch */ + +}; + +#endif + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_drmif.h b/src/gallium/winsys/dri/nouveau/nouveau_drmif.h new file mode 100644 index 0000000000..dcd6a5eb0a --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_drmif.h @@ -0,0 +1,310 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 __NOUVEAU_DRMIF_H__ +#define __NOUVEAU_DRMIF_H__ + +#include <stdint.h> +#include <xf86drm.h> +#include <nouveau_drm.h> + +#include "nouveau/nouveau_device.h" +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_grobj.h" +#include "nouveau/nouveau_notifier.h" +#include "nouveau/nouveau_bo.h" +#include "nouveau/nouveau_resource.h" +#include "nouveau/nouveau_pushbuf.h" + +struct nouveau_device_priv { +	struct nouveau_device base; + +	int fd; +	drm_context_t ctx; +	drmLock *lock; +	int needs_close; + +	struct drm_nouveau_mem_alloc sa; +	void *sa_map; +	struct nouveau_resource *sa_heap; +}; +#define nouveau_device(n) ((struct nouveau_device_priv *)(n)) + +extern int +nouveau_device_open_existing(struct nouveau_device **, int close, +			     int fd, drm_context_t ctx); + +extern int +nouveau_device_open(struct nouveau_device **, const char *busid); + +extern void +nouveau_device_close(struct nouveau_device **); + +extern int +nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v); + +extern int +nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val); + +struct nouveau_fence { +	struct nouveau_channel *channel; +}; + +struct nouveau_fence_cb { +	struct nouveau_fence_cb *next; +	void (*func)(void *); +	void *priv; +}; + +struct nouveau_fence_priv { +	struct nouveau_fence base; +	int refcount; + +	struct nouveau_fence *next; +	struct nouveau_fence_cb *signal_cb; + +	uint32_t sequence; +	int emitted; +	int signalled; +}; +#define nouveau_fence(n) ((struct nouveau_fence_priv *)(n)) + +extern int +nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); + +extern int +nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **); + +extern int +nouveau_fence_signal_cb(struct nouveau_fence *, void (*)(void *), void *); + +extern void +nouveau_fence_emit(struct nouveau_fence *); + +extern int +nouveau_fence_wait(struct nouveau_fence **); + +extern void +nouveau_fence_flush(struct nouveau_channel *); + +struct nouveau_pushbuf_reloc { +	struct nouveau_pushbuf_bo *pbbo; +	uint32_t *ptr; +	uint32_t flags; +	uint32_t data; +	uint32_t vor; +	uint32_t tor; +}; + +struct nouveau_pushbuf_bo { +	struct nouveau_channel *channel; +	struct nouveau_bo *bo; +	unsigned flags; +	unsigned handled; +}; + +#define NOUVEAU_PUSHBUF_MAX_BUFFERS 1024 +#define NOUVEAU_PUSHBUF_MAX_RELOCS 1024 +struct nouveau_pushbuf_priv { +	struct nouveau_pushbuf base; + +	struct nouveau_fence *fence; + +	unsigned nop_jump; +	unsigned start; +	unsigned size; + +	struct nouveau_pushbuf_bo *buffers; +	unsigned nr_buffers; +	struct nouveau_pushbuf_reloc *relocs; +	unsigned nr_relocs; +}; +#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n)) + +#define pbbo_to_ptr(o) ((uint64_t)(unsigned long)(o)) +#define ptr_to_pbbo(h) ((struct nouveau_pushbuf_bo *)(unsigned long)(h)) +#define pbrel_to_ptr(o) ((uint64_t)(unsigned long)(o)) +#define ptr_to_pbrel(h) ((struct nouveau_pushbuf_reloc *)(unsigned long)(h)) +#define bo_to_ptr(o) ((uint64_t)(unsigned long)(o)) +#define ptr_to_bo(h) ((struct nouveau_bo_priv *)(unsigned long)(h)) + +extern int +nouveau_pushbuf_init(struct nouveau_channel *); + +extern int +nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min); + +extern int +nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr, +			   struct nouveau_bo *, uint32_t data, uint32_t flags, +			   uint32_t vor, uint32_t tor); + +struct nouveau_dma_priv { +	uint32_t base; +	uint32_t max; +	uint32_t cur; +	uint32_t put; +	uint32_t free; + +	int push_free; +} dma; + +struct nouveau_channel_priv { +	struct nouveau_channel base; + +	struct drm_nouveau_channel_alloc drm; + +	uint32_t *pushbuf; +	void     *notifier_block; + +	volatile uint32_t *user; +	volatile uint32_t *put; +	volatile uint32_t *get; +	volatile uint32_t *ref_cnt; + +	struct nouveau_dma_priv dma_master; +	struct nouveau_dma_priv dma_bufmgr; +	struct nouveau_dma_priv *dma; + +	struct nouveau_fence *fence_head; +	struct nouveau_fence *fence_tail; +	uint32_t fence_sequence; + +	struct nouveau_pushbuf_priv pb; + +	unsigned user_charge; +}; +#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n)) + +extern int +nouveau_channel_alloc(struct nouveau_device *, uint32_t fb, uint32_t tt, +		      struct nouveau_channel **); + +extern void +nouveau_channel_free(struct nouveau_channel **); + +struct nouveau_grobj_priv { +	struct nouveau_grobj base; +}; +#define nouveau_grobj(n) ((struct nouveau_grobj_priv *)(n)) + +extern int nouveau_grobj_alloc(struct nouveau_channel *, uint32_t handle, +			       int class, struct nouveau_grobj **); +extern int nouveau_grobj_ref(struct nouveau_channel *, uint32_t handle, +			     struct nouveau_grobj **); +extern void nouveau_grobj_free(struct nouveau_grobj **); + + +struct nouveau_notifier_priv { +	struct nouveau_notifier base; + +	struct drm_nouveau_notifierobj_alloc drm; +	volatile void *map; +}; +#define nouveau_notifier(n) ((struct nouveau_notifier_priv *)(n)) + +extern int +nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, int count, +		       struct nouveau_notifier **); + +extern void +nouveau_notifier_free(struct nouveau_notifier **); + +extern void +nouveau_notifier_reset(struct nouveau_notifier *, int id); + +extern uint32_t +nouveau_notifier_status(struct nouveau_notifier *, int id); + +extern uint32_t +nouveau_notifier_return_val(struct nouveau_notifier *, int id); + +extern int +nouveau_notifier_wait_status(struct nouveau_notifier *, int id, int status, +			     int timeout); + +struct nouveau_bo_priv { +	struct nouveau_bo base; + +	struct nouveau_pushbuf_bo *pending; +	struct nouveau_fence *fence; +	struct nouveau_fence *wr_fence; + +	struct drm_nouveau_mem_alloc drm; +	void *map; + +	void *sysmem; +	int user; + +	int refcount; + +	uint64_t offset; +	uint64_t flags; +	int tiled; +}; +#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n)) + +extern int +nouveau_bo_init(struct nouveau_device *); + +extern void +nouveau_bo_takedown(struct nouveau_device *); + +extern int +nouveau_bo_new(struct nouveau_device *, uint32_t flags, int align, int size, +	       struct nouveau_bo **); + +extern int +nouveau_bo_user(struct nouveau_device *, void *ptr, int size, +		struct nouveau_bo **); + +extern int +nouveau_bo_ref(struct nouveau_device *, uint64_t handle, struct nouveau_bo **); + +extern int +nouveau_bo_set_status(struct nouveau_bo *, uint32_t flags); + +extern void +nouveau_bo_del(struct nouveau_bo **); + +extern int +nouveau_bo_map(struct nouveau_bo *, uint32_t flags); + +extern void +nouveau_bo_unmap(struct nouveau_bo *); + +extern int +nouveau_bo_validate(struct nouveau_channel *, struct nouveau_bo *, +		    uint32_t flags); + +extern int +nouveau_resource_init(struct nouveau_resource **heap, unsigned start, +		      unsigned size); + +extern int +nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv, +		       struct nouveau_resource **); + +extern void +nouveau_resource_free(struct nouveau_resource **); + +#endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_fence.c b/src/gallium/winsys/dri/nouveau/nouveau_fence.c new file mode 100644 index 0000000000..e7b0b4ff07 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_fence.c @@ -0,0 +1,214 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdlib.h> +#include <errno.h> +#include <assert.h> + +#include "nouveau_drmif.h" +#include "nouveau_dma.h" +#include "nouveau_local.h" + +static void +nouveau_fence_del_unsignalled(struct nouveau_fence *fence) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel); +	struct nouveau_fence *le; + +	if (nvchan->fence_head == fence) { +		nvchan->fence_head = nouveau_fence(fence)->next; +		if (nvchan->fence_head == NULL) +			nvchan->fence_tail = NULL; +		return; +	} + +	le = nvchan->fence_head; +	while (le && nouveau_fence(le)->next != fence) +		le = nouveau_fence(le)->next; +	assert(le && nouveau_fence(le)->next == fence); +	nouveau_fence(le)->next = nouveau_fence(fence)->next; +	if (nvchan->fence_tail == fence) +		nvchan->fence_tail = le; +} + +static void +nouveau_fence_del(struct nouveau_fence **fence) +{ +	struct nouveau_fence_priv *nvfence; + +	if (!fence || !*fence) +		return; +	nvfence = nouveau_fence(*fence); +	*fence = NULL; + +	if (--nvfence->refcount) +		return; + +	if (nvfence->emitted && !nvfence->signalled) { +		if (nvfence->signal_cb) { +			nvfence->refcount++; +			nouveau_fence_wait((void *)&nvfence); +			return; +		} + +		nouveau_fence_del_unsignalled(&nvfence->base); +	} +	free(nvfence); +} + +int +nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **fence) +{ +	struct nouveau_fence_priv *nvfence; + +	if (!chan || !fence || *fence) +		return -EINVAL; +	 +	nvfence = calloc(1, sizeof(struct nouveau_fence_priv)); +	if (!nvfence) +		return -ENOMEM; +	nvfence->base.channel = chan; +	nvfence->refcount = 1; + +	*fence = &nvfence->base; +	return 0; +} + +int +nouveau_fence_ref(struct nouveau_fence *ref, struct nouveau_fence **fence) +{ +	struct nouveau_fence_priv *nvfence; + +	if (!fence) +		return -EINVAL; + +	if (*fence) { +		nouveau_fence_del(fence); +		*fence = NULL; +	} + +	if (ref) { +		nvfence = nouveau_fence(ref); +		nvfence->refcount++;	 +		*fence = &nvfence->base; +	} + +	return 0; +} + +int +nouveau_fence_signal_cb(struct nouveau_fence *fence, void (*func)(void *), +			void *priv) +{ +	struct nouveau_fence_priv *nvfence = nouveau_fence(fence); +	struct nouveau_fence_cb *cb; + +	if (!nvfence || !func) +		return -EINVAL; + +	cb = malloc(sizeof(struct nouveau_fence_cb)); +	if (!cb) +		return -ENOMEM; + +	cb->func = func; +	cb->priv = priv; +	cb->next = nvfence->signal_cb; +	nvfence->signal_cb = cb; +	return 0; +} + +void +nouveau_fence_emit(struct nouveau_fence *fence) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel); +	struct nouveau_fence_priv *nvfence = nouveau_fence(fence); + +	nvfence->emitted = 1; +	nvfence->sequence = ++nvchan->fence_sequence; +	if (nvfence->sequence == 0xffffffff) +		NOUVEAU_ERR("AII wrap unhandled\n"); + +	/*XXX: assumes subc 0 is populated */ +	RING_SPACE_CH(fence->channel, 2); +	OUT_RING_CH  (fence->channel, 0x00040050); +	OUT_RING_CH  (fence->channel, nvfence->sequence); + +	if (nvchan->fence_tail) { +		nouveau_fence(nvchan->fence_tail)->next = fence; +	} else { +		nvchan->fence_head = fence; +	} +	nvchan->fence_tail = fence; +} + +void +nouveau_fence_flush(struct nouveau_channel *chan) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	uint32_t sequence = *nvchan->ref_cnt; + +	while (nvchan->fence_head) { +		struct nouveau_fence_priv *nvfence; +	 +		nvfence = nouveau_fence(nvchan->fence_head); +		if (nvfence->sequence > sequence) +			break; +		nouveau_fence_del_unsignalled(&nvfence->base); +		nvfence->signalled = 1; + +		if (nvfence->signal_cb) { +			struct nouveau_fence *fence = NULL; + +			nouveau_fence_ref(&nvfence->base, &fence); + +			while (nvfence->signal_cb) { +				struct nouveau_fence_cb *cb; +				 +				cb = nvfence->signal_cb; +				nvfence->signal_cb = cb->next; +				cb->func(cb->priv); +				free(cb); +			} + +			nouveau_fence_ref(NULL, &fence); +		} +	} +} + +int +nouveau_fence_wait(struct nouveau_fence **fence) +{ +	struct nouveau_fence_priv *nvfence; +	 +	if (!fence || !*fence) +		return -EINVAL; +	nvfence = nouveau_fence(*fence); + +	if (nvfence->emitted) { +		while (!nvfence->signalled) +			nouveau_fence_flush(nvfence->base.channel); +	} +	nouveau_fence_ref(NULL, fence); + +	return 0; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_grobj.c b/src/gallium/winsys/dri/nouveau/nouveau_grobj.c new file mode 100644 index 0000000000..51523897d5 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_grobj.c @@ -0,0 +1,107 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdlib.h> +#include <errno.h> + +#include "nouveau_drmif.h" + +int +nouveau_grobj_alloc(struct nouveau_channel *chan, uint32_t handle, +		    int class, struct nouveau_grobj **grobj) +{ +	struct nouveau_device_priv *nvdev = nouveau_device(chan->device); +	struct nouveau_grobj_priv *nvgrobj; +	struct drm_nouveau_grobj_alloc g; +	int ret; + +	if (!nvdev || !grobj || *grobj) +		return -EINVAL; + +	nvgrobj = calloc(1, sizeof(*nvgrobj)); +	if (!nvgrobj) +		return -ENOMEM; +	nvgrobj->base.channel = chan; +	nvgrobj->base.handle  = handle; +	nvgrobj->base.grclass = class; + +	g.channel = chan->id; +	g.handle  = handle; +	g.class   = class; +	ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GROBJ_ALLOC, +			      &g, sizeof(g)); +	if (ret) { +		nouveau_grobj_free((void *)&nvgrobj); +		return ret; +	} + +	*grobj = &nvgrobj->base; +	return 0; +} + +int +nouveau_grobj_ref(struct nouveau_channel *chan, uint32_t handle, +		  struct nouveau_grobj **grobj) +{ +	struct nouveau_grobj_priv *nvgrobj; + +	if (!chan || !grobj || *grobj) +		return -EINVAL; + +	nvgrobj = calloc(1, sizeof(struct nouveau_grobj_priv)); +	if (!nvgrobj) +		return -ENOMEM; +	nvgrobj->base.channel = chan; +	nvgrobj->base.handle = handle; +	nvgrobj->base.grclass = 0; + +	*grobj = &nvgrobj->base; +	return 0; +} + +void +nouveau_grobj_free(struct nouveau_grobj **grobj) +{ +	struct nouveau_device_priv *nvdev; +	struct nouveau_channel_priv *chan; +	struct nouveau_grobj_priv *nvgrobj; + +	if (!grobj || !*grobj) +		return; +	nvgrobj = nouveau_grobj(*grobj); +	*grobj = NULL; + + +	chan = nouveau_channel(nvgrobj->base.channel); +	nvdev = nouveau_device(chan->base.device); + +	if (nvgrobj->base.grclass) { +		struct drm_nouveau_gpuobj_free f; + +		f.channel = chan->drm.channel; +		f.handle  = nvgrobj->base.handle; +		drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE, +				&f, sizeof(f));	 +	} +	free(nvgrobj); +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_local.h b/src/gallium/winsys/dri/nouveau/nouveau_local.h new file mode 100644 index 0000000000..e878a40803 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_local.h @@ -0,0 +1,117 @@ +#ifndef __NOUVEAU_LOCAL_H__ +#define __NOUVEAU_LOCAL_H__ + +#include "pipe/p_compiler.h" +#include "nouveau_winsys_pipe.h" +#include <stdio.h> + +struct pipe_buffer; + +/* Debug output */ +#define NOUVEAU_MSG(fmt, args...) do {                                         \ +	fprintf(stdout, "nouveau: "fmt, ##args);                               \ +	fflush(stdout);                                                        \ +} while(0) + +#define NOUVEAU_ERR(fmt, args...) do {                                         \ +	fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);           \ +	fflush(stderr);                                                        \ +} while(0) + +#define NOUVEAU_TIME_MSEC() 0 + +/* User FIFO control */ +//#define NOUVEAU_DMA_TRACE +//#define NOUVEAU_DMA_DEBUG +//#define NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF +#define NOUVEAU_DMA_BARRIER  +#define NOUVEAU_DMA_TIMEOUT 2000 + +/* Push buffer access macros */ +static INLINE void +OUT_RING(struct nouveau_channel *chan, unsigned data) +{ +	*(chan->pushbuf->cur++) = (data); +} + +static INLINE void +OUT_RINGp(struct nouveau_channel *chan, uint32_t *data, unsigned size) +{ +	memcpy(chan->pushbuf->cur, data, size * 4); +	chan->pushbuf->cur += size; +} + +static INLINE void +OUT_RINGf(struct nouveau_channel *chan, float f) +{ +	union { uint32_t i; float f; } c; +	c.f = f; +	OUT_RING(chan, c.i); +} + +static INLINE void +BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, +	   unsigned mthd, unsigned size) +{ +	if (chan->pushbuf->remaining < (size + 1)) +		nouveau_pushbuf_flush(chan, (size + 1)); +	OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd); +	chan->pushbuf->remaining -= (size + 1); +} + +static INLINE void +FIRE_RING(struct nouveau_channel *chan) +{ +	nouveau_pushbuf_flush(chan, 0); +} + +static INLINE void +BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned subc) +{ +	gr->subc = subc; +	BEGIN_RING(chan, gr, 0x0000, 1); +	OUT_RING  (chan, gr->handle); +} + +static INLINE void +OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo, +	  unsigned data, unsigned flags, unsigned vor, unsigned tor) +{ +	nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, +				   data, flags, vor, tor); +} + +/* Raw data + flags depending on FB/TT buffer */ +static INLINE void +OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo, +	   unsigned data, unsigned flags, unsigned vor, unsigned tor) +{ +	OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor); +} + +/* FB/TT object handle */ +static INLINE void +OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo, +	   unsigned flags) +{ +	OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR, +		  chan->vram->handle, chan->gart->handle); +} + +/* Low 32-bits of offset */ +static INLINE void +OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo, +	   unsigned delta, unsigned flags) +{ +	OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0); +} + +/* High 32-bits of offset */ +static INLINE void +OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo, +	   unsigned delta, unsigned flags) +{ +	OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0); +} + +#endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_lock.c b/src/gallium/winsys/dri/nouveau/nouveau_lock.c new file mode 100644 index 0000000000..9adb9ac854 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_lock.c @@ -0,0 +1,94 @@ +/************************************************************************** + *  + * Copyright 2003 Tungsten Graphics, 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, 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 TUNGSTEN GRAPHICS 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. + *  + **************************************************************************/ + +#include "main/glheader.h" +#include "glapi/glthread.h" +#include <GL/internal/glcore.h> + +#include "nouveau_context.h" +#include "nouveau_screen.h" + +_glthread_DECLARE_STATIC_MUTEX( lockMutex ); + +static void +nouveau_contended_lock(struct nouveau_context *nv, GLuint flags) +{ +	__DRIdrawablePrivate *dPriv = nv->dri_drawable; +	__DRIscreenPrivate *sPriv = nv->dri_screen; +	struct nouveau_screen *nv_screen = nv->nv_screen; +	struct nouveau_device *dev = nv_screen->device; +	struct nouveau_device_priv *nvdev = nouveau_device(dev); + +	drmGetLock(nvdev->fd, nvdev->ctx, flags); + +	/* If the window moved, may need to set a new cliprect now. +	 * +	 * NOTE: This releases and regains the hw lock, so all state +	 * checking must be done *after* this call: +	 */ +	if (dPriv) +		DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); +} + +/* Lock the hardware and validate our state. + */ +void +LOCK_HARDWARE(struct nouveau_context *nv) +{ +	struct nouveau_screen *nv_screen = nv->nv_screen; +	struct nouveau_device *dev = nv_screen->device; +	struct nouveau_device_priv *nvdev = nouveau_device(dev); +	char __ret=0; + +	_glthread_LOCK_MUTEX(lockMutex); +	assert(!nv->locked); +	 +	DRM_CAS(nvdev->lock, nvdev->ctx, +		(DRM_LOCK_HELD | nvdev->ctx), __ret); +	 +	if (__ret) +		nouveau_contended_lock(nv, 0); +	nv->locked = GL_TRUE; +} + + +  /* Unlock the hardware using the global current context  +   */ +void +UNLOCK_HARDWARE(struct nouveau_context *nv) +{ +	struct nouveau_screen *nv_screen = nv->nv_screen; +	struct nouveau_device *dev = nv_screen->device; +	struct nouveau_device_priv *nvdev = nouveau_device(dev); + +	assert(nv->locked); +	nv->locked = GL_FALSE; + +	DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx); + +	_glthread_UNLOCK_MUTEX(lockMutex); +}  diff --git a/src/gallium/winsys/dri/nouveau/nouveau_notifier.c b/src/gallium/winsys/dri/nouveau/nouveau_notifier.c new file mode 100644 index 0000000000..01e8f38440 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_notifier.c @@ -0,0 +1,137 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdlib.h> +#include <errno.h> + +#include "nouveau_drmif.h" +#include "nouveau_local.h" + +#define NOTIFIER(__v)                                                          \ +	struct nouveau_notifier_priv *nvnotify = nouveau_notifier(notifier);   \ +	volatile uint32_t *__v = (void*)nvnotify->map + (id * 32) + +int +nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, +		       int count, struct nouveau_notifier **notifier) +{ +	struct nouveau_notifier_priv *nvnotify; +	int ret; + +	if (!chan || !notifier || *notifier) +		return -EINVAL; + +	nvnotify = calloc(1, sizeof(struct nouveau_notifier_priv)); +	if (!nvnotify) +		return -ENOMEM; +	nvnotify->base.channel = chan; +	nvnotify->base.handle  = handle; + +	nvnotify->drm.channel = chan->id; +	nvnotify->drm.handle  = handle; +	nvnotify->drm.count   = count; +	if ((ret = drmCommandWriteRead(nouveau_device(chan->device)->fd, +				       DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, +				       &nvnotify->drm, +				       sizeof(nvnotify->drm)))) { +		nouveau_notifier_free((void *)&nvnotify); +		return ret; +	} + +	nvnotify->map = (void *)nouveau_channel(chan)->notifier_block + +				nvnotify->drm.offset; +	*notifier = &nvnotify->base; +	return 0; +} + +void +nouveau_notifier_free(struct nouveau_notifier **notifier) +{ + +	struct nouveau_notifier_priv *nvnotify; +	struct nouveau_channel_priv *nvchan; +	struct nouveau_device_priv *nvdev; +	struct drm_nouveau_gpuobj_free f; + +	if (!notifier || !*notifier) +		return; +	nvnotify = nouveau_notifier(*notifier); +	*notifier = NULL; + +	nvchan = nouveau_channel(nvnotify->base.channel); +	nvdev   = nouveau_device(nvchan->base.device); + +	f.channel = nvchan->drm.channel; +	f.handle  = nvnotify->base.handle; +	drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE, &f, sizeof(f));		 +	free(nvnotify); +} + +void +nouveau_notifier_reset(struct nouveau_notifier *notifier, int id) +{ +	NOTIFIER(n); + +	n[NV_NOTIFY_TIME_0      /4] = 0x00000000; +	n[NV_NOTIFY_TIME_1      /4] = 0x00000000; +	n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000; +	n[NV_NOTIFY_STATE       /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS << +				       NV_NOTIFY_STATE_STATUS_SHIFT); +} + +uint32_t +nouveau_notifier_status(struct nouveau_notifier *notifier, int id) +{ +	NOTIFIER(n); + +	return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT; +} + +uint32_t +nouveau_notifier_return_val(struct nouveau_notifier *notifier, int id) +{ +	NOTIFIER(n); + +	return n[NV_NOTIFY_RETURN_VALUE/4]; +} + +int +nouveau_notifier_wait_status(struct nouveau_notifier *notifier, int id, +			     int status, int timeout) +{ +	NOTIFIER(n); +	uint32_t time = 0, t_start = NOUVEAU_TIME_MSEC(); + +	while (time <= timeout) { +		uint32_t v; + +		v = n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT; +		if (v == status) +			return 0; + +		if (timeout) +			time = NOUVEAU_TIME_MSEC() - t_start; +	} + +	return -EBUSY; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_pushbuf.c b/src/gallium/winsys/dri/nouveau/nouveau_pushbuf.c new file mode 100644 index 0000000000..815046ba85 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_pushbuf.c @@ -0,0 +1,271 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdlib.h> +#include <errno.h> +#include <assert.h> + +#include "nouveau_drmif.h" +#include "nouveau_dma.h" + +#define PB_BUFMGR_DWORDS   (4096 / 2) +#define PB_MIN_USER_DWORDS  2048 + +static int +nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb; + +	assert((min + 1) <= nvchan->dma->max); + +	/* Wait for enough space in push buffer */ +	min = min < PB_MIN_USER_DWORDS ? PB_MIN_USER_DWORDS : min; +	min += 1; /* a bit extra for the NOP */ +	if (nvchan->dma->free < min) +		WAIT_RING_CH(chan, min); + +	/* Insert NOP, may turn into a jump later */ +	RING_SPACE_CH(chan, 1); +	nvpb->nop_jump = nvchan->dma->cur; +	OUT_RING_CH(chan, 0); + +	/* Any remaining space is available to the user */ +	nvpb->start = nvchan->dma->cur; +	nvpb->size = nvchan->dma->free; +	nvpb->base.channel = chan; +	nvpb->base.remaining = nvpb->size; +	nvpb->base.cur = &nvchan->pushbuf[nvpb->start]; + +	/* Create a new fence object for this "frame" */ +	nouveau_fence_ref(NULL, &nvpb->fence); +	nouveau_fence_new(chan, &nvpb->fence); + +	return 0; +} + +int +nouveau_pushbuf_init(struct nouveau_channel *chan) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_dma_priv *m = &nvchan->dma_master; +	struct nouveau_dma_priv *b = &nvchan->dma_bufmgr; +	int i; + +	if (!nvchan) +		return -EINVAL; + +	/* Reassign last bit of push buffer for a "separate" bufmgr +	 * ring buffer +	 */ +	m->max -= PB_BUFMGR_DWORDS; +	m->free -= PB_BUFMGR_DWORDS; + +	b->base = m->base + ((m->max + 2) << 2); +	b->max = PB_BUFMGR_DWORDS - 2; +	b->cur = b->put = 0; +	b->free = b->max - b->cur; + +	/* Some NOPs just to be safe +	 *XXX: RING_SKIPS +	 */ +	nvchan->dma = b; +	RING_SPACE_CH(chan, 8); +	for (i = 0; i < 8; i++) +		OUT_RING_CH(chan, 0); +	nvchan->dma = m; + +	nouveau_pushbuf_space(chan, 0); +	chan->pushbuf = &nvchan->pb.base; + +	nvchan->pb.buffers = calloc(NOUVEAU_PUSHBUF_MAX_BUFFERS, +				    sizeof(struct nouveau_pushbuf_bo)); +	nvchan->pb.relocs = calloc(NOUVEAU_PUSHBUF_MAX_RELOCS, +				   sizeof(struct nouveau_pushbuf_reloc)); +	return 0; +} + +static uint32_t +nouveau_pushbuf_calc_reloc(struct nouveau_bo *bo, +			   struct nouveau_pushbuf_reloc *r) +{ +	uint32_t push; + +	if (r->flags & NOUVEAU_BO_LOW) { +		push = bo->offset + r->data; +	} else +	if (r->flags & NOUVEAU_BO_HIGH) { +		push = (bo->offset + r->data) >> 32; +	} else { +		push = r->data; +	} + +	if (r->flags & NOUVEAU_BO_OR) { +		if (bo->flags & NOUVEAU_BO_VRAM) +			push |= r->vor; +		else +			push |= r->tor; +	} + +	return push; +} + +/* This would be our TTM "superioctl" */ +int +nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min) +{ +	struct nouveau_channel_priv *nvchan = nouveau_channel(chan); +	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb; +	int ret, i; + +	if (nvpb->base.remaining == nvpb->size) +		return 0; + +	nouveau_fence_flush(chan); + +	nvpb->size -= nvpb->base.remaining; +	nvchan->dma->cur += nvpb->size; +	nvchan->dma->free -= nvpb->size; +	assert(nvchan->dma->cur <= nvchan->dma->max); + +	nvchan->dma = &nvchan->dma_bufmgr; +	nvchan->pushbuf[nvpb->nop_jump] = 0x20000000 | +		(nvchan->dma->base + (nvchan->dma->cur << 2)); + +	/* Validate buffers + apply relocations */ +	nvchan->user_charge = 0; +	for (i = 0; i < nvpb->nr_relocs; i++) { +		struct nouveau_pushbuf_reloc *r = &nvpb->relocs[i]; +		struct nouveau_pushbuf_bo *pbbo = r->pbbo; +		struct nouveau_bo *bo = pbbo->bo; + +		/* Validated, mem matches presumed, no relocation necessary */ +		if (pbbo->handled & 2) { +			if (!(pbbo->handled & 1)) +				assert(0); +			continue; +		} + +		/* Not yet validated, do it now */ +		if (!(pbbo->handled & 1)) { +			ret = nouveau_bo_validate(chan, bo, pbbo->flags); +			if (ret) { +				assert(0); +				return ret; +			} +			pbbo->handled |= 1; + +			if (bo->offset == nouveau_bo(bo)->offset && +			    bo->flags == nouveau_bo(bo)->flags) { +				pbbo->handled |= 2; +				continue; +			} +			bo->offset = nouveau_bo(bo)->offset; +			bo->flags = nouveau_bo(bo)->flags; +		} + +		/* Apply the relocation */ +		*r->ptr = nouveau_pushbuf_calc_reloc(bo, r); +	} +	nvpb->nr_relocs = 0; + +	/* Dereference all buffers on validate list */ +	for (i = 0; i < nvpb->nr_buffers; i++) { +		struct nouveau_pushbuf_bo *pbbo = &nvpb->buffers[i]; + +		nouveau_bo(pbbo->bo)->pending = NULL; +		nouveau_bo_del(&pbbo->bo); +	} +	nvpb->nr_buffers = 0; + +	/* Switch back to user's ring */ +	RING_SPACE_CH(chan, 1); +	OUT_RING_CH(chan, 0x20000000 | ((nvpb->start << 2) + +					nvchan->dma_master.base)); +	nvchan->dma = &nvchan->dma_master; + +	/* Fence + kickoff */ +	nouveau_fence_emit(nvpb->fence); +	FIRE_RING_CH(chan); + +	/* Allocate space for next push buffer */ +	ret = nouveau_pushbuf_space(chan, min); +	assert(!ret); + +	return 0; +} + +static struct nouveau_pushbuf_bo * +nouveau_pushbuf_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo) +{ +	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf); +	struct nouveau_bo_priv *nvbo = nouveau_bo(bo); +	struct nouveau_pushbuf_bo *pbbo; + +	if (nvbo->pending) +		return nvbo->pending; + +	if (nvpb->nr_buffers >= NOUVEAU_PUSHBUF_MAX_BUFFERS) +		return NULL; +	pbbo = nvpb->buffers + nvpb->nr_buffers++; +	nvbo->pending = pbbo; + +	nouveau_bo_ref(bo->device, bo->handle, &pbbo->bo); +	pbbo->channel = chan; +	pbbo->flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART; +	pbbo->handled = 0; +	return pbbo; +} + +int +nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr, +			   struct nouveau_bo *bo, uint32_t data, uint32_t flags, +			   uint32_t vor, uint32_t tor) +{ +	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf); +	struct nouveau_pushbuf_bo *pbbo; +	struct nouveau_pushbuf_reloc *r; + +	if (nvpb->nr_relocs >= NOUVEAU_PUSHBUF_MAX_RELOCS) +		return -ENOMEM; + +	pbbo = nouveau_pushbuf_emit_buffer(chan, bo); +	if (!pbbo) +		return -ENOMEM; +	pbbo->flags |= (flags & NOUVEAU_BO_RDWR); +	pbbo->flags &= (flags | NOUVEAU_BO_RDWR); + +	r = nvpb->relocs + nvpb->nr_relocs++; +	r->pbbo = pbbo; +	r->ptr = ptr; +	r->flags = flags; +	r->data = data; +	r->vor = vor; +	r->tor = tor; + +	if (flags & NOUVEAU_BO_DUMMY) +		*(uint32_t *)ptr = 0; +	else +		*(uint32_t *)ptr = nouveau_pushbuf_calc_reloc(bo, r); +	return 0; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_resource.c b/src/gallium/winsys/dri/nouveau/nouveau_resource.c new file mode 100644 index 0000000000..3bbcb5c45e --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_resource.c @@ -0,0 +1,116 @@ +/* + * Copyright 2007 Nouveau Project + * + * 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 + * THE AUTHORS 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 <stdlib.h> +#include <errno.h> + +#include "nouveau_drmif.h" +#include "nouveau_local.h" + +int +nouveau_resource_init(struct nouveau_resource **heap, +		      unsigned start, unsigned size) +{ +	struct nouveau_resource *r; + +	r = calloc(1, sizeof(struct nouveau_resource)); +	if (!r) +		return 1; + +	r->start = start; +	r->size  = size; +	*heap = r; +	return 0; +} + +int +nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv, +		       struct nouveau_resource **res) +{ +	struct nouveau_resource *r; + +	if (!heap || !size || !res || *res) +		return 1; + +	while (heap) { +		if (!heap->in_use && heap->size >= size) { +			r = calloc(1, sizeof(struct nouveau_resource)); +			if (!r) +				return 1; + +			r->start  = (heap->start + heap->size) - size; +			r->size   = size; +			r->in_use = 1; +			r->priv   = priv; + +			heap->size -= size; + +			r->next = heap->next; +			if (heap->next) +				heap->next->prev = r; +			r->prev = heap; +			heap->next = r; + +			*res = r; +			return 0; +		} +			 +		heap = heap->next; +	} + +	return 1; +} + +void +nouveau_resource_free(struct nouveau_resource **res) +{ +	struct nouveau_resource *r; + +	if (!res || !*res) +		return; +	r = *res; +	*res = NULL; + +	r->in_use = 0; + +	if (r->next && !r->next->in_use) { +		struct nouveau_resource *new = r->next; + +		new->prev = r->prev; +		if (r->prev) +			r->prev->next = new; +		new->size += r->size; +		new->start = r->start; + +		free(r); +		r = new; +	} + +	if (r->prev && !r->prev->in_use) { +		r->prev->next = r->next; +		if (r->next) +			r->next->prev = r->prev; +		r->prev->size += r->size; +		free(r); +	} +	 +} diff --git a/src/gallium/winsys/dri/nouveau/nouveau_screen.c b/src/gallium/winsys/dri/nouveau/nouveau_screen.c new file mode 100644 index 0000000000..df1fe7e69b --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_screen.c @@ -0,0 +1,310 @@ +#include "utils.h" +#include "vblank.h" +#include "xmlpool.h" + +#include "pipe/p_context.h" +#include "state_tracker/st_public.h" +#include "state_tracker/st_cb_fbo.h" + +#include "nouveau_context.h" +#include "nouveau_drm.h" +#include "nouveau_dri.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_swapbuffers.h" + +#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 11 +#error nouveau_drm.h version does not match expected version +#endif + +/* Extension stuff, enabling of extensions handled by Gallium's GL state + * tracker.  But, we still need to define the entry points we want. + */ +#define need_GL_ARB_fragment_program +#define need_GL_ARB_multisample +#define need_GL_ARB_occlusion_query +#define need_GL_ARB_point_parameters +#define need_GL_ARB_shader_objects +#define need_GL_ARB_texture_compression +#define need_GL_ARB_vertex_program +#define need_GL_ARB_vertex_shader +#define need_GL_ARB_vertex_buffer_object +#define need_GL_EXT_compiled_vertex_array +#define need_GL_EXT_fog_coord +#define need_GL_EXT_secondary_color +#define need_GL_EXT_framebuffer_object +#define need_GL_VERSION_2_0 +#define need_GL_VERSION_2_1 +#include "extension_helper.h" + +const struct dri_extension card_extensions[] = +{ +	{ "GL_ARB_multisample", GL_ARB_multisample_functions }, +	{ "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions }, +	{ "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, +	{ "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, +	{ "GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, +	{ "GL_ARB_shading_language_120", GL_VERSION_2_1_functions }, +	{ "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, +	{ "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, +	{ "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions }, +	{ "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions }, +	{ "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, +	{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, +	{ "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, +	{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, +	{ NULL, 0 } +}; + +PUBLIC const char __driConfigOptions[] = +DRI_CONF_BEGIN +DRI_CONF_END; +static const GLuint __driNConfigOptions = 0; + +extern const struct dri_extension common_extensions[]; +extern const struct dri_extension nv40_extensions[]; + +static GLboolean +nouveau_screen_create(__DRIscreenPrivate *driScrnPriv) +{ +	struct nouveau_dri *nv_dri = driScrnPriv->pDevPriv; +	struct nouveau_screen *nv_screen; +	int ret; + +	if (driScrnPriv->devPrivSize != sizeof(struct nouveau_dri)) { +		NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n"); +		return GL_FALSE; +	} + +	nv_screen = CALLOC_STRUCT(nouveau_screen); +	if (!nv_screen) +		return GL_FALSE; +	nv_screen->driScrnPriv = driScrnPriv; +	driScrnPriv->private = (void *)nv_screen; + +	driParseOptionInfo(&nv_screen->option_cache, +			   __driConfigOptions, __driNConfigOptions); + +	if ((ret = nouveau_device_open_existing(&nv_screen->device, 0, +						driScrnPriv->fd, 0))) { +		NOUVEAU_ERR("Failed opening nouveau device: %d\n", ret); +		return GL_FALSE; +	} + +	nv_screen->front_offset = nv_dri->front_offset; +	nv_screen->front_pitch  = nv_dri->front_pitch * (nv_dri->bpp / 8); +	nv_screen->front_cpp = nv_dri->bpp / 8; +	nv_screen->front_height = nv_dri->height; + +	return GL_TRUE; +} + +static void +nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv) +{ +	struct nouveau_screen *nv_screen = driScrnPriv->private; + +	driScrnPriv->private = NULL; +	FREE(nv_screen); +} + +static GLboolean +nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv, +		      __DRIdrawablePrivate * driDrawPriv, +		      const __GLcontextModes *glVis, GLboolean pixmapBuffer) +{ +	struct nouveau_framebuffer *nvfb; +	enum pipe_format colour, depth, stencil; + +	if (pixmapBuffer) +		return GL_FALSE; + +	nvfb = CALLOC_STRUCT(nouveau_framebuffer); +	if (!nvfb) +		return GL_FALSE; + +	if (glVis->redBits == 5) +		colour = PIPE_FORMAT_R5G6B5_UNORM; +	else +		colour = PIPE_FORMAT_A8R8G8B8_UNORM; + +	if (glVis->depthBits == 16) +		depth = PIPE_FORMAT_Z16_UNORM; +	else if (glVis->depthBits == 24) +		depth = PIPE_FORMAT_Z24S8_UNORM; +	else +		depth = PIPE_FORMAT_NONE; + +	if (glVis->stencilBits == 8) +		stencil = PIPE_FORMAT_Z24S8_UNORM; +	else +		stencil = PIPE_FORMAT_NONE; + +	nvfb->stfb = st_create_framebuffer(glVis, colour, depth, stencil, +					   driDrawPriv->w, driDrawPriv->h, +					   (void*)nvfb); +	if (!nvfb->stfb) { +		free(nvfb); +		return  GL_FALSE; +	} + +	driDrawPriv->driverPrivate = (void *)nvfb; +	return GL_TRUE; +} + +static void +nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv) +{ +	struct nouveau_framebuffer *nvfb; +	 +	nvfb = (struct nouveau_framebuffer *)driDrawPriv->driverPrivate; +	st_unreference_framebuffer(&nvfb->stfb); +	free(nvfb); +} + +static struct __DriverAPIRec +nouveau_api = { +	.InitDriver	= nouveau_screen_create, +	.DestroyScreen	= nouveau_screen_destroy, +	.CreateContext	= nouveau_context_create, +	.DestroyContext	= nouveau_context_destroy, +	.CreateBuffer	= nouveau_create_buffer, +	.DestroyBuffer	= nouveau_destroy_buffer, +	.SwapBuffers	= nouveau_swap_buffers, +	.MakeCurrent	= nouveau_context_bind, +	.UnbindContext	= nouveau_context_unbind, +	.GetSwapInfo	= NULL, +	.GetMSC		= NULL, +	.WaitForMSC	= NULL, +	.WaitForSBC	= NULL, +	.SwapBuffersMSC	= NULL, +	.CopySubBuffer	= nouveau_copy_sub_buffer, +	.setTexOffset	= NULL +}; + +static __GLcontextModes * +nouveau_fill_in_modes(unsigned pixel_bits, unsigned depth_bits, +		      unsigned stencil_bits, GLboolean have_back_buffer) +{ +	__GLcontextModes * modes; +	__GLcontextModes * m; +	unsigned num_modes; +	unsigned depth_buffer_factor; +	unsigned back_buffer_factor; +	int i; + +	static const struct { +		GLenum format; +		GLenum type; +	} fb_format_array[] = { +		{ GL_RGB , GL_UNSIGNED_SHORT_5_6_5     }, +		{ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, +		{ GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, +	}; + +	/* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't +	 * support pageflipping at all. +	 */ +	static const GLenum back_buffer_modes[] = { +		GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML +	}; + +	uint8_t depth_bits_array[4]   = { 0, 16, 24, 24 }; +	uint8_t stencil_bits_array[4] = { 0,  0,  0, 8 }; +	uint8_t msaa_samples_array[1] = { 0 }; + +	depth_buffer_factor = 4; +	back_buffer_factor  = (have_back_buffer) ? 3 : 1; + +	num_modes = ((pixel_bits==16) ? 1 : 2) * +		depth_buffer_factor * back_buffer_factor * 4; +	modes = (*dri_interface->createContextModes)(num_modes, +						     sizeof(__GLcontextModes)); +	m = modes; + +	for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) { +		if (!driFillInModes(&m, fb_format_array[i].format, +					fb_format_array[i].type, +					depth_bits_array, +					stencil_bits_array, +					depth_buffer_factor, +					back_buffer_modes, +					back_buffer_factor, +					msaa_samples_array, 1, +					GLX_TRUE_COLOR)) { +		fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", +				__func__, __LINE__ ); +		return NULL; +		} + +		if (!driFillInModes(&m, fb_format_array[i].format, +					fb_format_array[i].type, +					depth_bits_array, +					stencil_bits_array, +					depth_buffer_factor, +					back_buffer_modes, +					back_buffer_factor, +					msaa_samples_array, 1, +					GLX_DIRECT_COLOR)) { +		fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", +				__func__, __LINE__ ); +		return NULL; +		} +	} + +	return modes; +} +PUBLIC void * +__driCreateNewScreen_20050727(__DRInativeDisplay *dpy, int scrn, +			      __DRIscreen *psc, const __GLcontextModes * modes, +			      const __DRIversion * ddx_version, +			      const __DRIversion * dri_version, +			      const __DRIversion * drm_version, +			      const __DRIframebuffer * frame_buffer, +			      void * pSAREA, int fd, int internal_api_version, +			      const __DRIinterfaceMethods * interface, +			      __GLcontextModes ** driver_modes) +{ +	__DRIscreenPrivate *psp; +	static const __DRIversion ddx_expected = +		{ 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; +	static const __DRIversion dri_expected = { 4, 0, 0 }; +	static const __DRIversion drm_expected = +		{ 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; +	struct nouveau_dri *nv_dri = NULL; + +	dri_interface = interface; + +	if (!driCheckDriDdxDrmVersions2("nouveau", +					dri_version, &dri_expected, +					ddx_version, &ddx_expected, +					drm_version, &drm_expected)) { +		return NULL; +	} + +	if (drm_expected.patch != drm_version->patch) { +		fprintf(stderr, "Incompatible DRM patch level.\n" +				"Expected: %d\n" "Current : %d\n", +			drm_expected.patch, drm_version->patch); +		return NULL; +	} + +	psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, +				       ddx_version, dri_version, drm_version, +				       frame_buffer, pSAREA, fd, +				       internal_api_version, +				       &nouveau_api); +	if (psp == NULL) +		return NULL; +	nv_dri = psp->pDevPriv; + +	*driver_modes = nouveau_fill_in_modes(nv_dri->bpp, +					      (nv_dri->bpp == 16) ? 16 : 24, +					      (nv_dri->bpp == 16) ? 0 : 8, +					      1); + +	driInitExtensions(NULL, card_extensions, GL_FALSE); + +	return (void *)psp; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_screen.h b/src/gallium/winsys/dri/nouveau/nouveau_screen.h new file mode 100644 index 0000000000..388d6be9bb --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_screen.h @@ -0,0 +1,20 @@ +#ifndef __NOUVEAU_SCREEN_H__ +#define __NOUVEAU_SCREEN_H__ + +#include "xmlconfig.h" + +struct nouveau_screen { +	__DRIscreenPrivate *driScrnPriv; +	driOptionCache      option_cache; + +	struct nouveau_device *device; + +	uint32_t front_offset; +	uint32_t front_pitch; +	uint32_t front_cpp; +	uint32_t front_height; + +	void *nvc; +}; + +#endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.c b/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.c new file mode 100644 index 0000000000..70e0104e83 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.c @@ -0,0 +1,86 @@ +#include "main/glheader.h" +#include "glapi/glthread.h" +#include <GL/internal/glcore.h> + +#include "pipe/p_context.h" +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_cb_fbo.h" + +#include "nouveau_context.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_swapbuffers.h" + +void +nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf, +		    const drm_clip_rect_t *rect) +{ +	struct nouveau_context *nv = dPriv->driContextPriv->driverPrivate; +	drm_clip_rect_t *pbox; +	int nbox, i; + +	LOCK_HARDWARE(nv); +	if (!dPriv->numClipRects) { +		UNLOCK_HARDWARE(nv); +		return; +	} +	pbox = dPriv->pClipRects; +	nbox = dPriv->numClipRects; + +	nv->surface_copy_prep(nv, nv->frontbuffer, surf); +	for (i = 0; i < nbox; i++, pbox++) { +		int sx, sy, dx, dy, w, h; + +		sx = pbox->x1 - dPriv->x; +		sy = pbox->y1 - dPriv->y; +		dx = pbox->x1; +		dy = pbox->y1; +		w  = pbox->x2 - pbox->x1; +		h  = pbox->y2 - pbox->y1; + +		nv->surface_copy(nv, dx, dy, sx, sy, w, h); +	} + +	FIRE_RING(nv->nvc->channel); +	UNLOCK_HARDWARE(nv); + +	if (nv->last_stamp != dPriv->lastStamp) { +		struct nouveau_framebuffer *nvfb = dPriv->driverPrivate; +		st_resize_framebuffer(nvfb->stfb, dPriv->w, dPriv->h); +		nv->last_stamp = dPriv->lastStamp; +	} +} + +void +nouveau_copy_sub_buffer(__DRIdrawablePrivate *dPriv, int x, int y, int w, int h) +{ +	struct nouveau_framebuffer *nvfb = dPriv->driverPrivate; +	struct pipe_surface *surf; + +	surf = st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT); +	if (surf) { +		drm_clip_rect_t rect; +		rect.x1 = x; +		rect.y1 = y; +		rect.x2 = x + w; +		rect.y2 = y + h; + +		st_notify_swapbuffers(nvfb->stfb); +		nouveau_copy_buffer(dPriv, surf, &rect); +	} +} + +void +nouveau_swap_buffers(__DRIdrawablePrivate *dPriv) +{ +	struct nouveau_framebuffer *nvfb = dPriv->driverPrivate; +	struct pipe_surface *surf; + +	surf = st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT); +	if (surf) { +		st_notify_swapbuffers(nvfb->stfb); +		nouveau_copy_buffer(dPriv, surf, NULL); +	} +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.h b/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.h new file mode 100644 index 0000000000..825d3da6da --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.h @@ -0,0 +1,10 @@ +#ifndef __NOUVEAU_SWAPBUFFERS_H__ +#define __NOUVEAU_SWAPBUFFERS_H__ + +extern void nouveau_copy_buffer(__DRIdrawablePrivate *, struct pipe_surface *, +				const drm_clip_rect_t *); +extern void nouveau_copy_sub_buffer(__DRIdrawablePrivate *, +				    int x, int y, int w, int h); +extern void nouveau_swap_buffers(__DRIdrawablePrivate *); + +#endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c new file mode 100644 index 0000000000..5eabbc8893 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c @@ -0,0 +1,158 @@ +#include "pipe/p_util.h" + +#include "nouveau_context.h" +#include "nouveau_screen.h" +#include "nouveau_winsys_pipe.h" + +#include "nouveau/nouveau_winsys.h" + +static int +nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count, +			    struct nouveau_notifier **notify) +{ +	struct nouveau_context *nv = nvws->nv; + +	return nouveau_notifier_alloc(nv->nvc->channel, nv->nvc->next_handle++, +				      count, notify); +} + +static int +nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass, +			 struct nouveau_grobj **grobj) +{ +	struct nouveau_context *nv = nvws->nv; +	struct nouveau_channel *chan = nv->nvc->channel; +	int ret; + +	ret = nouveau_grobj_alloc(chan, nv->nvc->next_handle++, +				  grclass, grobj); +	if (ret) +		return ret; + +	assert(nv->nvc->next_subchannel < 7); +	BIND_RING(chan, *grobj, nv->nvc->next_subchannel++); +	return 0; +} + +static int +nouveau_pipe_surface_copy(struct nouveau_winsys *nvws, struct pipe_surface *dst, +			  unsigned dx, unsigned dy, struct pipe_surface *src, +			  unsigned sx, unsigned sy, unsigned w, unsigned h) +{ +	struct nouveau_context *nv = nvws->nv; + +	if (nv->surface_copy_prep(nv, dst, src)) +		return 1; +	nv->surface_copy(nv, dx, dy, sx, sy, w, h); +	nv->surface_copy_done(nv); + +	return 0; +} + +static int +nouveau_pipe_surface_fill(struct nouveau_winsys *nvws, struct pipe_surface *dst, +			  unsigned dx, unsigned dy, unsigned w, unsigned h, +			  unsigned value) +{ +	if (nvws->nv->surface_fill(nvws->nv, dst, dx, dy, w, h, value)) +		return 1; +	return 0; +} + +static int +nouveau_pipe_push_reloc(struct nouveau_winsys *nvws, void *ptr, +			struct pipe_buffer *buf, uint32_t data, +			uint32_t flags, uint32_t vor, uint32_t tor) +{ +	return nouveau_pushbuf_emit_reloc(nvws->channel, ptr, +					  nouveau_buffer(buf)->bo, +					  data, flags, vor, tor); +} + +static int +nouveau_pipe_push_flush(struct nouveau_winsys *nvws, unsigned size, +			struct pipe_fence_handle **fence) +{ +	if (fence) { +		struct nouveau_pushbuf *pb = nvws->channel->pushbuf; +		struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(pb); +		struct nouveau_fence *ref = NULL; + +		nouveau_fence_ref(nvpb->fence, &ref); +		*fence = (struct pipe_fence_handle *)ref; +	} + +	return nouveau_pushbuf_flush(nvws->channel, size); +} + +struct pipe_context * +nouveau_pipe_create(struct nouveau_context *nv) +{ +	struct nouveau_channel_context *nvc = nv->nvc; +	struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys); +	struct pipe_screen *(*hws_create)(struct pipe_winsys *, +					  struct nouveau_winsys *); +	struct pipe_context *(*hw_create)(struct pipe_screen *, unsigned); +	struct pipe_winsys *ws; +	unsigned chipset = nv->nv_screen->device->chipset; + +	if (!nvws) +		return NULL; + +	switch (chipset & 0xf0) { +	case 0x10: +	case 0x20: +		hws_create = nv10_screen_create; +		hw_create = nv10_create; +		break; +	case 0x30: +		hws_create = nv30_screen_create; +		hw_create = nv30_create; +		break; +	case 0x40: +	case 0x60: +		hws_create = nv40_screen_create; +		hw_create = nv40_create; +		break; +	case 0x50: +	case 0x80: +	case 0x90: +		hws_create = nv50_screen_create; +		hw_create = nv50_create; +		break; +	default: +		NOUVEAU_ERR("Unknown chipset NV%02x\n", chipset); +		return NULL; +	} + +	nvws->nv		= nv; +	nvws->channel		= nv->nvc->channel; + +	nvws->res_init		= nouveau_resource_init; +	nvws->res_alloc		= nouveau_resource_alloc; +	nvws->res_free		= nouveau_resource_free; + +	nvws->push_reloc        = nouveau_pipe_push_reloc; +	nvws->push_flush	= nouveau_pipe_push_flush; + +	nvws->grobj_alloc	= nouveau_pipe_grobj_alloc; +	nvws->grobj_free	= nouveau_grobj_free; + +	nvws->notifier_alloc	= nouveau_pipe_notifier_alloc; +	nvws->notifier_free	= nouveau_notifier_free; +	nvws->notifier_reset	= nouveau_notifier_reset; +	nvws->notifier_status	= nouveau_notifier_status; +	nvws->notifier_retval	= nouveau_notifier_return_val; +	nvws->notifier_wait	= nouveau_notifier_wait_status; + +	nvws->surface_copy	= nouveau_pipe_surface_copy; +	nvws->surface_fill	= nouveau_pipe_surface_fill; + +	ws = nouveau_create_pipe_winsys(nv); + +	if (!nvc->pscreen) +		nvc->pscreen = hws_create(ws, nvws); +	nvc->pctx[nv->pctx_id] = hw_create(nvc->pscreen, nv->pctx_id); +	return nvc->pctx[nv->pctx_id]; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.c new file mode 100644 index 0000000000..8a2870a2ff --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.c @@ -0,0 +1,205 @@ +#include "pipe/p_winsys.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "nouveau_context.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_swapbuffers.h" +#include "nouveau_winsys_pipe.h" + +static void +nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf, +			  void *context_private) +{ +	struct nouveau_context *nv = context_private; +	__DRIdrawablePrivate *dPriv = nv->dri_drawable; + +	nouveau_copy_buffer(dPriv, surf, NULL); +} + +static const char * +nouveau_get_name(struct pipe_winsys *pws) +{ +	return "Nouveau/DRI"; +} + +static struct pipe_buffer * +nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, +		       unsigned usage, unsigned size) +{ +	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; +	struct nouveau_context *nv = nvpws->nv; +	struct nouveau_device *dev = nv->nv_screen->device; +	struct nouveau_pipe_buffer *nvbuf; +	uint32_t flags; + +	nvbuf = calloc(1, sizeof(*nvbuf)); +	if (!nvbuf) +		return NULL; +	nvbuf->base.refcount = 1; +	nvbuf->base.alignment = alignment; +	nvbuf->base.usage = usage; +	nvbuf->base.size = size; + +	flags = NOUVEAU_BO_LOCAL; + +	if (usage & PIPE_BUFFER_USAGE_PIXEL) { +		if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE) +			flags |= NOUVEAU_BO_GART; +		flags |= NOUVEAU_BO_VRAM; + +		switch (dev->chipset & 0xf0) { +		case 0x50: +		case 0x80: +		case 0x90: +			flags |= NOUVEAU_BO_TILED; +			if (usage & NOUVEAU_BUFFER_USAGE_ZETA) +				flags |= NOUVEAU_BO_ZTILE; +			break; +		default: +			break; +		} +	} + +	if (usage & PIPE_BUFFER_USAGE_VERTEX) { +		if (nv->cap.hw_vertex_buffer) +			flags |= NOUVEAU_BO_GART; +	} + +	if (usage & PIPE_BUFFER_USAGE_INDEX) { +		if (nv->cap.hw_index_buffer) +			flags |= NOUVEAU_BO_GART; +	} + +	if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { +		free(nvbuf); +		return NULL; +	} + +	return &nvbuf->base; +} + +static struct pipe_buffer * +nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) +{ +	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; +	struct nouveau_device *dev = nvpws->nv->nv_screen->device; +	struct nouveau_pipe_buffer *nvbuf; + +	nvbuf = calloc(1, sizeof(*nvbuf)); +	if (!nvbuf) +		return NULL; +	nvbuf->base.refcount = 1; +	nvbuf->base.size = bytes; + +	if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) { +		free(nvbuf); +		return NULL; +	} + +	return &nvbuf->base; +} + +static void +nouveau_pipe_bo_del(struct pipe_winsys *ws, struct pipe_buffer *buf) +{ +	struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf); + +	nouveau_bo_del(&nvbuf->bo); +	free(nvbuf); +} + +static void * +nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf, +		    unsigned flags) +{ +	struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf); +	uint32_t map_flags = 0; + +	if (flags & PIPE_BUFFER_USAGE_CPU_READ) +		map_flags |= NOUVEAU_BO_RD; +	if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) +		map_flags |= NOUVEAU_BO_WR; + +	if (nouveau_bo_map(nvbuf->bo, map_flags)) +		return NULL; +	return nvbuf->bo->map; +} + +static void +nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) +{ +	struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf); + +	nouveau_bo_unmap(nvbuf->bo); +} + +static INLINE struct nouveau_fence * +nouveau_pipe_fence(struct pipe_fence_handle *pfence) +{ +	return (struct nouveau_fence *)pfence; +} + +static void +nouveau_pipe_fence_reference(struct pipe_winsys *ws, +			     struct pipe_fence_handle **ptr, +			     struct pipe_fence_handle *pfence) +{ +	nouveau_fence_ref((void *)pfence, (void *)ptr); +} + +static int +nouveau_pipe_fence_signalled(struct pipe_winsys *ws, +			     struct pipe_fence_handle *pfence, unsigned flag) +{ +	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)ws; +	struct nouveau_fence *fence = nouveau_pipe_fence(pfence); + +	if (nouveau_fence(fence)->signalled == 0) +		nouveau_fence_flush(nvpws->nv->nvc->channel); + +	return !nouveau_fence(fence)->signalled; +} + +static int +nouveau_pipe_fence_finish(struct pipe_winsys *ws, +			  struct pipe_fence_handle *pfence, unsigned flag) +{ +	struct nouveau_fence *fence = nouveau_pipe_fence(pfence); +	struct nouveau_fence *ref = NULL; + +	nouveau_fence_ref(fence, &ref); +	return nouveau_fence_wait(&ref); +} + +struct pipe_winsys * +nouveau_create_pipe_winsys(struct nouveau_context *nv) +{ +	struct nouveau_pipe_winsys *nvpws; +	struct pipe_winsys *pws; + +	nvpws = CALLOC_STRUCT(nouveau_pipe_winsys); +	if (!nvpws) +		return NULL; +	nvpws->nv = nv; +	pws = &nvpws->pws; + +	pws->flush_frontbuffer = nouveau_flush_frontbuffer; + +	pws->buffer_create = nouveau_pipe_bo_create; +	pws->buffer_destroy = nouveau_pipe_bo_del; +	pws->user_buffer_create = nouveau_pipe_bo_user_create; +	pws->buffer_map = nouveau_pipe_bo_map; +	pws->buffer_unmap = nouveau_pipe_bo_unmap; + +	pws->fence_reference = nouveau_pipe_fence_reference; +	pws->fence_signalled = nouveau_pipe_fence_signalled; +	pws->fence_finish = nouveau_pipe_fence_finish; + +	pws->get_name = nouveau_get_name; + +	return &nvpws->pws; +} + diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.h b/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.h new file mode 100644 index 0000000000..6a03ac0d77 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.h @@ -0,0 +1,34 @@ +#ifndef NOUVEAU_PIPE_WINSYS_H +#define NOUVEAU_PIPE_WINSYS_H + +#include "pipe/p_context.h" +#include "pipe/p_winsys.h" +#include "nouveau_context.h" + +struct nouveau_pipe_buffer { +	struct pipe_buffer base; +	struct nouveau_bo *bo; +}; + +static inline struct nouveau_pipe_buffer * +nouveau_buffer(struct pipe_buffer *buf) +{ +	return (struct nouveau_pipe_buffer *)buf; +} + +struct nouveau_pipe_winsys { +	struct pipe_winsys pws; + +	struct nouveau_context *nv; +}; + +extern struct pipe_winsys * +nouveau_create_pipe_winsys(struct nouveau_context *nv); + +struct pipe_context * +nouveau_create_softpipe(struct nouveau_context *nv); + +struct pipe_context * +nouveau_pipe_create(struct nouveau_context *nv); + +#endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys_softpipe.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys_softpipe.c new file mode 100644 index 0000000000..704f6c7750 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys_softpipe.c @@ -0,0 +1,85 @@ +/************************************************************************** + *  + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA + * 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, 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 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 + * THE COPYRIGHT HOLDERS, AUTHORS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + *  + **************************************************************************/ +/* + * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> + */ + +#include "imports.h" + +#include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "softpipe/sp_winsys.h" + +#include "nouveau_context.h" +#include "nouveau_winsys_pipe.h" + +struct nouveau_softpipe_winsys { +   struct softpipe_winsys sws; +   struct nouveau_context *nv; +}; + +/** + * Return list of surface formats supported by this driver. + */ +static boolean +nouveau_is_format_supported(struct softpipe_winsys *sws, uint format) +{ +	switch (format) { +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case PIPE_FORMAT_R5G6B5_UNORM: +	case PIPE_FORMAT_Z24S8_UNORM: +		return TRUE; +	default: +		break; +	}; + +	return FALSE; +} + +struct pipe_context * +nouveau_create_softpipe(struct nouveau_context *nv) +{ +	struct nouveau_softpipe_winsys *nvsws; +	struct pipe_screen *pscreen; +	struct pipe_winsys *ws; + +	ws = nouveau_create_pipe_winsys(nv); +	if (!ws) +		return NULL; +	pscreen = softpipe_create_screen(ws); + +	nvsws = CALLOC_STRUCT(nouveau_softpipe_winsys); +	if (!nvsws) +		return NULL; + +	nvsws->sws.is_format_supported = nouveau_is_format_supported; +	nvsws->nv = nv; + +	return softpipe_create(pscreen, ws, &nvsws->sws); +} + diff --git a/src/gallium/winsys/dri/nouveau/nv04_surface.c b/src/gallium/winsys/dri/nouveau/nv04_surface.c new file mode 100644 index 0000000000..0085b1c345 --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nv04_surface.c @@ -0,0 +1,310 @@ +#include "pipe/p_context.h" +#include "pipe/p_format.h" + +#include "nouveau_context.h" + +static INLINE int +nv04_surface_format(enum pipe_format format) +{ +	switch (format) { +	case PIPE_FORMAT_A8_UNORM: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8; +	case PIPE_FORMAT_R5G6B5_UNORM: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5; +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case PIPE_FORMAT_Z24S8_UNORM: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32; +	default: +		return -1; +	} +} + +static INLINE int +nv04_rect_format(enum pipe_format format) +{ +	switch (format) { +	case PIPE_FORMAT_A8_UNORM: +		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; +	case PIPE_FORMAT_R5G6B5_UNORM: +		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5; +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case PIPE_FORMAT_Z24S8_UNORM: +		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; +	default: +		return -1; +	} +} + +static void +nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy, +		       unsigned sx, unsigned sy, unsigned w, unsigned h) +{ +	struct nouveau_channel *chan = nv->nvc->channel; +	struct pipe_surface *dst = nv->surf_dst; +	struct pipe_surface *src = nv->surf_src; +	unsigned dst_offset, src_offset; + +	dst_offset = dst->offset + (dy * dst->stride) + (dx * dst->block.size); +	src_offset = src->offset + (sy * src->stride) + (sx * src->block.size); + +	while (h) { +		int count = (h > 2047) ? 2047 : h; + +		BEGIN_RING(chan, nv->nvc->NvM2MF, +			   NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); +		OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src_offset, +			   NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); +		OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst_offset, +			   NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR); +		OUT_RING  (chan, src->stride); +		OUT_RING  (chan, dst->stride); +		OUT_RING  (chan, w * src->block.size); +		OUT_RING  (chan, count); +		OUT_RING  (chan, 0x0101); +		OUT_RING  (chan, 0); + +		h -= count; +		src_offset += src->stride * count; +		dst_offset += dst->stride * count; +	} +} + +static void +nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy, +		       unsigned sx, unsigned sy, unsigned w, unsigned h) +{ +	struct nouveau_channel *chan = nv->nvc->channel; + +	BEGIN_RING(chan, nv->nvc->NvImageBlit, 0x0300, 3); +	OUT_RING  (chan, (sy << 16) | sx); +	OUT_RING  (chan, (dy << 16) | dx); +	OUT_RING  (chan, ( h << 16) |  w); +} + +static int +nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst, +		       struct pipe_surface *src) +{ +	struct nouveau_channel *chan = nv->nvc->channel; +	int format; + +	if (src->format != dst->format) +		return 1; + +	/* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback +	 * to NV_MEMORY_TO_MEMORY_FORMAT in this case. +	 */ +	if ((src->offset & 63) || (dst->offset & 63)) { +		BEGIN_RING(nv->nvc->channel, nv->nvc->NvM2MF, +			   NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); +		OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo, +			   NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +		OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo, +			   NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +		nv->surface_copy = nv04_surface_copy_m2mf; +		nv->surf_dst = dst; +		nv->surf_src = src; +		return 0; + +	} + +	if ((format = nv04_surface_format(dst->format)) < 0) { +		NOUVEAU_ERR("Bad surface format 0x%x\n", dst->format); +		return 1; +	} +	nv->surface_copy = nv04_surface_copy_blit; + +	BEGIN_RING(chan, nv->nvc->NvCtxSurf2D, +		   NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2); +	OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +	OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	BEGIN_RING(chan, nv->nvc->NvCtxSurf2D, +		   NV04_CONTEXT_SURFACES_2D_FORMAT, 4); +	OUT_RING  (chan, format); +	OUT_RING  (chan, (dst->stride << 16) | src->stride); +	OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src->offset, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +	OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	return 0; +} + +static void +nv04_surface_copy_done(struct nouveau_context *nv) +{ +	FIRE_RING(nv->nvc->channel); +} + +static int +nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst, +		  unsigned dx, unsigned dy, unsigned w, unsigned h, +		  unsigned value) +{ +	struct nouveau_channel *chan = nv->nvc->channel; +	struct nouveau_grobj *surf2d = nv->nvc->NvCtxSurf2D; +	struct nouveau_grobj *rect = nv->nvc->NvGdiRect; +	int cs2d_format, gdirect_format; + +	if ((cs2d_format = nv04_surface_format(dst->format)) < 0) { +		NOUVEAU_ERR("Bad format = %d\n", dst->format); +		return 1; +	} + +	if ((gdirect_format = nv04_rect_format(dst->format)) < 0) { +		NOUVEAU_ERR("Bad format = %d\n", dst->format); +		return 1; +	} + +	BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2); +	OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4); +	OUT_RING  (chan, cs2d_format); +	OUT_RING  (chan, (dst->stride << 16) | dst->stride); +	OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset, +		   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1); +	OUT_RING  (chan, gdirect_format); +	BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1); +	OUT_RING  (chan, value); +	BEGIN_RING(chan, rect, +		   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2); +	OUT_RING  (chan, (dx << 16) | dy); +	OUT_RING  (chan, ( w << 16) |  h); + +	FIRE_RING(chan); +	return 0; +} + +int +nouveau_surface_channel_create_nv04(struct nouveau_channel_context *nvc) +{ +	struct nouveau_channel *chan = nvc->channel; +	unsigned chipset = nvc->channel->device->chipset, class; +	int ret; + +	if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, 0x39, +				       &nvc->NvM2MF))) { +		NOUVEAU_ERR("Error creating m2mf object: %d\n", ret); +		return 1; +	} +	BIND_RING (chan, nvc->NvM2MF, nvc->next_subchannel++); +	BEGIN_RING(chan, nvc->NvM2MF, +		   NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); +	OUT_RING  (chan, nvc->sync_notifier->handle); + +	class = chipset < 0x10 ? NV04_CONTEXT_SURFACES_2D : +				 NV10_CONTEXT_SURFACES_2D; +	if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class, +				       &nvc->NvCtxSurf2D))) { +		NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret); +		return 1; +	} +	BIND_RING (chan, nvc->NvCtxSurf2D, nvc->next_subchannel++); +	BEGIN_RING(chan, nvc->NvCtxSurf2D, +		   NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2); +	OUT_RING  (chan, nvc->channel->vram->handle); +	OUT_RING  (chan, nvc->channel->vram->handle); + +	class = chipset < 0x10 ? NV04_IMAGE_BLIT : NV12_IMAGE_BLIT; +	if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class, +				       &nvc->NvImageBlit))) { +		NOUVEAU_ERR("Error creating blit object: %d\n", ret); +		return 1; +	} +	BIND_RING (chan, nvc->NvImageBlit, nvc->next_subchannel++); +	BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1); +	OUT_RING  (chan, nvc->sync_notifier->handle); +	BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_SURFACE, 1); +	OUT_RING  (chan, nvc->NvCtxSurf2D->handle); +	BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1); +	OUT_RING  (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY); + +	class = NV04_GDI_RECTANGLE_TEXT; +	if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class, +				       &nvc->NvGdiRect))) { +		NOUVEAU_ERR("Error creating rect object: %d\n", ret); +		return 1; +	} +	BIND_RING (chan, nvc->NvGdiRect, nvc->next_subchannel++); +	BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1); +	OUT_RING  (chan, nvc->sync_notifier->handle); +	BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1); +	OUT_RING  (chan, nvc->NvCtxSurf2D->handle); +	BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1); +	OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY); +	BEGIN_RING(chan, nvc->NvGdiRect, +		   NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1); +	OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE); + +	switch (chipset & 0xf0) { +	case 0x00: +	case 0x10: +		class = NV04_SWIZZLED_SURFACE; +		break; +	case 0x20: +		class = NV20_SWIZZLED_SURFACE; +		break; +	case 0x30: +		class = NV30_SWIZZLED_SURFACE; +		break; +	case 0x40: +	case 0x60: +		class = NV40_SWIZZLED_SURFACE; +		break; +	default: +		/* Famous last words: this really can't happen.. */ +		assert(0); +		break; +	} + +	ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class, +				  &nvc->NvSwzSurf); +	if (ret) { +		NOUVEAU_ERR("Error creating swizzled surface: %d\n", ret); +		return 1; +	} + +	BIND_RING (chan, nvc->NvSwzSurf, nvc->next_subchannel++); + +	if (chipset < 0x10) { +		class = NV04_SCALED_IMAGE_FROM_MEMORY; +	} else +	if (chipset < 0x40) { +		class = NV10_SCALED_IMAGE_FROM_MEMORY; +	} else { +		class = NV40_SCALED_IMAGE_FROM_MEMORY; +	} + +	ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class, +				  &nvc->NvSIFM); +	if (ret) { +		NOUVEAU_ERR("Error creating scaled image object: %d\n", ret); +		return 1; +	} + +	BIND_RING (chan, nvc->NvSIFM, nvc->next_subchannel++); + +	return 0; +} + +int +nouveau_surface_init_nv04(struct nouveau_context *nv) +{ +	nv->surface_copy_prep = nv04_surface_copy_prep; +	nv->surface_copy = nv04_surface_copy_blit; +	nv->surface_copy_done = nv04_surface_copy_done; +	nv->surface_fill = nv04_surface_fill; +	return 0; +} + diff --git a/src/gallium/winsys/dri/nouveau/nv50_surface.c b/src/gallium/winsys/dri/nouveau/nv50_surface.c new file mode 100644 index 0000000000..c8ab7f690f --- /dev/null +++ b/src/gallium/winsys/dri/nouveau/nv50_surface.c @@ -0,0 +1,194 @@ +#include "pipe/p_context.h" +#include "pipe/p_format.h" + +#include "nouveau_context.h" + +static INLINE int +nv50_format(enum pipe_format format) +{ +	switch (format) { +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case PIPE_FORMAT_Z24S8_UNORM: +		return NV50_2D_DST_FORMAT_32BPP; +	case PIPE_FORMAT_X8R8G8B8_UNORM: +		return NV50_2D_DST_FORMAT_24BPP; +	case PIPE_FORMAT_R5G6B5_UNORM: +		return NV50_2D_DST_FORMAT_16BPP; +	case PIPE_FORMAT_A8_UNORM: +		return NV50_2D_DST_FORMAT_8BPP; +	default: +		return -1; +	} +} + +static int +nv50_surface_set(struct nouveau_context *nv, struct pipe_surface *surf, int dst) +{ +	struct nouveau_channel *chan = nv->nvc->channel; +	struct nouveau_grobj *eng2d = nv->nvc->Nv2D; + 	struct nouveau_bo *bo = nouveau_buffer(surf->buffer)->bo; + 	int surf_format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT; + 	int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD); +   + 	surf_format = nv50_format(surf->format); + 	if (surf_format < 0) + 		return 1; +   + 	if (!nouveau_bo(bo)->tiled) { + 		BEGIN_RING(chan, eng2d, mthd, 2); + 		OUT_RING  (chan, surf_format); + 		OUT_RING  (chan, 1); + 		BEGIN_RING(chan, eng2d, mthd + 0x14, 5); + 		OUT_RING  (chan, surf->stride); + 		OUT_RING  (chan, surf->width); + 		OUT_RING  (chan, surf->height); + 		OUT_RELOCh(chan, bo, surf->offset, flags); + 		OUT_RELOCl(chan, bo, surf->offset, flags); + 	} else { + 		BEGIN_RING(chan, eng2d, mthd, 5); + 		OUT_RING  (chan, surf_format); + 		OUT_RING  (chan, 0); + 		OUT_RING  (chan, 0); + 		OUT_RING  (chan, 1); + 		OUT_RING  (chan, 0); + 		BEGIN_RING(chan, eng2d, mthd + 0x18, 4); + 		OUT_RING  (chan, surf->width); + 		OUT_RING  (chan, surf->height); + 		OUT_RELOCh(chan, bo, surf->offset, flags); + 		OUT_RELOCl(chan, bo, surf->offset, flags); + 	} +  +#if 0 + 	if (dst) { + 		BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4); + 		OUT_RING  (chan, 0); + 		OUT_RING  (chan, 0); + 		OUT_RING  (chan, surf->width); + 		OUT_RING  (chan, surf->height); + 	} +#endif +   + 	return 0; +} + +static int +nv50_surface_copy_prep(struct nouveau_context *nv, +		       struct pipe_surface *dst, struct pipe_surface *src) +{ +	int ret; + +	assert(src->format == dst->format); + +	ret = nv50_surface_set(nv, dst, 1); +	if (ret) +		return ret; + +	ret = nv50_surface_set(nv, src, 0); +	if (ret) +		return ret; + +	return 0; +} + +static void +nv50_surface_copy(struct nouveau_context *nv, unsigned dx, unsigned dy, +		  unsigned sx, unsigned sy, unsigned w, unsigned h) +{ +	struct nouveau_channel *chan = nv->nvc->channel; +	struct nouveau_grobj *eng2d = nv->nvc->Nv2D; + +	BEGIN_RING(chan, eng2d, 0x088c, 1); +	OUT_RING  (chan, 0); +	BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4); +	OUT_RING  (chan, dx); +	OUT_RING  (chan, dy); +	OUT_RING  (chan, w); +	OUT_RING  (chan, h); +	BEGIN_RING(chan, eng2d, 0x08c0, 4); +	OUT_RING  (chan, 0); +	OUT_RING  (chan, 1); +	OUT_RING  (chan, 0); +	OUT_RING  (chan, 1); +	BEGIN_RING(chan, eng2d, 0x08d0, 4); +	OUT_RING  (chan, 0); +	OUT_RING  (chan, sx); +	OUT_RING  (chan, 0); +	OUT_RING  (chan, sy); +} + +static void +nv50_surface_copy_done(struct nouveau_context *nv) +{ +	FIRE_RING(nv->nvc->channel); +} + +static int +nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst, +		  unsigned dx, unsigned dy, unsigned w, unsigned h, +		  unsigned value) +{ +	struct nouveau_channel *chan = nv->nvc->channel; +	struct nouveau_grobj *eng2d = nv->nvc->Nv2D; +	int rect_format, ret; + +	rect_format = nv50_format(dst->format); +	if (rect_format < 0) +		return 1; + +	ret = nv50_surface_set(nv, dst, 1); +	if (ret) +		return ret; + +	BEGIN_RING(chan, eng2d, 0x0580, 3); +	OUT_RING  (chan, 4); +	OUT_RING  (chan, rect_format); +	OUT_RING  (chan, value); + +	BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4); +	OUT_RING  (chan, dx); +	OUT_RING  (chan, dy); +	OUT_RING  (chan, dx + w); +	OUT_RING  (chan, dy + h); + +	FIRE_RING(chan); +	return 0; +} + +int +nouveau_surface_channel_create_nv50(struct nouveau_channel_context *nvc) +{ +	struct nouveau_channel *chan = nvc->channel; +	struct nouveau_grobj *eng2d = NULL; +	int ret; + +	ret = nouveau_grobj_alloc(chan, nvc->next_handle++, NV50_2D, &eng2d); +	if (ret) +		return ret; +	nvc->Nv2D = eng2d; + +	BIND_RING (chan, eng2d, nvc->next_subchannel++); +	BEGIN_RING(chan, eng2d, NV50_2D_DMA_NOTIFY, 4); +	OUT_RING  (chan, nvc->sync_notifier->handle); +	OUT_RING  (chan, chan->vram->handle); +	OUT_RING  (chan, chan->vram->handle); +	OUT_RING  (chan, chan->vram->handle); +	BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1); +	OUT_RING  (chan, NV50_2D_OPERATION_SRCCOPY); +	BEGIN_RING(chan, eng2d, 0x0290, 1); +	OUT_RING  (chan, 0); +	BEGIN_RING(chan, eng2d, 0x0888, 1); +	OUT_RING  (chan, 1); + +	return 0; +} + +int +nouveau_surface_init_nv50(struct nouveau_context *nv) +{ +	nv->surface_copy_prep = nv50_surface_copy_prep; +	nv->surface_copy = nv50_surface_copy; +	nv->surface_copy_done = nv50_surface_copy_done; +	nv->surface_fill = nv50_surface_fill; +	return 0; +} + diff --git a/src/gallium/winsys/g3dvl/nouveau/Makefile b/src/gallium/winsys/g3dvl/nouveau/Makefile new file mode 100644 index 0000000000..2861bd7db4 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/Makefile @@ -0,0 +1,48 @@ +TARGET		= libnouveau_dri.so +GALLIUMDIR	= ../../.. +DRMDIR		?= /usr +DRIDIR		= ../../../../driclient + +OBJECTS		= nouveau_bo.o nouveau_fence.o nouveau_swapbuffers.o nouveau_channel.o		\ +		  nouveau_grobj.o nouveau_context.o nouveau_winsys.o nouveau_lock.o		\ +		  nouveau_winsys_pipe.o nouveau_device.o nouveau_notifier.o nouveau_dma.o	\ +		  nouveau_pushbuf.o nouveau_resource.o nouveau_screen.o nv04_surface.o		\ +		  nv50_surface.o #nouveau_winsys_softpipe.o + +CFLAGS		+= -g -Wall -Werror -fPIC		\ +		   -I${GALLIUMDIR}/include		\ +		   -I${GALLIUMDIR}/winsys/g3dvl		\ +		   -I${DRMDIR}/include			\ +		   -I${DRMDIR}/include/drm		\ +		   -I${GALLIUMDIR}/drivers		\ +		   -I${GALLIUMDIR}/auxiliary		\ +		   -I${DRIDIR}/include + +LDFLAGS		+= -L${DRMDIR}/lib			\ +		   -L${DRIDIR}/lib			\ +		   -L${GALLIUMDIR}/auxiliary/draw	\ +		   -L${GALLIUMDIR}/auxiliary/tgsi	\ +		   -L${GALLIUMDIR}/auxiliary/translate	\ +		   -L${GALLIUMDIR}/auxiliary/rtasm	\ +		   -L${GALLIUMDIR}/auxiliary/cso_cache	\ +		   -L${GALLIUMDIR}/drivers/nv10		\ +		   -L${GALLIUMDIR}/drivers/nv30		\ +		   -L${GALLIUMDIR}/drivers/nv40		\ +		   -L${GALLIUMDIR}/drivers/nv50 + +LIBS		+= -ldriclient -ldrm -lnv10 -lnv30 -lnv40 -lnv50 -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lm + +############################################# + +.PHONY	= all clean + +all: ${TARGET} + +${TARGET}: ${OBJECTS} +	cd ${DRIDIR}/src; ${MAKE} +	$(CC) ${LDFLAGS} -shared -o $@ $^ ${LIBS} + +clean: +	cd ${DRIDIR}/src; ${MAKE} clean +	rm -rf ${OBJECTS} ${TARGET} + diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_bo.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_bo.c new file mode 120000 index 0000000000..73ac4a4171 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_bo.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_bo.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_channel.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_channel.c new file mode 120000 index 0000000000..6c9b2c48d8 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_channel.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_channel.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_context.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.c new file mode 100644 index 0000000000..5e173c7672 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.c @@ -0,0 +1,371 @@ +#include "pipe/p_defines.h" +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_util.h" + +#include "nouveau_context.h" +#include "nouveau_dri.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_winsys_pipe.h" + +/* +#ifdef DEBUG +static const struct dri_debug_control debug_control[] = { +	{ "bo", DEBUG_BO }, +	{ NULL, 0 } +}; +int __nouveau_debug = 0; +#endif +*/ + +/* + * TODO: Re-examine dri_screen, dri_context, nouveau_screen, nouveau_context + * relationships, seems like there is a lot of room for simplification there. + */ + +static void +nouveau_channel_context_destroy(struct nouveau_channel_context *nvc) +{ +	nouveau_grobj_free(&nvc->NvCtxSurf2D); +	nouveau_grobj_free(&nvc->NvImageBlit); +	nouveau_grobj_free(&nvc->NvGdiRect); +	nouveau_grobj_free(&nvc->NvM2MF); +	nouveau_grobj_free(&nvc->Nv2D); +	nouveau_grobj_free(&nvc->NvSwzSurf); +	nouveau_grobj_free(&nvc->NvSIFM); + +	nouveau_notifier_free(&nvc->sync_notifier); + +	nouveau_channel_free(&nvc->channel); + +	FREE(nvc); +} + +static struct nouveau_channel_context * +nouveau_channel_context_create(struct nouveau_device *dev) +{ +	struct nouveau_channel_context *nvc; +	int ret; + +	nvc = CALLOC_STRUCT(nouveau_channel_context); +	if (!nvc) +		return NULL; + +	if ((ret = nouveau_channel_alloc(dev, 0x8003d001, 0x8003d002, +					 &nvc->channel))) { +		NOUVEAU_ERR("Error creating GPU channel: %d\n", ret); +		nouveau_channel_context_destroy(nvc); +		return NULL; +	} + +	nvc->next_handle = 0x80000000; + +	if ((ret = nouveau_notifier_alloc(nvc->channel, nvc->next_handle++, 1, +					  &nvc->sync_notifier))) { +		NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret); +		nouveau_channel_context_destroy(nvc); +		return NULL; +	} + +	switch (dev->chipset & 0xf0) { +	case 0x50: +	case 0x80: +	case 0x90: +		ret = nouveau_surface_channel_create_nv50(nvc); +		break; +	default: +		ret = nouveau_surface_channel_create_nv04(nvc); +		break; +	} + +	if (ret) { +		NOUVEAU_ERR("Error initialising surface objects: %d\n", ret); +		nouveau_channel_context_destroy(nvc); +		return NULL; +	} + +	return nvc; +} + +int +nouveau_context_create(dri_context_t *dri_context) +{ +	dri_screen_t			*dri_screen = dri_context->dri_screen; +	struct nouveau_screen 		*nv_screen = dri_screen->private; +	struct nouveau_context		*nv = CALLOC_STRUCT(nouveau_context); +	struct pipe_context		*pipe = NULL; +	struct nouveau_channel_context	*nvc = NULL; +	struct nouveau_device		*dev = nv_screen->device; +	int				i; + +	switch (dev->chipset & 0xf0) { +	case 0x10: +	case 0x20: +		/* NV10 */ +	case 0x30: +		/* NV30 */ +	case 0x40: +	case 0x60: +		/* NV40 */ +	case 0x50: +	case 0x80: +	case 0x90: +		/* G80 */ +		break; +	default: +		NOUVEAU_ERR("Unsupported chipset: NV%02x\n", dev->chipset); +		return 1; +	} + +	dri_context->private = (void*)nv; +	nv->dri_context = dri_context; +	nv->nv_screen  = nv_screen; + +	{ +		struct nouveau_device_priv *nvdev = nouveau_device(dev); + +		nvdev->ctx  = dri_context->drm_context; +		nvdev->lock = (drmLock*)&dri_screen->sarea->lock; +	} + +	/* +	driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache, +			    nv->dri_screen->myNum, "nouveau"); +#ifdef DEBUG +	__nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"), +					      debug_control); +#endif +	*/ + +	/*XXX: Hack up a fake region and buffer object for front buffer. +	 *     This will go away with TTM, replaced with a simple reference +	 *     of the front buffer handle passed to us by the DDX. +	 */ +	{ +		struct pipe_surface *fb_surf; +		struct nouveau_pipe_buffer *fb_buf; +		struct nouveau_bo_priv *fb_bo; + +		fb_bo = calloc(1, sizeof(struct nouveau_bo_priv)); +		fb_bo->drm.offset = nv_screen->front_offset; +		fb_bo->drm.flags = NOUVEAU_MEM_FB; +		fb_bo->drm.size = nv_screen->front_pitch *  +				  nv_screen->front_height; +		fb_bo->refcount = 1; +		fb_bo->base.flags = NOUVEAU_BO_PIN | NOUVEAU_BO_VRAM; +		fb_bo->base.offset = fb_bo->drm.offset; +		fb_bo->base.handle = (unsigned long)fb_bo; +		fb_bo->base.size = fb_bo->drm.size; +		fb_bo->base.device = nv_screen->device; + +		fb_buf = calloc(1, sizeof(struct nouveau_pipe_buffer)); +		fb_buf->bo = &fb_bo->base; + +		fb_surf = calloc(1, sizeof(struct pipe_surface)); +		if (nv_screen->front_cpp == 2) +			fb_surf->format = PIPE_FORMAT_R5G6B5_UNORM; +		else +			fb_surf->format = PIPE_FORMAT_A8R8G8B8_UNORM; +		pf_get_block(fb_surf->format, &fb_surf->block); +		fb_surf->width = nv_screen->front_pitch / nv_screen->front_cpp; +		fb_surf->height = nv_screen->front_height; +		fb_surf->stride = fb_surf->width * fb_surf->block.size; +		fb_surf->refcount = 1; +		fb_surf->buffer = &fb_buf->base; + +		nv->frontbuffer = fb_surf; +	} + +	nvc = nv_screen->nvc; + +	if (!nvc) { +		nvc = nouveau_channel_context_create(dev); +		if (!nvc) { +			NOUVEAU_ERR("Failed initialising GPU context\n"); +			return 1; +		} +		nv_screen->nvc = nvc; +	} + +	nvc->refcount++; +	nv->nvc = nvc; + +	/* Find a free slot for a pipe context, allocate a new one if needed */ +	nv->pctx_id = -1; +	for (i = 0; i < nvc->nr_pctx; i++) { +		if (nvc->pctx[i] == NULL) { +			nv->pctx_id = i; +			break; +		} +	} + +	if (nv->pctx_id < 0) { +		nv->pctx_id = nvc->nr_pctx++; +		nvc->pctx = +			realloc(nvc->pctx, +				sizeof(struct pipe_context *) * nvc->nr_pctx); +	} + +	/* Create pipe */ +	switch (dev->chipset & 0xf0) { +	case 0x50: +	case 0x80: +	case 0x90: +		if (nouveau_surface_init_nv50(nv)) +			return 1; +		break; +	default: +		if (nouveau_surface_init_nv04(nv)) +			return 1; +		break; +	} + +	if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) { +		struct pipe_screen *pscreen; + +		pipe = nouveau_pipe_create(nv); +		if (!pipe) +			NOUVEAU_ERR("Couldn't create hw pipe\n"); +		pscreen = nvc->pscreen; + +		nv->cap.hw_vertex_buffer = +			pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF); +		nv->cap.hw_index_buffer = +			pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF); +	} + +	/* XXX: nouveau_winsys_softpipe needs a mesa header removed before we can compile it. */ +	/* +	if (!pipe) { +		NOUVEAU_MSG("Using softpipe\n"); +		pipe = nouveau_create_softpipe(nv); +		if (!pipe) { +			NOUVEAU_ERR("Error creating pipe, bailing\n"); +			return 1; +		} +	} +	*/ +	if (!pipe) { +		NOUVEAU_ERR("Error creating pipe, bailing\n"); +		return 1; +	} + +	pipe->priv = nv; + +	return 0; +} + +void +nouveau_context_destroy(dri_context_t *dri_context) +{ +	struct nouveau_context *nv = dri_context->private; +	struct nouveau_channel_context *nvc = nv->nvc; + +	assert(nv); + +	if (nv->pctx_id >= 0) { +		nvc->pctx[nv->pctx_id] = NULL; +		if (--nvc->refcount <= 0) { +			nouveau_channel_context_destroy(nvc); +			nv->nv_screen->nvc = NULL; +		} +	} + +	free(nv); +} + +int +nouveau_context_bind(struct nouveau_context *nv, dri_drawable_t *dri_drawable) +{ +	assert(nv); +	assert(dri_drawable); +	 +	if (nv->dri_drawable != dri_drawable) +	{ +		nv->dri_drawable = dri_drawable; +		dri_drawable->private = nv; +	} + +	return 0; +} + +int +nouveau_context_unbind(struct nouveau_context *nv) +{ +	assert(nv); +	 +	nv->dri_drawable = NULL; +	 +	return 0; +} + +/* Show starts here */ + +int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable) +{ +	struct nouveau_context	*nv; +	dri_drawable_t		*dri_drawable; +	 +	nv = pipe->priv; +	 +	driCreateDrawable(nv->nv_screen->dri_screen, drawable, &dri_drawable); +	 +	nouveau_context_bind(nv, dri_drawable); +	 +	return 0; +} + +int unbind_pipe_drawable(struct pipe_context *pipe) +{ +	nouveau_context_unbind(pipe->priv); +	 +	return 0; +} + +struct pipe_context* create_pipe_context(Display *display, int screen) +{ +	dri_screen_t		*dri_screen; +	dri_framebuffer_t	dri_framebuf; +	dri_context_t		*dri_context; +	struct nouveau_context	*nv; +	 +	driCreateScreen(display, screen, &dri_screen, &dri_framebuf); +	driCreateContext(dri_screen, XDefaultVisual(display, screen), &dri_context); +	 +	nouveau_screen_create(dri_screen, &dri_framebuf); +	nouveau_context_create(dri_context); +	 +	nv = dri_context->private; +	 +	return nv->nvc->pctx[nv->pctx_id]; +} + +int destroy_pipe_context(struct pipe_context *pipe) +{ +	struct pipe_screen	*screen; +	struct pipe_winsys	*winsys; +	struct nouveau_context	*nv; +	dri_screen_t		*dri_screen; +	dri_context_t		*dri_context; +	 +	assert(pipe); +	 +	screen = pipe->screen; +	winsys = pipe->winsys; +	nv = pipe->priv; +	dri_context = nv->dri_context; +	dri_screen = dri_context->dri_screen; +	 +	pipe->destroy(pipe); +	screen->destroy(screen); +	free(winsys); + +	nouveau_context_destroy(dri_context); +	nouveau_screen_destroy(dri_screen); +	driDestroyContext(dri_context); +	driDestroyScreen(dri_screen); +	 +	return 0; +} + diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_context.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.h new file mode 100644 index 0000000000..395a3ab790 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.h @@ -0,0 +1,105 @@ +#ifndef __NOUVEAU_CONTEXT_H__ +#define __NOUVEAU_CONTEXT_H__ + +/*#include "xmlconfig.h"*/ + +#include <driclient.h> +#include "nouveau/nouveau_winsys.h" +#include "nouveau_drmif.h" +#include "nouveau_dma.h" + +struct nouveau_channel_context { +	struct pipe_screen *pscreen; +	int refcount; + +	unsigned cur_pctx; +	unsigned nr_pctx; +	struct pipe_context **pctx; + +	struct nouveau_channel  *channel; + +	struct nouveau_notifier *sync_notifier; + +	/* Common */ +	struct nouveau_grobj    *NvM2MF; +	/* NV04-NV40 */ +	struct nouveau_grobj    *NvCtxSurf2D; +	struct nouveau_grobj	*NvSwzSurf; +	struct nouveau_grobj    *NvImageBlit; +	struct nouveau_grobj    *NvGdiRect; +	struct nouveau_grobj	*NvSIFM; +	/* G80 */ +	struct nouveau_grobj    *Nv2D; + +	uint32_t                 next_handle; +	uint32_t                 next_subchannel; +	uint32_t                 next_sequence; +}; + +struct nouveau_context { +	/* DRI stuff */ +	dri_context_t		*dri_context; +	dri_drawable_t		*dri_drawable; +	unsigned int		last_stamp; +	/*driOptionCache	dri_option_cache;*/ +	drm_context_t		drm_context; +	drmLock			drm_lock; +	int			locked; +	struct nouveau_screen	*nv_screen; +	struct pipe_surface	*frontbuffer; + +	struct { +		int hw_vertex_buffer; +		int hw_index_buffer; +	} cap; + +	/* Hardware context */ +	struct nouveau_channel_context	*nvc; +	int				pctx_id; + +	/* pipe_surface accel */ +	struct pipe_surface		*surf_src, *surf_dst; +	unsigned			surf_src_offset, surf_dst_offset; +	 +	int  (*surface_copy_prep)(struct nouveau_context *, +				  struct pipe_surface *dst, +				  struct pipe_surface *src); +	void (*surface_copy)(struct nouveau_context *, unsigned dx, unsigned dy, +			     unsigned sx, unsigned sy, unsigned w, unsigned h); +	void (*surface_copy_done)(struct nouveau_context *); +	int (*surface_fill)(struct nouveau_context *, struct pipe_surface *, +			    unsigned, unsigned, unsigned, unsigned, unsigned); +}; + +extern int nouveau_context_create(dri_context_t *); +extern void nouveau_context_destroy(dri_context_t *); +extern int nouveau_context_bind(struct nouveau_context *, dri_drawable_t *); +extern int nouveau_context_unbind(struct nouveau_context *); + +#ifdef DEBUG +extern int __nouveau_debug; + +#define DEBUG_BO (1 << 0) + +#define DBG(flag, ...) do {                   \ +	if (__nouveau_debug & (DEBUG_##flag)) \ +		NOUVEAU_ERR(__VA_ARGS__);     \ +} while(0) +#else +#define DBG(flag, ...) +#endif + +extern void LOCK_HARDWARE(struct nouveau_context *); +extern void UNLOCK_HARDWARE(struct nouveau_context *); + +extern int +nouveau_surface_channel_create_nv04(struct nouveau_channel_context *); +extern int +nouveau_surface_channel_create_nv50(struct nouveau_channel_context *); +extern int nouveau_surface_init_nv04(struct nouveau_context *); +extern int nouveau_surface_init_nv50(struct nouveau_context *); + +extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int); +extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *); + +#endif diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_device.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_device.c new file mode 120000 index 0000000000..47d52dafa8 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_device.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_device.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.c new file mode 120000 index 0000000000..45078c964f --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_dma.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.h new file mode 120000 index 0000000000..6b9ec77741 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.h @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_dma.h
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_dri.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_dri.h new file mode 120000 index 0000000000..0e6c9fce35 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_dri.h @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_dri.h
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_drmif.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_drmif.h new file mode 120000 index 0000000000..473b7d4812 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_drmif.h @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_drmif.h
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_fence.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_fence.c new file mode 120000 index 0000000000..ef1f0c6afe --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_fence.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_fence.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_grobj.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_grobj.c new file mode 120000 index 0000000000..428186544c --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_grobj.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_grobj.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_local.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_local.h new file mode 120000 index 0000000000..6b878aad22 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_local.h @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_local.h
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_lock.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_lock.c new file mode 100644 index 0000000000..375634bd05 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_lock.c @@ -0,0 +1,92 @@ +/************************************************************************** + *  + * Copyright 2003 Tungsten Graphics, 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, 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 TUNGSTEN GRAPHICS 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. + *  + **************************************************************************/ + +#include <pthread.h> +#include <driclient.h> +#include "nouveau_context.h" +#include "nouveau_screen.h" + +static pthread_mutex_t lockMutex = PTHREAD_MUTEX_INITIALIZER; + +static void +nouveau_contended_lock(struct nouveau_context *nv, unsigned int flags) +{ +	dri_drawable_t			*dri_drawable = nv->dri_drawable; +	dri_screen_t			*dri_screen = nv->dri_context->dri_screen; +	struct nouveau_screen		*nv_screen = nv->nv_screen; +	struct nouveau_device		*dev = nv_screen->device; +	struct nouveau_device_priv	*nvdev = nouveau_device(dev); + +	drmGetLock(nvdev->fd, nvdev->ctx, flags); + +	/* If the window moved, may need to set a new cliprect now. +	 * +	 * NOTE: This releases and regains the hw lock, so all state +	 * checking must be done *after* this call: +	 */ +	if (dri_drawable) +		DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable); +} + +/* Lock the hardware and validate our state. + */ +void +LOCK_HARDWARE(struct nouveau_context *nv) +{ +	struct nouveau_screen		*nv_screen = nv->nv_screen; +	struct nouveau_device		*dev = nv_screen->device; +	struct nouveau_device_priv	*nvdev = nouveau_device(dev); +	char				__ret=0; + +	pthread_mutex_lock(&lockMutex); +	assert(!nv->locked); +	 +	DRM_CAS(nvdev->lock, nvdev->ctx, +		(DRM_LOCK_HELD | nvdev->ctx), __ret); +	 +	if (__ret) +		nouveau_contended_lock(nv, 0); +	nv->locked = 1; +} + + +/* Unlock the hardware using the global current context  + */ +void +UNLOCK_HARDWARE(struct nouveau_context *nv) +{ +	struct nouveau_screen		*nv_screen = nv->nv_screen; +	struct nouveau_device		*dev = nv_screen->device; +	struct nouveau_device_priv	*nvdev = nouveau_device(dev); + +	assert(nv->locked); +	nv->locked = 0; + +	DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx); + +	pthread_mutex_unlock(&lockMutex); +}  diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_notifier.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_notifier.c new file mode 120000 index 0000000000..3024a612a7 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_notifier.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_notifier.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_pushbuf.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_pushbuf.c new file mode 120000 index 0000000000..dae31d9799 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_pushbuf.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_pushbuf.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_resource.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_resource.c new file mode 120000 index 0000000000..e0d71e9d2b --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_resource.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_resource.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.c new file mode 100644 index 0000000000..daea3fff68 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.c @@ -0,0 +1,92 @@ +#include "pipe/p_context.h" +#include "pipe/p_util.h" +#include "nouveau_context.h" +#include <nouveau_drm.h> +#include "nouveau_dri.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_swapbuffers.h" + +#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 11 +#error nouveau_drm.h version does not match expected version +#endif + +/* +PUBLIC const char __driConfigOptions[] = +DRI_CONF_BEGIN +DRI_CONF_END; +static const GLuint __driNConfigOptions = 0; +*/ + +int nouveau_check_dri_drm_ddx(dri_version_t *dri, dri_version_t *drm, dri_version_t *ddx) +{ +	static const dri_version_t ddx_expected = {0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL}; +	static const dri_version_t dri_expected = {4, 0, 0}; +	static const dri_version_t drm_expected = {0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL}; +	 +	assert(dri); +	assert(drm); +	assert(ddx); +	 +	if (dri->major != dri_expected.major || dri->minor < dri_expected.minor) +	{ +		NOUVEAU_ERR("Unexpected DRI version.\n"); +		return 1; +	} +	if (drm->major != drm_expected.major || drm->minor < drm_expected.minor) +	{ +		NOUVEAU_ERR("Unexpected DRM version.\n"); +		return 1; +	} +	if (ddx->major != ddx_expected.major || ddx->minor < ddx_expected.minor) +	{ +		NOUVEAU_ERR("Unexpected DDX version.\n"); +		return 1; +	} +	 +	return 0; +} + +int +nouveau_screen_create(dri_screen_t *dri_screen, dri_framebuffer_t *dri_framebuf) +{	 +	struct nouveau_dri	*nv_dri = dri_framebuf->private; +	struct nouveau_screen	*nv_screen; +	int			ret; +	 +	if (nouveau_check_dri_drm_ddx(&dri_screen->dri, &dri_screen->drm, &dri_screen->ddx)) +		return 1; + +	nv_screen = CALLOC_STRUCT(nouveau_screen); +	if (!nv_screen) +		return 1; +	nv_screen->dri_screen = dri_screen; +	dri_screen->private = (void*)nv_screen; + +	/* +	driParseOptionInfo(&nv_screen->option_cache, +			   __driConfigOptions, __driNConfigOptions); +	*/ + +	if ((ret = nouveau_device_open_existing(&nv_screen->device, 0, +						dri_screen->fd, 0))) { +		NOUVEAU_ERR("Failed opening nouveau device: %d.\n", ret); +		return 1; +	} + +	nv_screen->front_offset = nv_dri->front_offset; +	nv_screen->front_pitch  = nv_dri->front_pitch * (nv_dri->bpp / 8); +	nv_screen->front_cpp = nv_dri->bpp / 8; +	nv_screen->front_height = nv_dri->height; + +	return 0; +} + +void +nouveau_screen_destroy(dri_screen_t *dri_screen) +{ +	struct nouveau_screen *nv_screen = dri_screen->private; + +	FREE(nv_screen); +} + diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.h new file mode 100644 index 0000000000..8a58bb7556 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.h @@ -0,0 +1,24 @@ +#ifndef __NOUVEAU_SCREEN_H__ +#define __NOUVEAU_SCREEN_H__ + +/* TODO: Investigate using DRI options for interesting things */ +/*#include "xmlconfig.h"*/ + +struct nouveau_screen { +	dri_screen_t			*dri_screen; +	struct nouveau_device		*device; +	struct nouveau_channel_context	*nvc; + +	uint32_t			front_offset; +	uint32_t			front_pitch; +	uint32_t			front_cpp; +	uint32_t			front_height; +	 +	/*driOptionCache		option_cache;*/ +}; + +int nouveau_screen_create(dri_screen_t *dri_screen, dri_framebuffer_t *dri_framebuf); +void nouveau_screen_destroy(dri_screen_t *dri_screen); + +#endif + diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c new file mode 100644 index 0000000000..7916c80615 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c @@ -0,0 +1,64 @@ +#include "pipe/p_context.h" +#include "nouveau_context.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_swapbuffers.h" + +void +nouveau_copy_buffer(dri_drawable_t *dri_drawable, struct pipe_surface *surf, +		    const drm_clip_rect_t *rect) +{ +	struct nouveau_context	*nv = dri_drawable->private; +	drm_clip_rect_t		*pbox; +	int			nbox, i; + +	LOCK_HARDWARE(nv); +	if (!dri_drawable->num_cliprects) { +		UNLOCK_HARDWARE(nv); +		return; +	} +	pbox = dri_drawable->cliprects; +	nbox = dri_drawable->num_cliprects; + +	nv->surface_copy_prep(nv, nv->frontbuffer, surf); +	for (i = 0; i < nbox; i++, pbox++) { +		int sx, sy, dx, dy, w, h; + +		sx = pbox->x1 - dri_drawable->x; +		sy = pbox->y1 - dri_drawable->y; +		dx = pbox->x1; +		dy = pbox->y1; +		w  = pbox->x2 - pbox->x1; +		h  = pbox->y2 - pbox->y1; + +		nv->surface_copy(nv, dx, dy, sx, sy, w, h); +	} + +	FIRE_RING(nv->nvc->channel); +	UNLOCK_HARDWARE(nv); + +	//if (nv->last_stamp != dri_drawable->last_sarea_stamp) +		//nv->last_stamp = dri_drawable->last_sarea_stamp; +} + +void +nouveau_copy_sub_buffer(dri_drawable_t *dri_drawable, struct pipe_surface *surf, int x, int y, int w, int h) +{ +	if (surf) { +		drm_clip_rect_t rect; +		rect.x1 = x; +		rect.y1 = y; +		rect.x2 = x + w; +		rect.y2 = y + h; + +		nouveau_copy_buffer(dri_drawable, surf, &rect); +	} +} + +void +nouveau_swap_buffers(dri_drawable_t *dri_drawable, struct pipe_surface *surf) +{ +	if (surf) +		nouveau_copy_buffer(dri_drawable, surf, NULL); +} + diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h new file mode 100644 index 0000000000..35e934adba --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h @@ -0,0 +1,10 @@ +#ifndef __NOUVEAU_SWAPBUFFERS_H__ +#define __NOUVEAU_SWAPBUFFERS_H__ + +extern void nouveau_copy_buffer(dri_drawable_t *, struct pipe_surface *, +				const drm_clip_rect_t *); +extern void nouveau_copy_sub_buffer(dri_drawable_t *, struct pipe_surface *, +				    int x, int y, int w, int h); +extern void nouveau_swap_buffers(dri_drawable_t *, struct pipe_surface *); + +#endif diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys.c new file mode 120000 index 0000000000..43de49b98b --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_winsys.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c new file mode 100644 index 0000000000..b835bd5760 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c @@ -0,0 +1,261 @@ +#include "pipe/p_winsys.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "nouveau_context.h" +#include "nouveau_local.h" +#include "nouveau_screen.h" +#include "nouveau_swapbuffers.h" +#include "nouveau_winsys_pipe.h" + +static void +nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf, +			  void *context_private) +{ +	struct nouveau_context *nv = context_private; +	dri_drawable_t *dri_drawable = nv->dri_drawable; + +	nouveau_copy_buffer(dri_drawable, surf, NULL); +} + +static const char * +nouveau_get_name(struct pipe_winsys *pws) +{ +	return "Nouveau/DRI"; +} + +static struct pipe_surface * +nouveau_surface_alloc(struct pipe_winsys *ws) +{ +	struct pipe_surface *surf; +	 +	surf = CALLOC_STRUCT(pipe_surface); +	if (!surf) +		return NULL; + +	surf->refcount = 1; +	surf->winsys = ws; +	return surf; +} + +/* Borrowed from Mesa's xm_winsys */ +static unsigned int +round_up(unsigned n, unsigned multiple) +{ +   return (n + multiple - 1) & ~(multiple - 1); +} + +static int +nouveau_surface_alloc_storage +( +	struct pipe_winsys *pws, +	struct pipe_surface *surface, +	unsigned width, +	unsigned height, +	enum pipe_format format, +	unsigned flags, +	unsigned tex_usage +) +{ +	const unsigned int ALIGNMENT = 256; +	 +	assert(pws); +	assert(surface); +	 +	surface->width = width; +	surface->height = height; +	surface->format = format; +	pf_get_block(format, &surface->block); +	surface->nblocksx = pf_get_nblocksx(&surface->block, width); +	surface->nblocksy = pf_get_nblocksy(&surface->block, height); +	surface->stride = round_up(surface->nblocksx * surface->block.size, ALIGNMENT); +	surface->usage = flags; +	surface->buffer = pws->buffer_create(pws, ALIGNMENT, PIPE_BUFFER_USAGE_PIXEL, surface->stride * surface->nblocksy); +	 +	return 0; +} + +static void +nouveau_surface_release(struct pipe_winsys *ws, struct pipe_surface **s) +{ +	struct pipe_surface *surf = *s; + +	*s = NULL; +	if (--surf->refcount <= 0) { +		if (surf->buffer) +			pipe_buffer_reference(ws, &surf->buffer, NULL); +		free(surf); +	} +} + +static struct pipe_buffer * +nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, +		       unsigned usage, unsigned size) +{ +	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; +	struct nouveau_context *nv = nvpws->nv; +	struct nouveau_device *dev = nv->nv_screen->device; +	struct nouveau_pipe_buffer *nvbuf; +	uint32_t flags; + +	nvbuf = calloc(1, sizeof(*nvbuf)); +	if (!nvbuf) +		return NULL; +	nvbuf->base.refcount = 1; +	nvbuf->base.alignment = alignment; +	nvbuf->base.usage = usage; +	nvbuf->base.size = size; + +	flags = NOUVEAU_BO_LOCAL; + +	if (usage & PIPE_BUFFER_USAGE_PIXEL) { +		if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE) +			flags |= NOUVEAU_BO_GART; +		flags |= NOUVEAU_BO_VRAM; +	} + +	if (usage & PIPE_BUFFER_USAGE_VERTEX) { +		if (nv->cap.hw_vertex_buffer) +			flags |= NOUVEAU_BO_GART; +	} + +	if (usage & PIPE_BUFFER_USAGE_INDEX) { +		if (nv->cap.hw_index_buffer) +			flags |= NOUVEAU_BO_GART; +	} + +	if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { +		free(nvbuf); +		return NULL; +	} + +	return &nvbuf->base; +} + +static struct pipe_buffer * +nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) +{ +	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; +	struct nouveau_device *dev = nvpws->nv->nv_screen->device; +	struct nouveau_pipe_buffer *nvbuf; + +	nvbuf = calloc(1, sizeof(*nvbuf)); +	if (!nvbuf) +		return NULL; +	nvbuf->base.refcount = 1; +	nvbuf->base.size = bytes; + +	if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) { +		free(nvbuf); +		return NULL; +	} + +	return &nvbuf->base; +} + +static void +nouveau_pipe_bo_del(struct pipe_winsys *ws, struct pipe_buffer *buf) +{ +	struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf); + +	nouveau_bo_del(&nvbuf->bo); +	free(nvbuf); +} + +static void * +nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf, +		    unsigned flags) +{ +	struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf); +	uint32_t map_flags = 0; + +	if (flags & PIPE_BUFFER_USAGE_CPU_READ) +		map_flags |= NOUVEAU_BO_RD; +	if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) +		map_flags |= NOUVEAU_BO_WR; + +	if (nouveau_bo_map(nvbuf->bo, map_flags)) +		return NULL; +	return nvbuf->bo->map; +} + +static void +nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) +{ +	struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf); + +	nouveau_bo_unmap(nvbuf->bo); +} + +static INLINE struct nouveau_fence * +nouveau_pipe_fence(struct pipe_fence_handle *pfence) +{ +	return (struct nouveau_fence *)pfence; +} + +static void +nouveau_pipe_fence_reference(struct pipe_winsys *ws, +			     struct pipe_fence_handle **ptr, +			     struct pipe_fence_handle *pfence) +{ +	nouveau_fence_ref((void *)pfence, (void *)ptr); +} + +static int +nouveau_pipe_fence_signalled(struct pipe_winsys *ws, +			     struct pipe_fence_handle *pfence, unsigned flag) +{ +	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)ws; +	struct nouveau_fence *fence = nouveau_pipe_fence(pfence); + +	if (nouveau_fence(fence)->signalled == 0) +		nouveau_fence_flush(nvpws->nv->nvc->channel); + +	return !nouveau_fence(fence)->signalled; +} + +static int +nouveau_pipe_fence_finish(struct pipe_winsys *ws, +			  struct pipe_fence_handle *pfence, unsigned flag) +{ +	struct nouveau_fence *fence = nouveau_pipe_fence(pfence); +	struct nouveau_fence *ref = NULL; + +	nouveau_fence_ref(fence, &ref); +	return nouveau_fence_wait(&ref); +} + +struct pipe_winsys * +nouveau_create_pipe_winsys(struct nouveau_context *nv) +{ +	struct nouveau_pipe_winsys *nvpws; +	struct pipe_winsys *pws; + +	nvpws = CALLOC_STRUCT(nouveau_pipe_winsys); +	if (!nvpws) +		return NULL; +	nvpws->nv = nv; +	pws = &nvpws->pws; + +	pws->flush_frontbuffer = nouveau_flush_frontbuffer; + +	pws->surface_alloc = nouveau_surface_alloc; +	pws->surface_alloc_storage = nouveau_surface_alloc_storage; +	pws->surface_release = nouveau_surface_release; + +	pws->buffer_create = nouveau_pipe_bo_create; +	pws->buffer_destroy = nouveau_pipe_bo_del; +	pws->user_buffer_create = nouveau_pipe_bo_user_create; +	pws->buffer_map = nouveau_pipe_bo_map; +	pws->buffer_unmap = nouveau_pipe_bo_unmap; + +	pws->fence_reference = nouveau_pipe_fence_reference; +	pws->fence_signalled = nouveau_pipe_fence_signalled; +	pws->fence_finish = nouveau_pipe_fence_finish; + +	pws->get_name = nouveau_get_name; + +	return &nvpws->pws; +} + diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.h new file mode 120000 index 0000000000..264716fef0 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.h @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_winsys_pipe.h
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_softpipe.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_softpipe.c new file mode 120000 index 0000000000..83faccde96 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_softpipe.c @@ -0,0 +1 @@ +../../dri/nouveau/nouveau_winsys_softpipe.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nv04_surface.c b/src/gallium/winsys/g3dvl/nouveau/nv04_surface.c new file mode 120000 index 0000000000..e05f0671d6 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nv04_surface.c @@ -0,0 +1 @@ +../../dri/nouveau/nv04_surface.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/nouveau/nv50_surface.c b/src/gallium/winsys/g3dvl/nouveau/nv50_surface.c new file mode 120000 index 0000000000..3850748229 --- /dev/null +++ b/src/gallium/winsys/g3dvl/nouveau/nv50_surface.c @@ -0,0 +1 @@ +../../dri/nouveau/nv50_surface.c
\ No newline at end of file diff --git a/src/gallium/winsys/g3dvl/vl_winsys.h b/src/gallium/winsys/g3dvl/vl_winsys.h new file mode 100644 index 0000000000..c83db28dd9 --- /dev/null +++ b/src/gallium/winsys/g3dvl/vl_winsys.h @@ -0,0 +1,14 @@ +#ifndef vl_winsys_h +#define vl_winsys_h + +#include <X11/Xlib.h> + +struct pipe_context; + +struct pipe_context* create_pipe_context(Display *display, int screen); +int destroy_pipe_context(struct pipe_context *pipe); +int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable); +int unbind_pipe_drawable(struct pipe_context *pipe); + +#endif + diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.c b/src/gallium/winsys/g3dvl/xsp_winsys.c new file mode 100644 index 0000000000..0100fe37bd --- /dev/null +++ b/src/gallium/winsys/g3dvl/xsp_winsys.c @@ -0,0 +1,337 @@ +#include "vl_winsys.h" +#include <X11/Xutil.h> +#include <pipe/p_winsys.h> +#include <pipe/p_state.h> +#include <pipe/p_util.h> +#include <pipe/p_inlines.h> +#include <softpipe/sp_winsys.h> + +/* pipe_winsys implementation */ + +struct xsp_pipe_winsys +{ +	struct pipe_winsys	base; +	XImage			fbimage; +}; + +struct xsp_context +{ +	Display			*display; +	int			screen; +	Drawable		drawable; +	int			drawable_bound; +}; + +struct xsp_buffer +{ +	struct pipe_buffer	base; +	boolean			is_user_buffer; +	void			*data; +	void			*mapped_data; +}; + +static struct pipe_buffer* xsp_buffer_create(struct pipe_winsys *pws, unsigned alignment, unsigned usage, unsigned size) +{ +	struct xsp_buffer *buffer; +	 +	assert(pws); +	 +	buffer = calloc(1, sizeof(struct xsp_buffer)); +	buffer->base.refcount = 1; +	buffer->base.alignment = alignment; +	buffer->base.usage = usage; +	buffer->base.size = size; +	buffer->data = align_malloc(size, alignment); +	 +	return (struct pipe_buffer*)buffer; +} + +static struct pipe_buffer* xsp_user_buffer_create(struct pipe_winsys *pws, void *data, unsigned size) +{ +	struct xsp_buffer *buffer; +	 +	assert(pws); +	 +	buffer = calloc(1, sizeof(struct xsp_buffer)); +	buffer->base.refcount = 1; +	buffer->base.size = size; +	buffer->is_user_buffer = TRUE; +	buffer->data = data; +	 +	return (struct pipe_buffer*)buffer; +} + +static void* xsp_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buffer, unsigned flags) +{ +	struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer; +	 +	assert(pws); +	assert(buffer); +	 +	xsp_buf->mapped_data = xsp_buf->data; +	 +	return xsp_buf->mapped_data; +} + +static void xsp_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buffer) +{ +	struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer; +	 +	assert(pws); +	assert(buffer); +	 +	xsp_buf->mapped_data = NULL; +} + +static void xsp_buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buffer) +{ +	struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer; +	 +	assert(pws); +	assert(buffer); +	 +	if (!xsp_buf->is_user_buffer) +		align_free(xsp_buf->data); +	 +	free(xsp_buf); +} + +static struct pipe_surface* xsp_surface_alloc(struct pipe_winsys *pws) +{ +	struct pipe_surface *surface; +	 +	assert(pws); +	 +	surface = calloc(1, sizeof(struct pipe_surface)); +	surface->refcount = 1; +	surface->winsys = pws; +	 +	return surface; +} + +/* Borrowed from Mesa's xm_winsys */ +static unsigned int round_up(unsigned n, unsigned multiple) +{ +   return (n + multiple - 1) & ~(multiple - 1); +} + +static int xsp_surface_alloc_storage +( +	struct pipe_winsys *pws, +	struct pipe_surface *surface, +	unsigned width, +	unsigned height, +	enum pipe_format format, +	unsigned flags, +	unsigned tex_usage +) +{ +	const unsigned int ALIGNMENT = 1; +	 +	assert(pws); +	assert(surface); +	 +	surface->width = width; +	surface->height = height; +	surface->format = format; +	pf_get_block(format, &surface->block); +	surface->nblocksx = pf_get_nblocksx(&surface->block, width); +	surface->nblocksy = pf_get_nblocksy(&surface->block, height); +	surface->stride = round_up(surface->nblocksx * surface->block.size, ALIGNMENT); +	surface->usage = flags; +	surface->buffer = pws->buffer_create(pws, ALIGNMENT, PIPE_BUFFER_USAGE_PIXEL, surface->stride * surface->nblocksy); +	 +	return 0; +} + +static void xsp_surface_release(struct pipe_winsys *pws, struct pipe_surface **surface) +{ +	struct pipe_surface *s; +	 +	assert(pws); +	assert(surface); +	assert(*surface); +	 +	s = *surface; +	 +	s->refcount--; +	 +	if (s->refcount == 0) +	{ +		pipe_buffer_reference(pws, &s->buffer, NULL); +		free(s); +	} +	 +	*surface = NULL; +} + +static void xsp_fence_reference(struct pipe_winsys *pws, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence) +{ +	assert(pws); +	assert(ptr); +	assert(fence); +} + +static int xsp_fence_signalled(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag) +{ +	assert(pws); +	assert(fence); +	 +	return 0; +} + +static int xsp_fence_finish(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag) +{ +	assert(pws); +	assert(fence); +	 +	return 0; +} + +static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private) +{	 +	struct xsp_pipe_winsys	*xsp_winsys; +	struct xsp_context	*xsp_context; +	 +	assert(pws); +	assert(surface); +	assert(context_private); +	 +	xsp_winsys = (struct xsp_pipe_winsys*)pws; +	xsp_context = (struct xsp_context*)context_private; +	 +	if (!xsp_context->drawable_bound) +		return; +	 +	xsp_winsys->fbimage.width = surface->width; +	xsp_winsys->fbimage.height = surface->height; +	xsp_winsys->fbimage.bytes_per_line = surface->width * (xsp_winsys->fbimage.bits_per_pixel >> 3); +	xsp_winsys->fbimage.data = pipe_surface_map(surface, 0); +	 +	XPutImage +	( +		xsp_context->display, +		xsp_context->drawable, +		XDefaultGC(xsp_context->display, xsp_context->screen), +		&xsp_winsys->fbimage, +		0, +		0, +		0, +		0, +		surface->width, +		surface->height +	); +	XFlush(xsp_context->display); +	pipe_surface_unmap(surface); +} + +static const char* xsp_get_name(struct pipe_winsys *pws) +{ +	assert(pws); +	return "X11 SoftPipe"; +} + +/* Show starts here */ + +int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable) +{ +	struct xsp_context *xsp_context; +	 +	assert(pipe); +	 +	xsp_context = pipe->priv; +	xsp_context->drawable = drawable; +	xsp_context->drawable_bound = 1; +	 +	return 0; +} + +int unbind_pipe_drawable(struct pipe_context *pipe) +{ +	struct xsp_context *xsp_context; +	 +	assert(pipe); +	 +	xsp_context = pipe->priv; +	xsp_context->drawable_bound = 0; +	 +	return 0; +} + +struct pipe_context* create_pipe_context(Display *display, int screen) +{ +	struct xsp_pipe_winsys	*xsp_winsys; +	struct xsp_context	*xsp_context; +	struct pipe_screen	*sp_screen; +	struct pipe_context	*sp_pipe; +	 +	assert(display); +	 +	xsp_winsys = calloc(1, sizeof(struct xsp_pipe_winsys)); +	xsp_winsys->base.buffer_create = xsp_buffer_create; +	xsp_winsys->base.user_buffer_create = xsp_user_buffer_create; +	xsp_winsys->base.buffer_map = xsp_buffer_map; +	xsp_winsys->base.buffer_unmap = xsp_buffer_unmap; +	xsp_winsys->base.buffer_destroy = xsp_buffer_destroy; +	xsp_winsys->base.surface_alloc = xsp_surface_alloc; +	xsp_winsys->base.surface_alloc_storage = xsp_surface_alloc_storage; +	xsp_winsys->base.surface_release = xsp_surface_release; +	xsp_winsys->base.fence_reference = xsp_fence_reference; +	xsp_winsys->base.fence_signalled = xsp_fence_signalled; +	xsp_winsys->base.fence_finish = xsp_fence_finish; +	xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer; +	xsp_winsys->base.get_name = xsp_get_name; +	 +	{ +		/* XXX: Can't use the returned XImage* directly, +		since we don't have control over winsys destruction +		and we wouldn't be able to free it */ +		XImage *template = XCreateImage +		( +			display, +			XDefaultVisual(display, XDefaultScreen(display)), +			XDefaultDepth(display, XDefaultScreen(display)), +			ZPixmap, +			0, +			NULL, +			0,	/* Don't know the width and height until flush_frontbuffer */ +			0, +			32, +			0 +		); +		 +		memcpy(&xsp_winsys->fbimage, template, sizeof(XImage)); +		XInitImage(&xsp_winsys->fbimage); +		 +		XDestroyImage(template); +	} +	 +	sp_screen = softpipe_create_screen((struct pipe_winsys*)xsp_winsys); +	sp_pipe = softpipe_create(sp_screen, (struct pipe_winsys*)xsp_winsys, NULL); +	 +	xsp_context = calloc(1, sizeof(struct xsp_context)); +	xsp_context->display = display; +	xsp_context->screen = screen; +	 +	sp_pipe->priv = xsp_context; +	 +	return sp_pipe; +} + +int destroy_pipe_context(struct pipe_context *pipe) +{ +	struct pipe_screen *screen; +	struct pipe_winsys *winsys; +	 +	assert(pipe); +	 +	screen = pipe->screen; +	winsys = pipe->winsys; +	free(pipe->priv); +	pipe->destroy(pipe); +	screen->destroy(screen); +	free(winsys); +	 +	return 0; +} + diff --git a/src/libXvMC/Makefile b/src/libXvMC/Makefile new file mode 100644 index 0000000000..c154e17dc3 --- /dev/null +++ b/src/libXvMC/Makefile @@ -0,0 +1,64 @@ +TARGET		= libXvMCg3dvl.so +SONAME		= libXvMCg3dvl.so.1 +GALLIUMDIR	= ../gallium + +OBJECTS         = block.o surface.o context.o subpicture.o attributes.o + +ifeq (${DRIVER}, softpipe) +OBJECTS         += ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o +endif + +CFLAGS	+= -g -fPIC -Wall -Werror			\ +	   -I${GALLIUMDIR}/state_trackers/g3dvl		\ +	   -I${GALLIUMDIR}/winsys/g3dvl			\ +	   -I${GALLIUMDIR}/include			\ +	   -I${GALLIUMDIR}/auxiliary			\ +	   -I${GALLIUMDIR}/drivers + +ifeq (${DRIVER}, softpipe) +LDFLAGS	+= -L${GALLIUMDIR}/state_trackers/g3dvl		\ +	   -L${GALLIUMDIR}/drivers/softpipe		\ +	   -L${GALLIUMDIR}/auxiliary/tgsi		\ +	   -L${GALLIUMDIR}/auxiliary/draw		\ +	   -L${GALLIUMDIR}/auxiliary/translate		\ +	   -L${GALLIUMDIR}/auxiliary/cso_cache		\ +	   -L${GALLIUMDIR}/auxiliary/util		\ +	   -L${GALLIUMDIR}/auxiliary/rtasm +else +LDFLAGS	+= -L${GALLIUMDIR}/state_trackers/g3dvl		\ +   	   -L${GALLIUMDIR}/winsys/g3dvl/nouveau		\ +   	   -L${GALLIUMDIR}/auxiliary/util +endif + +ifeq (${DRIVER}, softpipe) +LIBS	+= -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lm +else +LIBS	+= -lg3dvl -lnouveau_dri -lutil +endif + +############################################# + +.PHONY	= all clean + +all: ${TARGET} + +ifeq (${DRIVER}, softpipe) +${TARGET}: ${OBJECTS} +	cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} +	$(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ $^ ${LIBS} + +clean: +	cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean +	rm -rf ${OBJECTS} ${TARGET} +else +${TARGET}: ${OBJECTS} +	cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} +	cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE} +	$(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ $^ ${LIBS} + +clean: +	cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean +	cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE} clean +	rm -rf ${OBJECTS} ${TARGET} +endif + diff --git a/src/libXvMC/attributes.c b/src/libXvMC/attributes.c new file mode 100644 index 0000000000..674524b8b8 --- /dev/null +++ b/src/libXvMC/attributes.c @@ -0,0 +1,20 @@ +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMC.h> + +XvAttribute* XvMCQueryAttributes(Display *display, XvMCContext *context, int *number) +{ +	return NULL; +} + +Status XvMCSetAttribute(Display *display, XvMCContext *context, Atom attribute, int value) +{ +	return BadImplementation; +} + +Status XvMCGetAttribute(Display *display, XvMCContext *context, Atom attribute, int *value) +{ +	return BadImplementation; +} + diff --git a/src/libXvMC/block.c b/src/libXvMC/block.c new file mode 100644 index 0000000000..deca305bdc --- /dev/null +++ b/src/libXvMC/block.c @@ -0,0 +1,84 @@ +#include <assert.h> +#include <stdlib.h> +#include <X11/Xlib.h> +#include <X11/extensions/XvMC.h> +#include <vl_context.h> + +/* + * XvMC defines 64 element blocks (8x8 elements). + * Elements are 8 bits when they represent color values, + * 9 bits when they reprecent DCT coefficients, we + * store them in 2 bytes in either case. + */ +#define BLOCK_SIZE (64 * 2) + +Status XvMCCreateBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks) +{ +	struct vl_context *vl_ctx; +	 +	assert(display); +	 +	if (!context) +		return XvMCBadContext; +	if (num_blocks == 0) +		return BadValue; +	 +	assert(blocks); +	 +	vl_ctx = context->privData; +	assert(display == vl_ctx->display); + +	blocks->context_id = context->context_id; +	blocks->num_blocks = num_blocks; +	blocks->blocks = malloc(BLOCK_SIZE * num_blocks); +	/* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */ +	blocks->privData = display; +	 +	return Success; +} + +Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *blocks) +{	 +	assert(display); +	assert(blocks); +	assert(display == blocks->privData); +	free(blocks->blocks); +	 +	return Success; +} + +Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks) +{ +	struct vl_context *vl_ctx; +	 +	assert(display); +	 +	if (!context) +		return XvMCBadContext; +	if (num_blocks == 0) +		return BadValue; +	 +	assert(blocks); +	 +	vl_ctx = context->privData; +	assert(display == vl_ctx->display); +	 +	blocks->context_id = context->context_id; +	blocks->num_blocks = num_blocks; +	blocks->macro_blocks = malloc(sizeof(XvMCMacroBlock) * num_blocks); +	/* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */ +	blocks->privData = display; +	 +	return Success; +} + +Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *blocks) +{	 +	assert(display); +	assert(blocks); +	assert(display == blocks->privData); +	free(blocks->macro_blocks); +	 +	return Success; +} + diff --git a/src/libXvMC/context.c b/src/libXvMC/context.c new file mode 100644 index 0000000000..9cf654d6bb --- /dev/null +++ b/src/libXvMC/context.c @@ -0,0 +1,218 @@ +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> +#include <vl_context.h> +#include <vl_winsys.h> + +static Status Validate(Display *display, XvPortID port, int surface_type_id, unsigned int width, unsigned int height, int flags, int *chroma_format) +{ +	unsigned int	found_port = 0; +	unsigned int	found_surface = 0; +	XvAdaptorInfo	*adaptor_info; +	unsigned int	num_adaptors; +	int		num_types; +	unsigned int	max_width, max_height; +	Status		ret; +	unsigned int	i, j, k; +	 +	assert(display && chroma_format); +	 +	ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info); +	if (ret != Success) +		return ret; +	 +	/* Scan through all adaptors looking for this port and surface */ +	for (i = 0; i < num_adaptors && !found_port; ++i) +	{ +		/* Scan through all ports of this adaptor looking for our port */ +		for (j = 0; j < adaptor_info[i].num_ports && !found_port; ++j) +		{ +			/* If this is our port, scan through all its surfaces looking for our surface */ +			if (adaptor_info[i].base_id + j == port) +			{ +				XvMCSurfaceInfo *surface_info; +				 +				found_port = 1; +				surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); +				 +				if (surface_info) +				{ +					for (k = 0; k < num_types && !found_surface; ++k) +					{ +						if (surface_info[k].surface_type_id == surface_type_id) +						{ +							found_surface = 1; +							max_width = surface_info[k].max_width; +							max_height = surface_info[k].max_height; +							*chroma_format = surface_info[k].chroma_format; +						} +					} +					 +					XFree(surface_info); +				} +				else +				{ +					XvFreeAdaptorInfo(adaptor_info); +					return BadAlloc; +				} +			} +		} +	} +	 +	XvFreeAdaptorInfo(adaptor_info); +	 +	if (!found_port) +		return XvBadPort; +	if (!found_surface) +		return BadMatch; +	if (width > max_width || height > max_height) +		return BadValue; +	if (flags != XVMC_DIRECT && flags != 0) +		return BadValue; +	 +	return Success; +} + +static enum VL_FORMAT FormatToVL(int xvmc_format) +{ +	enum VL_FORMAT vl_format; +	 +	switch (xvmc_format) +	{ +		case XVMC_CHROMA_FORMAT_420: +		{ +			vl_format = VL_FORMAT_YCBCR_420; +			break; +		} +		case XVMC_CHROMA_FORMAT_422: +		{ +			vl_format = VL_FORMAT_YCBCR_422; +			break; +		} +		case XVMC_CHROMA_FORMAT_444: +		{ +			vl_format = VL_FORMAT_YCBCR_444; +			break; +		} +		default: +			assert(0); +	} +	 +	return vl_format; +} + +Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context) +{ +	int			chroma_format; +	Status			ret; +	struct VL_CONTEXT	*vl_ctx; +	struct pipe_context	*pipe; +	 +	assert(display); +	 +	if (!context) +		return XvMCBadContext; +	 +	ret = Validate(display, port, surface_type_id, width, height, flags, &chroma_format); +	if (ret != Success) +		return ret; +	 +	pipe = create_pipe_context(display, XDefaultScreen(display)); +	 +	assert(pipe); +	 +	vlCreateContext(display, pipe, width, height, FormatToVL(chroma_format), &vl_ctx); +	 +	context->context_id = XAllocID(display); +	context->surface_type_id = surface_type_id; +	context->width = width; +	context->height = height; +	context->flags = flags; +	context->port = port; +	context->privData = vl_ctx; +	 +	return Success; +} + +Status XvMCDestroyContext(Display *display, XvMCContext *context) +{ +	struct VL_CONTEXT	*vl_ctx; +	struct pipe_context	*pipe; +	 +	assert(display); +	 +	if (!context) +		return XvMCBadContext; +	 +	vl_ctx = context->privData; +	 +	assert(display == vl_ctx->display); +	 +	pipe = vl_ctx->pipe; +	vlDestroyContext(vl_ctx); +	destroy_pipe_context(pipe); +	 +	return Success; +} + +/* XXX: The following are here temporarily, need to be implemented in the DDX driver */ +/* TODO: Figure out which of these need to be in DDX, which are better off in DDX, which can stay */ + +Bool XvMCQueryExtension(Display *display, int *event_base, int *err_base) +{ +	*event_base = 0; +	*err_base = 0; +	 +	return True; +} + +Status XvMCQueryVersion(Display *display, int *major, int *minor) +{ +	*major = 1; +	*minor = 0; +	 +	return Success; +} + +XvMCSurfaceInfo* XvMCListSurfaceTypes(Display *display, XvPortID port, int *num) +{ +	XvMCSurfaceInfo	*surface_info = calloc(1, sizeof(XvMCSurfaceInfo)); +	 +	*num = 1; +	 +	surface_info->chroma_format = XVMC_CHROMA_FORMAT_420; +	surface_info->max_width = 2048; +	surface_info->max_height = 2048; +	surface_info->subpicture_max_width = 2048; +	surface_info->subpicture_max_height = 2048; +	surface_info->mc_type = XVMC_IDCT | XVMC_MPEG_2; +	surface_info->surface_type_id = 123; /* FIXME: XAllocID(display)*/; +	surface_info->flags = XVMC_INTRA_UNSIGNED | XVMC_SUBPICTURE_INDEPENDENT_SCALING | XVMC_BACKEND_SUBPICTURE; +	 +	return surface_info; +} + +XvImageFormatValues* XvMCListSubpictureTypes(Display* display, XvPortID port, int surface_type_id, int *count_return) +{ +	XvImageFormatValues *image_formats = calloc(1, sizeof(XvImageFormatValues)); +	 +	*count_return = 1; +	 +	image_formats[0].id = 123; +	image_formats[0].type = XvRGB; +	image_formats[0].byte_order = LSBFirst; +	image_formats[0].bits_per_pixel = 8; +	image_formats[0].format = XvPacked; +	image_formats[0].num_planes = 1; +	image_formats[0].depth = 8; +	image_formats[0].red_mask = 0x0000FF; +	image_formats[0].green_mask = 0x00FF00; +	image_formats[0].blue_mask = 0xFF0000; +	image_formats[0].component_order[0] = 'R'; +	image_formats[0].component_order[0] = 'G'; +	image_formats[0].component_order[0] = 'B'; +	image_formats[0].scanline_order = XvTopToBottom; +	 +	return image_formats; +} + diff --git a/src/libXvMC/subpicture.c b/src/libXvMC/subpicture.c new file mode 100644 index 0000000000..c8f70c90d0 --- /dev/null +++ b/src/libXvMC/subpicture.c @@ -0,0 +1,215 @@ +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMC.h> + +Status XvMCCreateSubpicture +( +	Display *display, +	XvMCContext *context, +	XvMCSubpicture *subpicture, +	unsigned short width, +	unsigned short height, +	int xvimage_id +) +{ +	assert(display); +	 +	if (!context) +		return XvMCBadContext; +	 +	assert(subpicture); +	 +	if (width > 2048 || height > 2048) +		return BadValue; +	 +	if (xvimage_id != 123) +		return BadMatch; +	 +	subpicture->subpicture_id = XAllocID(display); +	subpicture->context_id = context->context_id; +	subpicture->xvimage_id = xvimage_id; +	subpicture->width = width; +	subpicture->height = height; +	subpicture->num_palette_entries = 0; +	subpicture->entry_bytes = 0; +	subpicture->component_order[0] = 0; +	subpicture->component_order[1] = 0; +	subpicture->component_order[2] = 0; +	subpicture->component_order[3] = 0; +	/* TODO: subpicture->privData = ;*/ +	 +	return Success; +} + +Status XvMCClearSubpicture +( +	Display *display, +	XvMCSubpicture *subpicture, +	short x, +	short y, +	unsigned short width, +	unsigned short height, +	unsigned int color +) +{ +	assert(display); +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	/* TODO: Assert clear rect is within bounds? Or clip? */ +	 +	return Success; +} + +Status XvMCCompositeSubpicture +( +	Display *display, +	XvMCSubpicture *subpicture, +	XvImage *image, +	short srcx, +	short srcy, +	unsigned short width, +	unsigned short height, +	short dstx, +	short dsty +) +{ +	assert(display); +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	assert(image); +	 +	if (subpicture->xvimage_id != image->id) +		return BadMatch; +	 +	/* TODO: Assert rects are within bounds? Or clip? */ +	 +	return Success; +} + +Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture) +{ +	assert(display); +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	return BadImplementation; +} + +Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, unsigned char *palette) +{ +	assert(display); +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	assert(palette); +	 +	/* We don't support paletted subpictures */ +	return BadMatch; +} + +Status XvMCBlendSubpicture +( +	Display *display, +	XvMCSurface *target_surface, +	XvMCSubpicture *subpicture, +	short subx, +	short suby, +	unsigned short subw, +	unsigned short subh, +	short surfx, +	short surfy, +	unsigned short surfw, +	unsigned short surfh +) +{ +	assert(display); +	 +	if (!target_surface) +		return XvMCBadSurface; +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	if (target_surface->context_id != subpicture->context_id) +		return BadMatch; +	 +	/* TODO: Assert rects are within bounds? Or clip? */ +	return Success; +} + +Status XvMCBlendSubpicture2 +( +	Display *display, +	XvMCSurface *source_surface, +	XvMCSurface *target_surface, +	XvMCSubpicture *subpicture, +	short subx, +	short suby, +	unsigned short subw, +	unsigned short subh, +	short surfx, +	short surfy, +	unsigned short surfw, +	unsigned short surfh +) +{ +	assert(display); +	 +	if (!source_surface || !target_surface) +		return XvMCBadSurface; +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	if (source_surface->context_id != subpicture->context_id) +		return BadMatch; +		 +	if (source_surface->context_id != subpicture->context_id) +		return BadMatch; +	 +	/* TODO: Assert rects are within bounds? Or clip? */ +	return Success; +} + +Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture) +{ +	assert(display); +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	return Success; +} + +Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture) +{ +	assert(display); +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	return Success; +} + +Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, int *status) +{ +	assert(display); +	 +	if (!subpicture) +		return XvMCBadSubpicture; +	 +	assert(status); +	 +	/* TODO */ +	*status = 0; +	 +	return Success; +} + diff --git a/src/libXvMC/surface.c b/src/libXvMC/surface.c new file mode 100644 index 0000000000..1c07220e84 --- /dev/null +++ b/src/libXvMC/surface.c @@ -0,0 +1,412 @@ +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/extensions/XvMC.h> +#include <vl_context.h> +#include <vl_surface.h> + +static enum VL_PICTURE PictureToVL(int xvmc_pic) +{ +	enum VL_PICTURE vl_pic; +	 +	switch (xvmc_pic) +	{ +		case XVMC_TOP_FIELD: +		{ +			vl_pic = VL_TOP_FIELD; +			break; +		} +		case XVMC_BOTTOM_FIELD: +		{ +			vl_pic = VL_BOTTOM_FIELD; +			break; +		} +		case XVMC_FRAME_PICTURE: +		{ +			vl_pic = VL_FRAME_PICTURE; +			break; +		} +		default: +			assert(0); +	} +	 +	return vl_pic; +} + +static enum VL_MC_TYPE MotionToVL(int xvmc_motion_type) +{ +	enum VL_MC_TYPE vl_mc_type; +	 +	switch (xvmc_motion_type) +	{ +		case XVMC_PREDICTION_FRAME: +		{ +			vl_mc_type = VL_FRAME_MC; +			break; +		} +		case XVMC_PREDICTION_FIELD: +		{ +			vl_mc_type = VL_FIELD_MC; +			break; +		} +		case XVMC_PREDICTION_DUAL_PRIME: +		{ +			vl_mc_type = VL_DUAL_PRIME_MC; +			break; +		} +		default: +			assert(0); +	} +	 +	return vl_mc_type; +} + +Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface) +{ +	struct VL_CONTEXT *vl_ctx; +	struct VL_SURFACE *vl_sfc; +	 +	assert(display); +	 +	if (!context) +		return XvMCBadContext; +	if (!surface) +		return XvMCBadSurface; +	 +	vl_ctx = context->privData; +	 +	assert(display == vl_ctx->display); +	 +	vlCreateSurface(vl_ctx, &vl_sfc); +	 +	surface->surface_id = XAllocID(display); +	surface->context_id = context->context_id; +	surface->surface_type_id = context->surface_type_id; +	surface->width = context->width; +	surface->height = context->height; +	surface->privData = vl_sfc; +	 +	return Success; +} + +Status XvMCRenderSurface +( +	Display *display, +	XvMCContext *context, +	unsigned int picture_structure, +	XvMCSurface *target_surface, +	XvMCSurface *past_surface, +	XvMCSurface *future_surface, +	unsigned int flags, +	unsigned int num_macroblocks, +	unsigned int first_macroblock, +	XvMCMacroBlockArray *macroblocks, +	XvMCBlockArray *blocks +) +{ +	struct VL_CONTEXT	*vl_ctx; +	struct VL_SURFACE	*target_vl_surface; +	struct VL_SURFACE	*past_vl_surface; +	struct VL_SURFACE	*future_vl_surface; +	unsigned int		i; +	 +	assert(display); +	 +	if (!context) +		return XvMCBadContext; +	if (!target_surface) +		return XvMCBadSurface; +	 +	if +	( +		picture_structure != XVMC_TOP_FIELD && +		picture_structure != XVMC_BOTTOM_FIELD && +		picture_structure != XVMC_FRAME_PICTURE +	) +		return BadValue; +	if (future_surface && !past_surface) +		return BadMatch; +	 +	vl_ctx = context->privData; +	 +	assert(display == vl_ctx->display); +	 +	target_vl_surface = target_surface->privData; +	past_vl_surface = past_surface ? past_surface->privData : NULL; +	future_vl_surface = future_surface ? future_surface->privData : NULL; +	 +	assert(vl_ctx == target_vl_surface->context); +	assert(!past_vl_surface || vl_ctx == past_vl_surface->context); +	assert(!future_vl_surface || vl_ctx == future_vl_surface->context); +	 +	assert(macroblocks); +	assert(blocks); +	 +	assert(macroblocks->context_id == context->context_id); +	assert(blocks->context_id == context->context_id); +	 +	assert(flags == 0 || flags == XVMC_SECOND_FIELD); +	 +	/* TODO: Batch macroblocks by type (I,P,B) */ +	 +	for (i = first_macroblock; i < first_macroblock + num_macroblocks; ++i) +		if (macroblocks->macro_blocks[i].macroblock_type & XVMC_MB_TYPE_INTRA) +			vlRenderIMacroBlock +			( +				PictureToVL(picture_structure), +				flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST, +				macroblocks->macro_blocks[i].x, +				macroblocks->macro_blocks[i].y, +				macroblocks->macro_blocks[i].coded_block_pattern, +				macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED, +				blocks->blocks + (macroblocks->macro_blocks[i].index * 64), +				target_vl_surface +			); +		else if +		( +			(macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) +			== XVMC_MB_TYPE_MOTION_FORWARD +		) +		{ +			struct VL_MOTION_VECTOR motion_vector = +			{ +				{ +					macroblocks->macro_blocks[i].PMV[0][0][0], +					macroblocks->macro_blocks[i].PMV[0][0][1], +				}, +				{ +					macroblocks->macro_blocks[i].PMV[1][0][0], +					macroblocks->macro_blocks[i].PMV[1][0][1], +				} +			}; +						 +			vlRenderPMacroBlock +			( +				PictureToVL(picture_structure), +				flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST, +				macroblocks->macro_blocks[i].x, +				macroblocks->macro_blocks[i].y, +				MotionToVL(macroblocks->macro_blocks[i].motion_type), +				&motion_vector, +				macroblocks->macro_blocks[i].coded_block_pattern, +				macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED, +				blocks->blocks + (macroblocks->macro_blocks[i].index * 64), +				past_vl_surface, +				target_vl_surface +			); +		} +		else if +		( +			(macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) +			== XVMC_MB_TYPE_MOTION_BACKWARD +		) +		{ +			struct VL_MOTION_VECTOR motion_vector = +			{ +				{ +					macroblocks->macro_blocks[i].PMV[0][1][0], +					macroblocks->macro_blocks[i].PMV[0][1][1], +				}, +				{ +					macroblocks->macro_blocks[i].PMV[1][1][0], +					macroblocks->macro_blocks[i].PMV[1][1][1], +				} +			}; +			 +			vlRenderPMacroBlock +			( +				PictureToVL(picture_structure), +				flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST, +				macroblocks->macro_blocks[i].x, +				macroblocks->macro_blocks[i].y, +				MotionToVL(macroblocks->macro_blocks[i].motion_type), +				&motion_vector, +				macroblocks->macro_blocks[i].coded_block_pattern, +				macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED, +				blocks->blocks + (macroblocks->macro_blocks[i].index * 64), +				future_vl_surface, +				target_vl_surface +			); +		} +		else if +		( +			(macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) +			== (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD) +		) +		{ +			struct VL_MOTION_VECTOR motion_vector[2] = +			{ +				{ +					{ +						macroblocks->macro_blocks[i].PMV[0][0][0], +						macroblocks->macro_blocks[i].PMV[0][0][1], +					}, +					{ +						macroblocks->macro_blocks[i].PMV[1][0][0], +						macroblocks->macro_blocks[i].PMV[1][0][1], +					} +				}, +				{ +					{ +						macroblocks->macro_blocks[i].PMV[0][1][0], +						macroblocks->macro_blocks[i].PMV[0][1][1], +					}, +					{ +						macroblocks->macro_blocks[i].PMV[1][1][0], +						macroblocks->macro_blocks[i].PMV[1][1][1], +					} +				} +			}; +			 +			vlRenderBMacroBlock +			( +				PictureToVL(picture_structure), +				flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST, +				macroblocks->macro_blocks[i].x, +				macroblocks->macro_blocks[i].y, +				MotionToVL(macroblocks->macro_blocks[i].motion_type), +				motion_vector, +				macroblocks->macro_blocks[i].coded_block_pattern, +				macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED, +				blocks->blocks + (macroblocks->macro_blocks[i].index * 64), +				past_vl_surface, +				future_vl_surface, +				target_vl_surface +			); +		} +		else +			fprintf(stderr, "Unrecognized macroblock\n"); +	 +	return Success; +} + +Status XvMCFlushSurface(Display *display, XvMCSurface *surface) +{ +	assert(display); +	 +	if (!surface) +		return XvMCBadSurface; +	 +	/* TODO: Check display & surface match */ +	return Success; +} + +Status XvMCSyncSurface(Display *display, XvMCSurface *surface) +{ +	assert(display); +	 +	if (!surface) +		return XvMCBadSurface; +	 +	return Success; +} + +Status XvMCPutSurface +( +	Display *display, +	XvMCSurface *surface, +	Drawable drawable, +	short srcx, +	short srcy, +	unsigned short srcw, +	unsigned short srch, +	short destx, +	short desty, +	unsigned short destw, +	unsigned short desth, +	int flags +) +{ +	Window			root; +	int			x, y; +	unsigned int		width, height; +	unsigned int		border_width; +	unsigned int		depth; +	struct VL_SURFACE	*vl_sfc; +	 +	assert(display); +	 +	if (!surface) +		return XvMCBadSurface; +		 +	if (XGetGeometry(display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable) +		return BadDrawable; +	 +	assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE); +	 +	/* TODO: Correct for negative srcx,srcy & destx,desty by clipping */ +	 +	assert(srcx + srcw - 1 < surface->width); +	assert(srcy + srch - 1 < surface->height); +	assert(destx + destw - 1 < width); +	assert(desty + desth - 1 < height); +	 +	vl_sfc = surface->privData; +	 +	vlPutSurface(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, PictureToVL(flags)); +	 +	return Success; +} + +Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status) +{ +	struct VL_CONTEXT *vl_ctx; +	struct VL_SURFACE *vl_sfc; +	 +	assert(display); +	 +	if (!surface) +		return XvMCBadSurface; +		 +	assert(status); +	 +	vl_sfc = surface->privData; +	vl_ctx = vl_sfc->context; +	 +	assert(display == vl_ctx->display); +	 +	/* TODO */ +	*status = 0; +	 +	return Success; +} + +Status XvMCDestroySurface(Display *display, XvMCSurface *surface) +{ +	struct VL_CONTEXT *vl_ctx; +	struct VL_SURFACE *vl_sfc; +	 +	assert(display); +	 +	if (!surface) +		return XvMCBadSurface; +	 +	vl_sfc = surface->privData; +	vl_ctx = vl_sfc->context; +	 +	assert(display == vl_ctx->display); +	 +	vlDestroySurface(vl_sfc); +	 +	return Success; +} + +Status XvMCHideSurface(Display *display, XvMCSurface *surface) +{ +	struct VL_CONTEXT *vl_ctx; +	struct VL_SURFACE *vl_sfc; +	 +	assert(display); +	 +	if (!surface) +		return XvMCBadSurface; +	 +	vl_sfc = surface->privData; +	vl_ctx = vl_sfc->context; +	 +	assert(display == vl_ctx->display); +	 +	/* No op, only for overlaid rendering */ +	 +	return Success; +} + diff --git a/src/libXvMC/tests/.gitignore b/src/libXvMC/tests/.gitignore new file mode 100644 index 0000000000..eb1ef8a076 --- /dev/null +++ b/src/libXvMC/tests/.gitignore @@ -0,0 +1,5 @@ +test_context +test_surface +test_blocks +test_rendering + diff --git a/src/libXvMC/tests/Makefile b/src/libXvMC/tests/Makefile new file mode 100644 index 0000000000..2cbc97e88b --- /dev/null +++ b/src/libXvMC/tests/Makefile @@ -0,0 +1,25 @@ +CFLAGS	+= -g -Wall -Werror +LDFLAGS	+= +LIBS	+= -lXvMCW -lXvMC -lXv + +############################################# + +.PHONY	= all clean + +all: test_context test_surface test_blocks test_rendering + +test_context: test_context.o testlib.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_surface: test_surface.o testlib.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_blocks: test_blocks.o testlib.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +test_rendering: test_rendering.o testlib.o +	$(CC) ${LDFLAGS} -o $@ $^ ${LIBS} + +clean: +	rm -rf *.o test_context test_surface test_blocks test_rendering + diff --git a/src/libXvMC/tests/test_blocks.c b/src/libXvMC/tests/test_blocks.c new file mode 100644 index 0000000000..0b895ee773 --- /dev/null +++ b/src/libXvMC/tests/test_blocks.c @@ -0,0 +1,95 @@ +#include <assert.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ +	const unsigned int	width = 16, height = 16; +	const unsigned int	min_required_blocks = 1, min_required_macroblocks = 1; +	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; +	 +	Display			*display; +	XvPortID		port_num; +	int			surface_type_id; +	unsigned int		is_overlay, intra_unsigned; +	int			colorkey; +	XvMCContext		context; +	XvMCSurface		surface; +	XvMCBlockArray		blocks = {0}; +	XvMCMacroBlockArray	macroblocks = {0}; +	 +	display = XOpenDisplay(NULL); +	 +	if (!GetPort +	( +		display, +		width, +		height, +		XVMC_CHROMA_FORMAT_420, +    		mc_types, +    		2, +    		&port_num, +    		&surface_type_id, +    		&is_overlay, +    		&intra_unsigned +	)) +	{ +		XCloseDisplay(display); +		error(1, 0, "Error, unable to find a good port.\n"); +	} +	 +	if (is_overlay) +	{ +		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); +		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); +	} +	 +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); +	assert(XvMCCreateSurface(display, &context, &surface) == Success); +	 +	/* Test NULL context */ +	assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext); +	/* Test 0 blocks */ +	assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue); +	/* Test too many blocks */ +	/*assert(XvMCCreateBlocks(display, &context, 16384, &blocks) == BadAlloc);*/ +	 +	/* Note: No XvMCBadBlock(s) error in spec */ +	 +	/* Test valid params */ +	assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success); +	/* Test context id assigned and correct */ +	assert(blocks.context_id == context.context_id); +	/* Test number of blocks assigned and correct */ +	assert(blocks.num_blocks == min_required_blocks); +	/* Test block pointer valid */ +	assert(blocks.blocks != NULL); +	/* Test NULL context */ +	assert(XvMCCreateMacroBlocks(display, NULL, 1, ¯oblocks) == XvMCBadContext); +	/* Test 0 macroblocks */ +	assert(XvMCCreateMacroBlocks(display, &context, 0, ¯oblocks) == BadValue); +	/* Test too many macroblocks */ +	/*assert(XvMCCreateMacroBlocks(display, &context, 16384, ¯oblocks) == BadAlloc);*/ + +	/* Note: No XvMCBadMacroBlock(s) error in spec */ + +	/* Test valid params */ +	assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, ¯oblocks) == Success); +	/* Test context id assigned and correct */ +	assert(macroblocks.context_id == context.context_id); +	/* Test macroblock pointer valid */ +	assert(macroblocks.macro_blocks != NULL); +	/* Test valid params */ +	assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success); +	/* Test valid params */ +	assert(XvMCDestroyBlocks(display, &blocks) == Success); +	 +	assert(XvMCDestroySurface(display, &surface) == Success); +	assert(XvMCDestroyContext(display, &context) == Success); +	 +	XvUngrabPort(display, port_num, CurrentTime); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/libXvMC/tests/test_context.c b/src/libXvMC/tests/test_context.c new file mode 100644 index 0000000000..22afb7ada4 --- /dev/null +++ b/src/libXvMC/tests/test_context.c @@ -0,0 +1,94 @@ +#include <assert.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ +	const unsigned int	width = 16, height = 16; +	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; +	 +	Display			*display; +	XvPortID		port_num; +	int			surface_type_id; +	unsigned int		is_overlay, intra_unsigned; +	int			colorkey; +	XvMCContext		context = {0}; +	 +	display = XOpenDisplay(NULL); +	 +	if (!GetPort +	( +		display, +		width, +		height, +		XVMC_CHROMA_FORMAT_420, +    		mc_types, +    		2, +    		&port_num, +    		&surface_type_id, +    		&is_overlay, +    		&intra_unsigned +	)) +	{ +		XCloseDisplay(display); +		error(1, 0, "Error, unable to find a good port.\n"); +	} +	 +	if (is_overlay) +	{ +		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); +		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); +	} +	 +	/* Note: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */ +	/* Note: Nvidia binary driver segfaults on NULL context, halts with debug output on bad port */ +	 +	/* Test NULL context */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext); +	/* Test invalid port */ +	assert(XvMCCreateContext(display, port_num + 1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort); +	/* Test invalid surface */ +	assert(XvMCCreateContext(display, port_num, surface_type_id + 1, width, height, XVMC_DIRECT, &context) == BadMatch); +	/* Test invalid flags */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue); +	/* Test huge width */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue); +	/* Test huge height */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue); +	/* Test huge width & height */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue); +	/* Test valid params */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); +	/* Test context id assigned */ +	assert(context.context_id != 0); +	/* Test surface type id assigned and correct */ +	assert(context.surface_type_id == surface_type_id); +	/* Test width & height assigned and correct */ +	assert(context.width == width && context.height == height); +	/* Test port assigned and correct */ +	assert(context.port == port_num); +	/* Test flags assigned and correct */ +	assert(context.flags == XVMC_DIRECT); +	/* Test NULL context */ +	assert(XvMCDestroyContext(display, NULL) == XvMCBadContext); +	/* Test valid params */ +	assert(XvMCDestroyContext(display, &context) == Success); +	/* Test awkward but valid width */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success); +	assert(context.width >= width + 1); +	assert(XvMCDestroyContext(display, &context) == Success); +	/* Test awkward but valid height */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success); +	assert(context.height >= height + 1); +	assert(XvMCDestroyContext(display, &context) == Success); +	/* Test awkward but valid width & height */ +	assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success); +	assert(context.width >= width + 1 && context.height >= height + 1); +	assert(XvMCDestroyContext(display, &context) == Success); +	 +	XvUngrabPort(display, port_num, CurrentTime); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/libXvMC/tests/test_rendering.c b/src/libXvMC/tests/test_rendering.c new file mode 100644 index 0000000000..1914b1fb62 --- /dev/null +++ b/src/libXvMC/tests/test_rendering.c @@ -0,0 +1,153 @@ +#include <assert.h> +#include <stdio.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ +	const unsigned int	width = 32, height = 32; +	const unsigned int	mwidth = width / 16, mheight = height / 16; +	const unsigned int	num_macroblocks = mwidth * mheight; +	const unsigned int	num_blocks = num_macroblocks * 6; +	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; +	 +	int			quit = 0; +	Display			*display; +	Window			root, window; +	Pixmap			framebuffer; +	XEvent			event; +	XvPortID		port_num; +	int			surface_type_id; +	unsigned int		is_overlay, intra_unsigned; +	int			colorkey; +	XvMCContext		context; +	XvMCSurface		surface; +	XvMCBlockArray		blocks; +	XvMCMacroBlockArray	macroblocks; +	unsigned int		b, x, y; +	 +	display = XOpenDisplay(NULL); +	 +	if (!GetPort +	( +		display, +		width, +		height, +		XVMC_CHROMA_FORMAT_420, +    		mc_types, +    		2, +    		&port_num, +    		&surface_type_id, +    		&is_overlay, +    		&intra_unsigned +	)) +	{ +		XCloseDisplay(display); +		error(1, 0, "Error, unable to find a good port.\n"); +	} +	 +	if (is_overlay) +	{ +		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); +		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); +	} +	 +	root = XDefaultRootWindow(display); +	window = XCreateSimpleWindow(display, root, 0, 0, width, height, 0, 0, colorkey); +	framebuffer = XCreatePixmap(display, root, width, height, 24); +	 +	XSelectInput(display, window, ExposureMask | KeyPressMask); +	XMapWindow(display, window); +	XSync(display, 0); +	 +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); +	assert(XvMCCreateSurface(display, &context, &surface) == Success); +	assert(XvMCCreateBlocks(display, &context, num_blocks, &blocks) == Success); +	assert(XvMCCreateMacroBlocks(display, &context, num_macroblocks, ¯oblocks) == Success); +	 +	for (b = 0; b < 6; ++b) +	{ +		for (y = 0; y < 8; ++y) +		{ +			for (x = 0; x < 8; ++x) +			{ +				blocks.blocks[b * 64 + y * 8 + x] = 0xFFFF; +			} +		} +	} +	 +	for (y = 0; y < mheight; ++y) +	{ +		for (x = 0; x < mwidth; ++x) +		{ +			macroblocks.macro_blocks[y * mwidth + x].x = x; +			macroblocks.macro_blocks[y * mwidth + x].y = y; +			macroblocks.macro_blocks[y * mwidth + x].index = (y * mwidth + x) * 6; +			macroblocks.macro_blocks[y * mwidth + x].macroblock_type = XVMC_MB_TYPE_INTRA; +			macroblocks.macro_blocks[y * mwidth + x].coded_block_pattern = 0x3F; +			macroblocks.macro_blocks[y * mwidth + x].dct_type = XVMC_DCT_TYPE_FRAME; +		} +	} +	 +	/* Test NULL context */ +	assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, 1, 0, ¯oblocks, &blocks) == XvMCBadContext); +	/* Test NULL surface */ +	assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, 1, 0, ¯oblocks, &blocks) == XvMCBadSurface); +	/* Test bad picture structure */ +	assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, 1, 0, ¯oblocks, &blocks) == BadValue); +	/* Test valid params */ +	assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, num_macroblocks, 0, ¯oblocks, &blocks) == Success); +	 +	/* Test NULL surface */ +	assert(XvMCPutSurface(display, NULL, window, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == XvMCBadSurface); +	/* Test bad window */ +	/* X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */ +	/*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/ +	/* Test valid params */ +	assert(XvMCPutSurface(display, &surface, framebuffer, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == Success); +	 +	puts("Press any key to continue..."); +	 +	while (!quit) +	{ +		XNextEvent(display, &event); +		switch (event.type) +		{ +			case Expose: +			{ +				XCopyArea +				( +					display, +					framebuffer, +					window, +					XDefaultGC(display, XDefaultScreen(display)), +					0, +					0, +					width, +					height, +					0, +					0 +				); +				break; +			} +			case KeyPress: +			{ +				quit = 1; +				break; +			} +		} +	} +	 +	assert(XvMCDestroyBlocks(display, &blocks) == Success); +	assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success); +	assert(XvMCDestroySurface(display, &surface) == Success);	 +	assert(XvMCDestroyContext(display, &context) == Success); +	 +	XFreePixmap(display, framebuffer); +	XvUngrabPort(display, port_num, CurrentTime); +	XDestroyWindow(display, window); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/libXvMC/tests/test_surface.c b/src/libXvMC/tests/test_surface.c new file mode 100644 index 0000000000..25ebdcc4fc --- /dev/null +++ b/src/libXvMC/tests/test_surface.c @@ -0,0 +1,72 @@ +#include <assert.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ +	const unsigned int	width = 16, height = 16; +	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; +	 +	Display			*display; +	XvPortID		port_num; +	int			surface_type_id; +	unsigned int		is_overlay, intra_unsigned; +	int			colorkey; +	XvMCContext		context; +	XvMCSurface		surface = {0}; +	 +	display = XOpenDisplay(NULL); +	 +	if (!GetPort +	( +		display, +		width, +		height, +		XVMC_CHROMA_FORMAT_420, +    		mc_types, +    		2, +    		&port_num, +    		&surface_type_id, +    		&is_overlay, +    		&intra_unsigned +	)) +	{ +		XCloseDisplay(display); +		error(1, 0, "Error, unable to find a good port.\n"); +	} +	 +	if (is_overlay) +	{ +		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); +		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); +	} +	 +	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); +	 +	/* Test NULL context */ +	assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext); +	/* Test NULL surface */ +	assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface); +	/* Test valid params */ +	assert(XvMCCreateSurface(display, &context, &surface) == Success); +	/* Test surface id assigned */ +	assert(surface.surface_id != 0); +	/* Test context id assigned and correct */ +	assert(surface.context_id == context.context_id); +	/* Test surface type id assigned and correct */ +	assert(surface.surface_type_id == surface_type_id); +	/* Test width & height assigned and correct */ +	assert(surface.width == width && surface.height == height); +	/* Test valid params */ +	assert(XvMCDestroySurface(display, &surface) == Success); +	/* Test NULL surface */ +	assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface); +	 +	assert(XvMCDestroyContext(display, &context) == Success); +	 +	XvUngrabPort(display, port_num, CurrentTime); +	XCloseDisplay(display); +	 +	return 0; +} + diff --git a/src/libXvMC/tests/testlib.c b/src/libXvMC/tests/testlib.c new file mode 100644 index 0000000000..8672aa9999 --- /dev/null +++ b/src/libXvMC/tests/testlib.c @@ -0,0 +1,87 @@ +#include "testlib.h" +#include <stdio.h> + +/* +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line) +{ +	fputs(doc_string, stderr); +	if (!pred) +		fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line); +	else +		fputs(" PASS!\n", stderr); +} +*/ + +int GetPort +( +	Display *display, +	unsigned int width, +	unsigned int height, +	unsigned int chroma_format, +	const unsigned int *mc_types, +	unsigned int num_mc_types, +	XvPortID *port_id, +	int *surface_type_id, +	unsigned int *is_overlay, +	unsigned int *intra_unsigned +) +{ +	unsigned int	found_port = 0; +	XvAdaptorInfo	*adaptor_info; +	unsigned int	num_adaptors; +	int		num_types; +	int		ev_base, err_base; +	unsigned int	i, j, k, l; +	 +	if (!XvMCQueryExtension(display, &ev_base, &err_base)) +		return 0; +	if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success) +		return 0; +	 +	for (i = 0; i < num_adaptors && !found_port; ++i) +	{ +		if (adaptor_info[i].type & XvImageMask) +		{ +			XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); +			 +			if (surface_info) +			{ +				for (j = 0; j < num_types && !found_port; ++j) +				{ +					if +					( +						surface_info[j].chroma_format == chroma_format && +						surface_info[j].max_width >= width && +						surface_info[j].max_height >= height +					) +					{ +						for (k = 0; k < num_mc_types && !found_port; ++k) +						{ +							if (surface_info[j].mc_type == mc_types[k]) +							{ +								for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l) +								{ +									if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success) +									{ +										*port_id = adaptor_info[i].base_id + l; +										*surface_type_id = surface_info[j].surface_type_id; +										*is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE; +										*intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED; +										found_port = 1; +									} +								} +							} +						} +					} +				} +				 +				XFree(surface_info); +			} +		} +	} +	 +	XvFreeAdaptorInfo(adaptor_info); +	 +	return found_port; +} + diff --git a/src/libXvMC/tests/testlib.h b/src/libXvMC/tests/testlib.h new file mode 100644 index 0000000000..c73845807e --- /dev/null +++ b/src/libXvMC/tests/testlib.h @@ -0,0 +1,38 @@ +#ifndef testlib_h +#define testlib_h + +/* +#define TEST(pred, doc)	test(pred, #pred, doc, __FILE__, __LINE__) + +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line); +*/ + +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> + +/* + * display: IN			A valid X display + * width, height: IN		Surface size that the port must display + * chroma_format: IN		Chroma format that the port must display + * mc_types, num_mc_types: IN	List of MC types that the port must support, first port that matches the first mc_type will be returned + * port_id: OUT			Your port's ID + * surface_type_id: OUT		Your port's surface ID + * is_overlay: OUT		If 1, port uses overlay surfaces, you need to set a colorkey + * intra_unsigned: OUT		If 1, port uses unsigned values for intra-coded blocks + */ +int GetPort +( +	Display *display, +	unsigned int width, +	unsigned int height, +	unsigned int chroma_format, +	const unsigned int *mc_types, +	unsigned int num_mc_types, +	XvPortID *port_id, +	int *surface_type_id, +	unsigned int *is_overlay, +	unsigned int *intra_unsigned +); + +#endif + diff --git a/src/mesa/x86-64/glapi_x86-64.S b/src/mesa/x86-64/glapi_x86-64.S index f8337ff93e..cb34061b36 100644 --- a/src/mesa/x86-64/glapi_x86-64.S +++ b/src/mesa/x86-64/glapi_x86-64.S @@ -73,7 +73,7 @@ _x86_64_get_dispatch:  	.p2align	4,,15  _x86_64_get_dispatch: -	movq	_gl_DispatchTSD@GOTPCREL(%rip), %rdi +	movq	_gl_DispatchTSD(%rip), %rdi  	jmp	pthread_getspecific@PLT  #elif defined(THREADS)  | 
