linux-directfb-install:
cd src/mesa/drivers/directfb && $(MAKE) install
+# Xserver GLcore module
+glcore:
+ cd src/mesa/drivers/xorg ; $(MAKE)
+
+glcore-install:
+ cd src/mesa/drivers/xorg ; $(MAKE) install
+
# If there's no current configuration file
$(TOP)/configs/current:
@echo
$(DIRECTORY)/src/mesa/depend \
$(DIRECTORY)/src/mesa/main/*.[chS] \
$(DIRECTORY)/src/mesa/main/descrip.mms \
- $(DIRECTORY)/src/mesa/main/sources \
$(DIRECTORY)/src/mesa/glapi/*.[chS] \
$(DIRECTORY)/src/mesa/glapi/descrip.mms \
- $(DIRECTORY)/src/mesa/glapi/sources \
$(DIRECTORY)/src/mesa/math/*.[ch] \
$(DIRECTORY)/src/mesa/math/descrip.mms \
- $(DIRECTORY)/src/mesa/math/sources \
$(DIRECTORY)/src/mesa/shader/*.[ch] \
$(DIRECTORY)/src/mesa/shader/descrip.mms \
- $(DIRECTORY)/src/mesa/shader/sources \
$(DIRECTORY)/src/mesa/shader/grammar/*.[ch] \
$(DIRECTORY)/src/mesa/shader/grammar/descrip.mms \
- $(DIRECTORY)/src/mesa/shader/grammar/sources \
$(DIRECTORY)/src/mesa/shader/slang/*.[ch] \
$(DIRECTORY)/src/mesa/shader/slang/descrip.mms \
- $(DIRECTORY)/src/mesa/shader/slang/sources \
$(DIRECTORY)/src/mesa/shader/slang/library/*.[ch] \
$(DIRECTORY)/src/mesa/shader/slang/library/*.gc \
$(DIRECTORY)/src/mesa/shader/slang/library/*.syn \
$(DIRECTORY)/src/mesa/shader/slang/library/Makefile \
$(DIRECTORY)/src/mesa/swrast/*.[ch] \
$(DIRECTORY)/src/mesa/swrast/descrip.mms \
- $(DIRECTORY)/src/mesa/swrast/sources \
$(DIRECTORY)/src/mesa/swrast_setup/*.[ch] \
$(DIRECTORY)/src/mesa/swrast_setup/descrip.mms \
- $(DIRECTORY)/src/mesa/swrast_setup/sources \
$(DIRECTORY)/src/mesa/vbo/*.[chS] \
$(DIRECTORY)/src/mesa/vbo/descrip.mms \
$(DIRECTORY)/src/mesa/tnl/*.[chS] \
$(DIRECTORY)/src/mesa/tnl/descrip.mms \
- $(DIRECTORY)/src/mesa/tnl/sources \
$(DIRECTORY)/src/mesa/tnl_dd/*.[ch] \
$(DIRECTORY)/src/mesa/tnl_dd/imm/*.[ch] \
$(DIRECTORY)/src/mesa/tnl_dd/imm/NOTES.imm \
$(DIRECTORY)/src/mesa/drivers/beos/Makefile \
$(DIRECTORY)/src/mesa/drivers/common/*.[ch] \
$(DIRECTORY)/src/mesa/drivers/common/descrip.mms \
- $(DIRECTORY)/src/mesa/drivers/common/sources \
$(DIRECTORY)/src/mesa/drivers/directfb/*.[ch] \
$(DIRECTORY)/src/mesa/drivers/directfb/Makefile \
$(DIRECTORY)/src/mesa/drivers/dos/*.[chS] \
$(DIRECTORY)/src/mesa/drivers/windows/*/*.[ch] \
$(DIRECTORY)/src/mesa/drivers/windows/*/*.def \
$(DIRECTORY)/src/mesa/drivers/x11/descrip.mms \
- $(DIRECTORY)/src/mesa/drivers/x11/sources \
$(DIRECTORY)/src/mesa/drivers/x11/*.[ch] \
$(DIRECTORY)/src/mesa/ppc/*.[ch] \
$(DIRECTORY)/src/mesa/sparc/*.[chS] \
# This is generated by configure
CONFIG_NAME = autoconf
-# Version info
-MESA_MAJOR = @MESA_MAJOR@
-MESA_MINOR = @MESA_MINOR@
-MESA_TINY = @MESA_TINY@
-
# Compiler and flags
CC = @CC@
CXX = @CXX@
$(EXTRA_LIB_PATH) @GLW_LIB_DEPS@
APP_LIB_DEPS = $(EXTRA_LIB_PATH) @APP_LIB_DEPS@
+# GLcore dependencies
+GLCORE_LIB_DEPS = $(EXTRA_LIB_PATH) @GLCORE_LIB_DEPS@
+
# DRI dependencies
DRI_LIB_DEPS = $(EXTRA_LIB_PATH) @DRI_LIB_DEPS@
LIBDRM_CFLAGS = @LIBDRM_CFLAGS@
DRI_LIB_DEPS = -L/usr/local/lib -lm -pthread -lexpat $(LIBDRM_LIB)
GL_LIB_DEPS = -L/usr/local/lib -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
-lm -pthread $(LIBDRM_LIB)
+GLCORE_LIB_DEPS = -lm -pthread
GLUT_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -L/usr/local/lib -lGLU -lGL -lX11 -lXmu -lXt -lXi -lm
GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -L/usr/local/lib -lGL -lXt -lX11
LIBDRM_LIB = `pkg-config --libs libdrm`
DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
- -lm -lpthread -ldl \
- $(LIBDRM_LIB)
+ -lm -lpthread -ldl $(LIBDRM_LIB)
+GLCORE_LIB_DEPS = -lm -lpthread -ldl
# This is now 0 by default since it seems to confuse the hell out of people
dnl Versioning
dnl Make version number available to autoconf and configure
-m4_define(mesa_major, 7)
-m4_define(mesa_minor, 1)
-m4_define(mesa_tiny, 0)
-m4_define(mesa_version, [mesa_major().mesa_minor().mesa_tiny()])
+m4_define([mesa_version],[7.1.0])
AC_INIT([Mesa],[mesa_version()],
[https://bugs.freedesktop.org/enter_bug.cgi?product=Mesa])
AC_CONFIG_AUX_DIR(bin)
AC_CANONICAL_HOST
-dnl Substitute the version number into shell variables
-MESA_MAJOR=mesa_major()
-MESA_MINOR=mesa_minor()
-MESA_TINY=mesa_tiny()
-AC_SUBST(MESA_MAJOR)
-AC_SUBST(MESA_MINOR)
-AC_SUBST(MESA_TINY)
-
dnl Check for progs
AC_PROG_CPP
AC_PROG_CC
dnl Make sure the pkg-config macros are defined
m4_ifdef([PKG_PROG_PKG_CONFIG],,[
- AC_MSG_ERROR([The pkg-config autoconf macros are not defined.
- Did you run 'make configure'?])]
-)
+ m4_errprint([Error: Could not locate the pkg-config autoconf macros.
+ These are usually located in /usr/share/aclocal/pkg.m4. If your
+ macros are in a different location, try setting the environment
+ variable ACLOCAL="aclocal -I/other/macro/dir" before running
+ autoreconf.
+])
+ m4_exit([1])
+])
PKG_PROG_PKG_CONFIG()
dnl LIB_DIR - library basename
dnl Driver configuration. Options are xlib, dri and osmesa right now.
dnl More later: directfb, fbdev, ...
dnl
+default_driver="xlib"
+
+case "$host_os" in
+linux*)
+ case "$host_cpu" in
+ i*86|x86_64|powerpc*) default_driver="dri";;
+ esac
+ ;;
+freebsd* | dragonfly*)
+ case "$host_cpu" in
+ i*86|x86_64) default_driver="dri";;
+ esac
+ ;;
+esac
+
AC_ARG_WITH(driver,
[AS_HELP_STRING([--with-driver=DRIVER],
- [driver for Mesa: xlib,dri,osmesa @<:@default=xlib@:>@])],
+ [driver for Mesa: xlib,dri,osmesa @<:@default=dri when available, or xlib@:>@])],
mesa_driver="$withval",
- mesa_driver="xlib")
+ mesa_driver="$default_driver")
dnl Check for valid option
case "x$mesa_driver" in
xxlib|xdri|xosmesa)
GL_LIB_DEPS="$X_LIBS -lX11 -lXext"
fi
GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread"
+ GLCORE_LIB_DEPS=""
# if static, move the external libraries to the programs
# and empty the libraries for libGL
# need DRM libs, -lpthread, etc.
GL_LIB_DEPS="$GL_LIB_DEPS $LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS"
+ GLCORE_LIB_DEPS="-lm -lpthread $DLOPEN_LIBS"
;;
osmesa)
# No libGL for osmesa
GL_LIB_DEPS=""
+ GLCORE_LIB_DEPS=""
;;
esac
AC_SUBST(GL_LIB_DEPS)
+AC_SUBST(GLCORE_LIB_DEPS)
dnl
dnl More X11 setup
#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+
+/************************************************************************/
+
+#ifdef _NEED_GL_CORE_IF
+
+/**
+ * The GLcore interface (a subset of the XMesa interface)
+ */
+#define __GL_CORE "GL_Core"
+
+typedef struct __GLcoreModuleRec {
+ /*
+ * XMesaVisual
+ */
+ XMesaVisual (*XMesaCreateVisual)( ScreenPtr display,
+ VisualPtr visinfo,
+ GLboolean rgb_flag,
+ GLboolean alpha_flag,
+ GLboolean db_flag,
+ GLboolean stereo_flag,
+ GLboolean ximage_flag,
+ GLint depth_size,
+ GLint stencil_size,
+ GLint accum_red_size,
+ GLint accum_green_size,
+ GLint accum_blue_size,
+ GLint accum_alpha_size,
+ GLint num_samples,
+ GLint level,
+ GLint visualCaveat );
+
+ void (*XMesaDestroyVisual)( XMesaVisual v );
+
+ /*
+ * XMesaBuffer
+ */
+ XMesaBuffer (*XMesaCreateWindowBuffer)( XMesaVisual v,
+ WindowPtr w );
+
+ XMesaBuffer (*XMesaCreatePixmapBuffer)( XMesaVisual v,
+ PixmapPtr p,
+ ColormapPtr cmap );
+
+ void (*XMesaDestroyBuffer)( XMesaBuffer b );
+
+ void (*XMesaSwapBuffers)( XMesaBuffer b );
+
+ void (*XMesaResizeBuffers)( XMesaBuffer b );
+
+ /*
+ * XMesaContext
+ */
+ XMesaContext (*XMesaCreateContext)( XMesaVisual v,
+ XMesaContext share_list );
+
+ void (*XMesaDestroyContext)( XMesaContext c );
+
+ GLboolean (*XMesaCopyContext)( XMesaContext src,
+ XMesaContext dst,
+ GLuint mask );
+
+ GLboolean (*XMesaMakeCurrent2)( XMesaContext c,
+ XMesaBuffer drawBuffer,
+ XMesaBuffer readBuffer );
+
+ GLboolean (*XMesaForceCurrent)( XMesaContext c );
+
+ GLboolean (*XMesaLoseCurrent)( XMesaContext c );
+
+} __GLcoreModule;
+
+#endif /* _NEED_GL_CORE_IF */
+
#endif /* __gl_core_h_ */
glDisable(GL_FRAGMENT_PROGRAM_ARB);
}
+ glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
}
overlay \
pbinfo \
pbdemo \
+ sharedtex \
texture_from_pixmap \
wincopy \
xfont \
--- /dev/null
+/*
+ * Test sharing of texture objects by two rendering contexts.
+ * In particular, test that changing a texture object in one context
+ * effects the texture in the second context.
+ *
+ * Brian Paul
+ * 30 Apr 2008
+ *
+ * Copyright (C) 2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/keysym.h>
+
+
+#define MAX_CONTEXTS 2
+
+#define TEX_SIZE 32
+
+static const char *DisplayName = NULL;
+static Display *Dpy;
+static XVisualInfo *VisInfo;
+static Window Win;
+static GLXContext Contexts[MAX_CONTEXTS];
+static int WinWidth = 300, WinHeight = 300;
+
+static int DrawContext = 0, TexContext = 1;
+
+static GLuint TexObj = 0;
+static GLboolean NewTexture = GL_FALSE;
+
+
+static void
+Error(const char *msg)
+{
+ fprintf(stderr, "sharedtex error: %s\n", msg);
+ exit(1);
+}
+
+
+static void
+CreateWindow(const char *name)
+{
+ int attrib[] = { GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+ int scrnum;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+ int xpos = 0, ypos = 0;
+ static int n = 0;
+
+ scrnum = DefaultScreen(Dpy);
+ root = RootWindow(Dpy, scrnum);
+
+ VisInfo = glXChooseVisual(Dpy, scrnum, attrib);
+ if (!VisInfo) {
+ Error("Unable to find RGB, double-buffered visual");
+ }
+
+ /* window attributes */
+ xpos = (n % 10) * 100;
+ ypos = (n / 10) * 100;
+ n++;
+
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(Dpy, root, VisInfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ Win = XCreateWindow(Dpy, root, xpos, ypos, WinWidth, WinHeight,
+ 0, VisInfo->depth, InputOutput,
+ VisInfo->visual, mask, &attr);
+ if (!Win) {
+ Error("Couldn't create window");
+ }
+
+ {
+ XSizeHints sizehints;
+ sizehints.x = xpos;
+ sizehints.y = ypos;
+ sizehints.width = WinWidth;
+ sizehints.height = WinHeight;
+ sizehints.flags = USSize | USPosition;
+ XSetNormalHints(Dpy, Win, &sizehints);
+ XSetStandardProperties(Dpy, Win, name, name,
+ None, (char **)NULL, 0, &sizehints);
+ }
+
+ XMapWindow(Dpy, Win);
+}
+
+
+/**
+ * Change texture image, using TexContext
+ */
+static void
+ModifyTexture(void)
+{
+ GLuint tex[TEX_SIZE][TEX_SIZE];
+ GLuint c0, c1;
+ int i, j;
+
+ if (Win && !glXMakeCurrent(Dpy, Win, Contexts[TexContext])) {
+ Error("glXMakeCurrent failed");
+ }
+
+ /* choose two random colors */
+ c0 = rand() & 0xffffffff;
+ c1 = rand() & 0xffffffff;
+
+ for (i = 0; i < TEX_SIZE; i++) {
+ for (j = 0; j < TEX_SIZE; j++) {
+ if (((i / 4) ^ (j / 4)) & 1) {
+ tex[i][j] = c0;
+ }
+ else {
+ tex[i][j] = c1;
+ }
+ }
+ }
+
+ glBindTexture(GL_TEXTURE_2D, TexObj);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, tex);
+
+ NewTexture = GL_TRUE;
+}
+
+
+static void
+InitContext(void)
+{
+ glGenTextures(1, &TexObj);
+ assert(TexObj);
+ glBindTexture(GL_TEXTURE_2D, TexObj);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glEnable(GL_TEXTURE_2D);
+
+ printf("GL_RENDERER = %s\n", (char*) glGetString(GL_RENDERER));
+}
+
+
+static void
+Setup(void)
+{
+ int i;
+
+ Dpy = XOpenDisplay(DisplayName);
+ if (!Dpy) {
+ Error("Unable to open display");
+ }
+
+ CreateWindow("sharedtex");
+
+ for (i = 0; i < MAX_CONTEXTS; i++) {
+ GLXContext share = i > 0 ? Contexts[0] : 0;
+
+ Contexts[i] = glXCreateContext(Dpy, VisInfo, share, True);
+ if (!Contexts[i]) {
+ Error("Unable to create GLX context");
+ }
+
+ if (!glXMakeCurrent(Dpy, Win, Contexts[i])) {
+ Error("glXMakeCurrent failed");
+ }
+
+ InitContext();
+ }
+
+ ModifyTexture();
+}
+
+
+/**
+ * Redraw window, using DrawContext
+ */
+static void
+Redraw(void)
+{
+ static float rot = 0.0;
+ float ar;
+
+ rot += 1.0;
+
+ if (Win && !glXMakeCurrent(Dpy, Win, Contexts[DrawContext])) {
+ Error("glXMakeCurrent failed");
+ }
+
+ glViewport(0, 0, WinWidth, WinHeight);
+ ar = (float) WinWidth / (float) WinHeight;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-ar, ar, -1.0, 1.0, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_FLAT);
+ glClearColor(0.5, 0.5, 0.5, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glPushMatrix();
+ glRotatef(rot, 0, 0, 1);
+ glScalef(0.7, 0.7, 0.7);
+
+ if (NewTexture) {
+ /* rebind to get new contents */
+ glBindTexture(GL_TEXTURE_2D, TexObj);
+ NewTexture = GL_FALSE;
+ }
+
+ /* draw textured quad */
+ glBegin(GL_POLYGON);
+ glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, -1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, 1.0 );
+ glEnd();
+
+ glPopMatrix();
+
+ if (Win)
+ glXSwapBuffers(Dpy, Win);
+}
+
+
+static void
+EventLoop(void)
+{
+ while (1) {
+ while (XPending(Dpy) > 0) {
+ XEvent event;
+ XNextEvent(Dpy, &event);
+
+ switch (event.type) {
+ case Expose:
+ Redraw();
+ break;
+ case ConfigureNotify:
+ WinWidth = event.xconfigure.width;
+ WinHeight = event.xconfigure.height;
+ break;
+ case KeyPress:
+ {
+ char buf[100];
+ KeySym keySym;
+ XComposeStatus stat;
+ XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+ switch (keySym) {
+ case XK_Escape:
+ exit(0);
+ break;
+ case XK_t:
+ case XK_T:
+ ModifyTexture();
+ break;
+ default:
+ ;
+ }
+ }
+ Redraw();
+ break;
+ default:
+ /*no-op*/ ;
+ }
+ }
+
+ Redraw();
+ usleep(10000);
+ }
+}
+
+
+
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-display") == 0 && i < argc) {
+ DisplayName = argv[i+1];
+ i++;
+ }
+ }
+
+ Setup();
+
+ printf("Press 't' to change texture image/colors\n");
+
+ EventLoop();
+
+ return 0;
+}
compsize.c \
eval.c \
glxcmds.c \
+ glxcurrent.c \
glxext.c \
glxextensions.c \
indirect.c \
indirect_init.c \
indirect_size.c \
indirect_window_pos.c \
+ indirect_texture_compression.c \
indirect_transpose_matrix.c \
indirect_vertex_array.c \
indirect_vertex_program.c \
xfont.c \
glx_pbuffer.c \
glx_query.c \
- glx_texture_compression.c \
dri_glx.c \
XF86dri.c \
glxhash.c \
#ifdef GLX_DIRECT_RENDERING
#include <unistd.h>
-#include <X11/Xlibint.h>
-#include <X11/extensions/Xext.h>
-#include <X11/extensions/extutil.h>
+#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xdamage.h>
#include "glheader.h"
#include "glxclient.h"
+#include "glcontextmodes.h"
#include "xf86dri.h"
#include "sarea.h"
-#include <stdio.h>
#include <dlfcn.h>
#include <sys/types.h>
-#include <stdarg.h>
-#include "glcontextmodes.h"
#include <sys/mman.h>
#include "xf86drm.h"
#include "dri2.h"
#ifdef GLX_DIRECT_RENDERING
#include <unistd.h>
-#include <X11/Xlibint.h>
-#include <X11/extensions/Xext.h>
-#include <X11/extensions/extutil.h>
+#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xdamage.h>
#include "glheader.h"
#include "glxclient.h"
+#include "glcontextmodes.h"
#include "xf86dri.h"
#include "sarea.h"
-#include <stdio.h>
#include <dlfcn.h>
#include <sys/types.h>
-#include <stdarg.h>
-#include "glcontextmodes.h"
#include <sys/mman.h>
#include "xf86drm.h"
+++ /dev/null
-/*
- * (C) Copyright IBM Corporation 2004
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file glx_texture_compression.c
- * Contains the routines required to implement GLX protocol for
- * ARB_texture_compression and related extensions.
- *
- * \sa http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_compression.txt
- *
- * \author Ian Romanick <idr@us.ibm.com>
- */
-
-#include "packrender.h"
-#include "packsingle.h"
-#include "indirect.h"
-
-#include <assert.h>
-
-
-void
-__indirect_glGetCompressedTexImageARB( GLenum target, GLint level,
- GLvoid * img )
-{
- __GLX_SINGLE_DECLARE_VARIABLES();
- xGLXGetTexImageReply reply;
- size_t image_bytes;
-
- __GLX_SINGLE_LOAD_VARIABLES();
- __GLX_SINGLE_BEGIN( X_GLsop_GetCompressedTexImage, 8 );
- __GLX_SINGLE_PUT_LONG( 0, target );
- __GLX_SINGLE_PUT_LONG( 4, level );
- __GLX_SINGLE_READ_XREPLY();
-
- image_bytes = reply.width;
- assert( image_bytes <= ((4 * reply.length) - 0) );
- assert( image_bytes >= ((4 * reply.length) - 3) );
-
- if ( image_bytes != 0 ) {
- _XRead( dpy, (char *) img, image_bytes );
- if ( image_bytes < (4 * reply.length) ) {
- _XEatData( dpy, (4 * reply.length) - image_bytes );
- }
- }
-
- __GLX_SINGLE_END();
-}
-
-
-/**
- * Internal function used for \c glCompressedTexImage1D and
- * \c glCompressedTexImage2D.
- */
-static void
-CompressedTexImage1D2D( GLenum target, GLint level,
- GLenum internal_format,
- GLsizei width, GLsizei height,
- GLint border, GLsizei image_size,
- const GLvoid *data, CARD32 rop )
-{
- __GLX_DECLARE_VARIABLES();
-
- __GLX_LOAD_VARIABLES();
- if ( gc->currentDpy == NULL ) {
- return;
- }
-
- if ( (target == GL_PROXY_TEXTURE_1D)
- || (target == GL_PROXY_TEXTURE_2D)
- || (target == GL_PROXY_TEXTURE_CUBE_MAP) ) {
- compsize = 0;
- }
- else {
- compsize = image_size;
- }
-
- cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE
- + compsize );
- if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
- __GLX_BEGIN_VARIABLE( rop, cmdlen );
- __GLX_PUT_LONG( 4, target );
- __GLX_PUT_LONG( 8, level );
- __GLX_PUT_LONG( 12, internal_format );
- __GLX_PUT_LONG( 16, width );
- __GLX_PUT_LONG( 20, height );
- __GLX_PUT_LONG( 24, border );
- __GLX_PUT_LONG( 28, image_size );
- if ( compsize != 0 ) {
- __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE,
- data, image_size );
- }
- __GLX_END( cmdlen );
- }
- else {
- assert( compsize != 0 );
-
- __GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
- __GLX_PUT_LONG( 8, target );
- __GLX_PUT_LONG( 12, level );
- __GLX_PUT_LONG( 16, internal_format );
- __GLX_PUT_LONG( 20, width );
- __GLX_PUT_LONG( 24, height );
- __GLX_PUT_LONG( 28, border );
- __GLX_PUT_LONG( 32, image_size );
- __glXSendLargeCommand( gc, gc->pc,
- __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE + 4,
- data, image_size );
- }
-}
-
-
-/**
- * Internal function used for \c glCompressedTexSubImage1D and
- * \c glCompressedTexSubImage2D.
- */
-static void
-CompressedTexSubImage1D2D( GLenum target, GLint level,
- GLsizei xoffset, GLsizei yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLsizei image_size,
- const GLvoid *data, CARD32 rop )
-{
- __GLX_DECLARE_VARIABLES();
-
- __GLX_LOAD_VARIABLES();
- if ( gc->currentDpy == NULL ) {
- return;
- }
-
- if ( target == GL_PROXY_TEXTURE_3D ) {
- compsize = 0;
- }
- else {
- compsize = image_size;
- }
-
- cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE
- + compsize );
- if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
- __GLX_BEGIN_VARIABLE( rop, cmdlen );
- __GLX_PUT_LONG( 4, target );
- __GLX_PUT_LONG( 8, level );
- __GLX_PUT_LONG( 12, xoffset );
- __GLX_PUT_LONG( 16, yoffset );
- __GLX_PUT_LONG( 20, width );
- __GLX_PUT_LONG( 24, height );
- __GLX_PUT_LONG( 28, format );
- __GLX_PUT_LONG( 32, image_size );
- if ( compsize != 0 ) {
- __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE,
- data, image_size );
- }
- __GLX_END( cmdlen );
- }
- else {
- assert( compsize != 0 );
-
- __GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
- __GLX_PUT_LONG( 8, target );
- __GLX_PUT_LONG( 12, level );
- __GLX_PUT_LONG( 16, xoffset );
- __GLX_PUT_LONG( 20, yoffset );
- __GLX_PUT_LONG( 24, width );
- __GLX_PUT_LONG( 28, height );
- __GLX_PUT_LONG( 32, format );
- __GLX_PUT_LONG( 36, image_size );
- __glXSendLargeCommand( gc, gc->pc,
- __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE + 4,
- data, image_size );
- }
-}
-
-
-void
-__indirect_glCompressedTexImage1DARB( GLenum target, GLint level,
- GLenum internal_format, GLsizei width,
- GLint border, GLsizei image_size,
- const GLvoid *data )
-{
- CompressedTexImage1D2D( target, level, internal_format, width, 0,
- border, image_size, data,
- X_GLrop_CompressedTexImage1D );
-}
-
-
-void
-__indirect_glCompressedTexImage2DARB( GLenum target, GLint level,
- GLenum internal_format,
- GLsizei width, GLsizei height,
- GLint border, GLsizei image_size,
- const GLvoid *data )
-{
- CompressedTexImage1D2D( target, level, internal_format, width, height,
- border, image_size, data,
- X_GLrop_CompressedTexImage2D );
-}
-
-
-void
-__indirect_glCompressedTexImage3DARB( GLenum target, GLint level,
- GLenum internal_format,
- GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLsizei image_size,
- const GLvoid *data )
-{
- __GLX_DECLARE_VARIABLES();
-
- __GLX_LOAD_VARIABLES();
- if ( gc->currentDpy == NULL ) {
- return;
- }
-
- cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE
- + image_size );
- if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
- __GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexImage3D, cmdlen );
- __GLX_PUT_LONG( 4, target );
- __GLX_PUT_LONG( 8, level );
- __GLX_PUT_LONG( 12, internal_format );
- __GLX_PUT_LONG( 16, width );
- __GLX_PUT_LONG( 20, height );
- __GLX_PUT_LONG( 24, depth );
- __GLX_PUT_LONG( 28, border );
- __GLX_PUT_LONG( 32, image_size );
- if ( image_size != 0 ) {
- __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE,
- data, image_size );
- }
- __GLX_END( cmdlen );
- }
- else {
- __GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexImage3D,
- cmdlen + 4 );
- __GLX_PUT_LONG( 8, target );
- __GLX_PUT_LONG( 12, level );
- __GLX_PUT_LONG( 16, internal_format );
- __GLX_PUT_LONG( 20, width );
- __GLX_PUT_LONG( 24, height );
- __GLX_PUT_LONG( 28, depth );
- __GLX_PUT_LONG( 32, border );
- __GLX_PUT_LONG( 36, image_size );
- __glXSendLargeCommand( gc, gc->pc,
- __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE + 4,
- data, image_size );
- }
-}
-
-
-void
-__indirect_glCompressedTexSubImage1DARB( GLenum target, GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLsizei image_size,
- const GLvoid *data )
-{
- CompressedTexSubImage1D2D( target, level, xoffset, 0, width, 0,
- format, image_size, data,
- X_GLrop_CompressedTexSubImage1D );
-}
-
-
-void
-__indirect_glCompressedTexSubImage2DARB( GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLsizei image_size,
- const GLvoid *data )
-{
- CompressedTexSubImage1D2D( target, level, xoffset, yoffset, width, height,
- format, image_size, data,
- X_GLrop_CompressedTexSubImage2D );
-}
-
-
-void
-__indirect_glCompressedTexSubImage3DARB( GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLsizei image_size,
- const GLvoid *data )
-{
- __GLX_DECLARE_VARIABLES();
-
- __GLX_LOAD_VARIABLES();
- if ( gc->currentDpy == NULL ) {
- return;
- }
-
- cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE
- + image_size );
- if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
- __GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexSubImage3D, cmdlen );
- __GLX_PUT_LONG( 4, target );
- __GLX_PUT_LONG( 8, level );
- __GLX_PUT_LONG( 12, xoffset );
- __GLX_PUT_LONG( 16, yoffset );
- __GLX_PUT_LONG( 20, zoffset );
- __GLX_PUT_LONG( 24, width );
- __GLX_PUT_LONG( 28, height );
- __GLX_PUT_LONG( 32, depth );
- __GLX_PUT_LONG( 36, format );
- __GLX_PUT_LONG( 40, image_size );
- if ( image_size != 0 ) {
- __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE,
- data, image_size );
- }
- __GLX_END( cmdlen );
- }
- else {
- __GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexSubImage3D,
- cmdlen + 4 );
- __GLX_PUT_LONG( 8, target );
- __GLX_PUT_LONG( 12, level );
- __GLX_PUT_LONG( 16, xoffset );
- __GLX_PUT_LONG( 20, yoffset );
- __GLX_PUT_LONG( 24, zoffset );
- __GLX_PUT_LONG( 28, width );
- __GLX_PUT_LONG( 32, height );
- __GLX_PUT_LONG( 36, depth );
- __GLX_PUT_LONG( 40, format );
- __GLX_PUT_LONG( 44, image_size );
- __glXSendLargeCommand( gc, gc->pc,
- __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE + 4,
- data, image_size );
- }
-}
extern const char *glXGetDriverConfig (const char *driverName);
-extern Bool __glXWindowExists(Display *dpy, GLXDrawable draw);
-
#endif
/************************************************************************/
};
-void __glXFreeContext(__GLXcontext*);
-
extern GLubyte *__glXFlushRenderBuffer(__GLXcontext*, GLubyte*);
extern void __glXSendLargeChunk(__GLXcontext *gc, GLint requestNumber,
#endif /* defined( USE_XTHREADS ) || defined( PTHREADS ) */
+extern void __glXSetCurrentContextNull(void);
+
+extern void __glXFreeContext(__GLXcontext*);
+
/*
** Global lock for all threads in this address space using the GLX
* Client-side GLX interface.
*/
-#include <inttypes.h>
#include "glxclient.h"
-#include <X11/extensions/extutil.h>
-#include <X11/extensions/Xext.h>
-#include <assert.h>
-#include <string.h>
#include "glapi.h"
-#ifdef GLX_DIRECT_RENDERING
-#include "indirect_init.h"
-#include <X11/extensions/xf86vmode.h>
-#include "xf86dri.h"
-#endif
#include "glxextensions.h"
#include "glcontextmodes.h"
#include "glheader.h"
+
+#ifdef GLX_DIRECT_RENDERING
#include <sys/time.h>
+#include <X11/extensions/xf86vmode.h>
+#include "xf86dri.h"
+#endif
static const char __glXGLXClientVendorName[] = "SGI";
static const char __glXGLXClientVersion[] = "1.4";
--- /dev/null
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+
+/**
+ * \file glxcurrent.c
+ * Client-side GLX interface for current context management.
+ */
+
+#include "glxclient.h"
+#include "glapi.h"
+#include "glheader.h"
+#include "indirect_init.h"
+
+#ifdef GLX_DIRECT_RENDERING
+#include "xf86dri.h"
+#endif
+
+/*
+** We setup some dummy structures here so that the API can be used
+** even if no context is current.
+*/
+
+static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
+
+/*
+** Dummy context used by small commands when there is no current context.
+** All the
+** gl and glx entry points are designed to operate as nop's when using
+** the dummy context structure.
+*/
+static __GLXcontext dummyContext = {
+ &dummyBuffer[0],
+ &dummyBuffer[0],
+ &dummyBuffer[0],
+ &dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
+ sizeof(dummyBuffer),
+};
+
+
+/*
+** All indirect rendering contexts will share the same indirect dispatch table.
+*/
+static __GLapi *IndirectAPI = NULL;
+
+
+/*
+ * Current context management and locking
+ */
+
+#if defined( USE_XTHREADS )
+
+/* thread safe */
+static GLboolean TSDinitialized = GL_FALSE;
+static xthread_key_t ContextTSD;
+
+_X_HIDDEN __GLXcontext *__glXGetCurrentContext(void)
+{
+ if (!TSDinitialized) {
+ xthread_key_create(&ContextTSD, NULL);
+ TSDinitialized = GL_TRUE;
+ return &dummyContext;
+ }
+ else {
+ void *p;
+ xthread_get_specific(ContextTSD, &p);
+ if (!p)
+ return &dummyContext;
+ else
+ return (__GLXcontext *) p;
+ }
+}
+
+_X_HIDDEN void __glXSetCurrentContext(__GLXcontext *c)
+{
+ if (!TSDinitialized) {
+ xthread_key_create(&ContextTSD, NULL);
+ TSDinitialized = GL_TRUE;
+ }
+ xthread_set_specific(ContextTSD, c);
+}
+
+
+/* Used by the __glXLock() and __glXUnlock() macros */
+_X_HIDDEN xmutex_rec __glXmutex;
+
+#elif defined( PTHREADS )
+
+_X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
+
+# if defined( GLX_USE_TLS )
+
+/**
+ * Per-thread GLX context pointer.
+ *
+ * \c __glXSetCurrentContext is written is such a way that this pointer can
+ * \b never be \c NULL. This is important! Because of this
+ * \c __glXGetCurrentContext can be implemented as trivial macro.
+ */
+__thread void * __glX_tls_Context __attribute__((tls_model("initial-exec")))
+ = &dummyContext;
+
+_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
+{
+ __glX_tls_Context = (c != NULL) ? c : &dummyContext;
+}
+
+# else
+
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+/**
+ * Per-thread data key.
+ *
+ * Once \c init_thread_data has been called, the per-thread data key will
+ * take a value of \c NULL. As each new thread is created the default
+ * value, in that thread, will be \c NULL.
+ */
+static pthread_key_t ContextTSD;
+
+/**
+ * Initialize the per-thread data key.
+ *
+ * This function is called \b exactly once per-process (not per-thread!) to
+ * initialize the per-thread data key. This is ideally done using the
+ * \c pthread_once mechanism.
+ */
+static void init_thread_data( void )
+{
+ if ( pthread_key_create( & ContextTSD, NULL ) != 0 ) {
+ perror( "pthread_key_create" );
+ exit( -1 );
+ }
+}
+
+_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
+{
+ pthread_once( & once_control, init_thread_data );
+ pthread_setspecific( ContextTSD, c );
+}
+
+_X_HIDDEN __GLXcontext * __glXGetCurrentContext( void )
+{
+ void * v;
+
+ pthread_once( & once_control, init_thread_data );
+
+ v = pthread_getspecific( ContextTSD );
+ return (v == NULL) ? & dummyContext : (__GLXcontext *) v;
+}
+
+# endif /* defined( GLX_USE_TLS ) */
+
+#elif defined( THREADS )
+
+#error Unknown threading method specified.
+
+#else
+
+/* not thread safe */
+_X_HIDDEN __GLXcontext *__glXcurrentContext = &dummyContext;
+
+#endif
+
+
+_X_HIDDEN void __glXSetCurrentContextNull(void)
+{
+ __glXSetCurrentContext(&dummyContext);
+#ifdef GLX_DIRECT_RENDERING
+ _glapi_set_dispatch(NULL); /* no-op functions */
+#endif
+}
+
+
+/************************************************************************/
+
+PUBLIC GLXContext glXGetCurrentContext(void)
+{
+ GLXContext cx = __glXGetCurrentContext();
+
+ if (cx == &dummyContext) {
+ return NULL;
+ } else {
+ return cx;
+ }
+}
+
+PUBLIC GLXDrawable glXGetCurrentDrawable(void)
+{
+ GLXContext gc = __glXGetCurrentContext();
+ return gc->currentDrawable;
+}
+
+
+/************************************************************************/
+
+/**
+ * Sends a GLX protocol message to the specified display to make the context
+ * and the drawables current.
+ *
+ * \param dpy Display to send the message to.
+ * \param opcode Major opcode value for the display.
+ * \param gc_id Context tag for the context to be made current.
+ * \param draw Drawable ID for the "draw" drawable.
+ * \param read Drawable ID for the "read" drawable.
+ * \param reply Space to store the X-server's reply.
+ *
+ * \warning
+ * This function assumes that \c dpy is locked with \c LockDisplay on entry.
+ */
+static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode,
+ GLXContextID gc_id, GLXContextTag gc_tag,
+ GLXDrawable draw, GLXDrawable read,
+ xGLXMakeCurrentReply *reply)
+{
+ Bool ret;
+
+
+ LockDisplay(dpy);
+
+ if (draw == read) {
+ xGLXMakeCurrentReq *req;
+
+ GetReq(GLXMakeCurrent,req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXMakeCurrent;
+ req->drawable = draw;
+ req->context = gc_id;
+ req->oldContextTag = gc_tag;
+ }
+ else {
+ __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+
+ /* If the server can support the GLX 1.3 version, we should
+ * perfer that. Not only that, some servers support GLX 1.3 but
+ * not the SGI extension.
+ */
+
+ if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+ xGLXMakeContextCurrentReq *req;
+
+ GetReq(GLXMakeContextCurrent,req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXMakeContextCurrent;
+ req->drawable = draw;
+ req->readdrawable = read;
+ req->context = gc_id;
+ req->oldContextTag = gc_tag;
+ }
+ else {
+ xGLXVendorPrivateWithReplyReq *vpreq;
+ xGLXMakeCurrentReadSGIReq *req;
+
+ GetReqExtra(GLXVendorPrivateWithReply,
+ sz_xGLXMakeCurrentReadSGIReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
+ req = (xGLXMakeCurrentReadSGIReq *)vpreq;
+ req->reqType = opcode;
+ req->glxCode = X_GLXVendorPrivateWithReply;
+ req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
+ req->drawable = draw;
+ req->readable = read;
+ req->context = gc_id;
+ req->oldContextTag = gc_tag;
+ }
+ }
+
+ ret = _XReply(dpy, (xReply*) reply, 0, False);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return ret;
+}
+
+
+#ifdef GLX_DIRECT_RENDERING
+static __GLXDRIdrawable *
+FetchDRIDrawable(Display *dpy,
+ GLXDrawable glxDrawable, GLXContext gc, Bool pre13)
+{
+ __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
+ __GLXDRIdrawable *pdraw;
+ __GLXscreenConfigs *psc;
+ XID drawable;
+
+ if (priv == NULL)
+ return NULL;
+
+ psc = &priv->screenConfigs[gc->screen];
+ if (psc->drawHash == NULL)
+ return NULL;
+
+ if (__glxHashLookup(psc->drawHash, glxDrawable, (void *) &pdraw) == 0)
+ return pdraw;
+
+ /* If this is glXMakeCurrent (pre GLX 1.3) we allow creating the
+ * GLX drawable on the fly. Otherwise we pass None as the X
+ * drawable */
+ if (pre13)
+ drawable = glxDrawable;
+ else
+ drawable = None;
+
+ pdraw = psc->driScreen->createDrawable(psc, drawable,
+ glxDrawable, gc->mode);
+ if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) {
+ (*pdraw->destroyDrawable)(pdraw);
+ return NULL;
+ }
+
+ return pdraw;
+}
+#endif /* GLX_DIRECT_RENDERING */
+
+
+/**
+ * Make a particular context current.
+ *
+ * \note This is in this file so that it can access dummyContext.
+ */
+static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
+ GLXDrawable read, GLXContext gc,
+ Bool pre13)
+{
+ xGLXMakeCurrentReply reply;
+ const GLXContext oldGC = __glXGetCurrentContext();
+ const CARD8 opcode = __glXSetupForCommand(dpy);
+ const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext))
+ ? opcode : __glXSetupForCommand(oldGC->currentDpy);
+ Bool bindReturnValue;
+
+
+ if (!opcode || !oldOpcode) {
+ return GL_FALSE;
+ }
+
+ /* Make sure that the new context has a nonzero ID. In the request,
+ * a zero context ID is used only to mean that we bind to no current
+ * context.
+ */
+ if ((gc != NULL) && (gc->xid == None)) {
+ return GL_FALSE;
+ }
+
+ _glapi_check_multithread();
+
+#ifdef GLX_DIRECT_RENDERING
+ /* Bind the direct rendering context to the drawable */
+ if (gc && gc->driContext) {
+ __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc, pre13);
+ __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc, pre13);
+
+ bindReturnValue =
+ (gc->driContext->bindContext) (gc->driContext, pdraw, pread);
+ } else
+#endif
+ {
+ /* Send a glXMakeCurrent request to bind the new context. */
+ bindReturnValue =
+ SendMakeCurrentRequest(dpy, opcode, gc ? gc->xid : None,
+ ((dpy != oldGC->currentDpy) || oldGC->isDirect)
+ ? None : oldGC->currentContextTag,
+ draw, read, &reply);
+ }
+
+
+ if (!bindReturnValue) {
+ return False;
+ }
+
+ if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) &&
+ !oldGC->isDirect && oldGC != &dummyContext) {
+ xGLXMakeCurrentReply dummy_reply;
+
+ /* We are either switching from one dpy to another and have to
+ * send a request to the previous dpy to unbind the previous
+ * context, or we are switching away from a indirect context to
+ * a direct context and have to send a request to the dpy to
+ * unbind the previous context.
+ */
+ (void) SendMakeCurrentRequest(oldGC->currentDpy, oldOpcode, None,
+ oldGC->currentContextTag, None, None,
+ & dummy_reply);
+ }
+#ifdef GLX_DIRECT_RENDERING
+ else if (oldGC->driContext) {
+ oldGC->driContext->unbindContext(oldGC->driContext);
+ }
+#endif
+
+
+ /* Update our notion of what is current */
+ __glXLock();
+ if (gc == oldGC) {
+ /* Even though the contexts are the same the drawable might have
+ * changed. Note that gc cannot be the dummy, and that oldGC
+ * cannot be NULL, therefore if they are the same, gc is not
+ * NULL and not the dummy.
+ */
+ gc->currentDrawable = draw;
+ gc->currentReadable = read;
+ } else {
+ if (oldGC != &dummyContext) {
+ /* Old current context is no longer current to anybody */
+ oldGC->currentDpy = 0;
+ oldGC->currentDrawable = None;
+ oldGC->currentReadable = None;
+ oldGC->currentContextTag = 0;
+
+ if (oldGC->xid == None) {
+ /* We are switching away from a context that was
+ * previously destroyed, so we need to free the memory
+ * for the old handle.
+ */
+#ifdef GLX_DIRECT_RENDERING
+ /* Destroy the old direct rendering context */
+ if (oldGC->driContext) {
+ oldGC->driContext->destroyContext(oldGC->driContext,
+ oldGC->psc,
+ oldGC->createDpy);
+ oldGC->driContext = NULL;
+ }
+#endif
+ __glXFreeContext(oldGC);
+ }
+ }
+ if (gc) {
+ __glXSetCurrentContext(gc);
+
+ gc->currentDpy = dpy;
+ gc->currentDrawable = draw;
+ gc->currentReadable = read;
+
+ if (!gc->driContext) {
+ if (!IndirectAPI)
+ IndirectAPI = __glXNewIndirectAPI();
+ _glapi_set_dispatch(IndirectAPI);
+
+#ifdef GLX_USE_APPLEGL
+ do {
+ extern void XAppleDRIUseIndirectDispatch(void);
+ XAppleDRIUseIndirectDispatch();
+ } while (0);
+#endif
+
+ __GLXattribute *state =
+ (__GLXattribute *)(gc->client_state_private);
+
+ gc->currentContextTag = reply.contextTag;
+ if (state->array_state == NULL) {
+ (void) glGetString(GL_EXTENSIONS);
+ (void) glGetString(GL_VERSION);
+ __glXInitVertexArrayState(gc);
+ }
+ }
+ else {
+ gc->currentContextTag = -1;
+ }
+ } else {
+ __glXSetCurrentContextNull();
+ }
+ }
+ __glXUnlock();
+ return GL_TRUE;
+}
+
+
+PUBLIC Bool glXMakeCurrent(Display *dpy, GLXDrawable draw, GLXContext gc)
+{
+ return MakeContextCurrent(dpy, draw, draw, gc, True);
+}
+
+PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
+ (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
+ (dpy, d, r, ctx, False), MakeContextCurrent)
+
+PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent,
+ (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
+ (dpy, d, r, ctx, False), MakeContextCurrent)
*/
#include "glxclient.h"
-#include <stdio.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
-#include <X11/extensions/Xfixes.h>
-#include <X11/extensions/Xdamage.h>
-#include <assert.h>
-#include "indirect_init.h"
#include "glapi.h"
#include "glxextensions.h"
#include "glcontextmodes.h"
#include "glheader.h"
-#ifdef GLX_DIRECT_RENDERING
-#include <inttypes.h>
-#include <sys/mman.h>
-#include "xf86dri.h"
-#include "xf86drm.h"
-#include "sarea.h"
-#endif
-
#ifdef USE_XCB
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
#endif
#ifdef USE_SPARC_ASM
-/*
- * This is where our dispatch table's bounds are.
- * And the static mesa_init is taken directly from
- * Mesa's 'sparc.c' initializer.
- *
- * We need something like this here, because this version
- * of openGL/glx never initializes a Mesa context, and so
- * the address of the dispatch table pointer never gets stuffed
- * into the dispatch jump table otherwise.
- *
- * It matters only on SPARC, and only if you are using assembler
- * code instead of C-code indirect dispatch.
- *
- * -- FEM, 04.xii.03
- */
-extern unsigned int _mesa_sparc_glapi_begin;
-extern unsigned int _mesa_sparc_glapi_end;
-extern void __glapi_sparc_icache_flush(unsigned int *);
static void _glx_mesa_init_sparc_glapi_relocs(void);
static int _mesa_sparc_needs_init = 1;
#define INIT_MESA_SPARC { \
#define INIT_MESA_SPARC
#endif
-/*
-** We setup some dummy structures here so that the API can be used
-** even if no context is current.
-*/
-
-static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
-
-/*
-** Dummy context used by small commands when there is no current context.
-** All the
-** gl and glx entry points are designed to operate as nop's when using
-** the dummy context structure.
-*/
-static __GLXcontext dummyContext = {
- &dummyBuffer[0],
- &dummyBuffer[0],
- &dummyBuffer[0],
- &dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
- sizeof(dummyBuffer),
-};
-
-
-/*
-** All indirect rendering contexts will share the same indirect dispatch table.
-*/
-static __GLapi *IndirectAPI = NULL;
-
-
-/*
- * Current context management and locking
- */
-
-#if defined( USE_XTHREADS )
-
-/* thread safe */
-static GLboolean TSDinitialized = GL_FALSE;
-static xthread_key_t ContextTSD;
-
-_X_HIDDEN __GLXcontext *__glXGetCurrentContext(void)
-{
- if (!TSDinitialized) {
- xthread_key_create(&ContextTSD, NULL);
- TSDinitialized = GL_TRUE;
- return &dummyContext;
- }
- else {
- void *p;
- xthread_get_specific(ContextTSD, &p);
- if (!p)
- return &dummyContext;
- else
- return (__GLXcontext *) p;
- }
-}
-
-_X_HIDDEN void __glXSetCurrentContext(__GLXcontext *c)
-{
- if (!TSDinitialized) {
- xthread_key_create(&ContextTSD, NULL);
- TSDinitialized = GL_TRUE;
- }
- xthread_set_specific(ContextTSD, c);
-}
-
-
-/* Used by the __glXLock() and __glXUnlock() macros */
-_X_HIDDEN xmutex_rec __glXmutex;
-
-#elif defined( PTHREADS )
-
-_X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
-
-# if defined( GLX_USE_TLS )
-
-/**
- * Per-thread GLX context pointer.
- *
- * \c __glXSetCurrentContext is written is such a way that this pointer can
- * \b never be \c NULL. This is important! Because of this
- * \c __glXGetCurrentContext can be implemented as trivial macro.
- */
-__thread void * __glX_tls_Context __attribute__((tls_model("initial-exec")))
- = &dummyContext;
-
-_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
-{
- __glX_tls_Context = (c != NULL) ? c : &dummyContext;
-}
-
-# else
-
-static pthread_once_t once_control = PTHREAD_ONCE_INIT;
-
-/**
- * Per-thread data key.
- *
- * Once \c init_thread_data has been called, the per-thread data key will
- * take a value of \c NULL. As each new thread is created the default
- * value, in that thread, will be \c NULL.
- */
-static pthread_key_t ContextTSD;
-
-/**
- * Initialize the per-thread data key.
- *
- * This function is called \b exactly once per-process (not per-thread!) to
- * initialize the per-thread data key. This is ideally done using the
- * \c pthread_once mechanism.
- */
-static void init_thread_data( void )
-{
- if ( pthread_key_create( & ContextTSD, NULL ) != 0 ) {
- perror( "pthread_key_create" );
- exit( -1 );
- }
-}
-
-_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
-{
- pthread_once( & once_control, init_thread_data );
- pthread_setspecific( ContextTSD, c );
-}
-
-_X_HIDDEN __GLXcontext * __glXGetCurrentContext( void )
-{
- void * v;
-
- pthread_once( & once_control, init_thread_data );
-
- v = pthread_getspecific( ContextTSD );
- return (v == NULL) ? & dummyContext : (__GLXcontext *) v;
-}
-
-# endif /* defined( GLX_USE_TLS ) */
-
-#elif defined( THREADS )
-
-#error Unknown threading method specified.
-
-#else
-
-/* not thread safe */
-_X_HIDDEN __GLXcontext *__glXcurrentContext = &dummyContext;
-
-#endif
-
-
/*
** You can set this cell to 1 to force the gl drawing stuff to be
** one command per packet
gc = __glXGetCurrentContext();
if (dpy == gc->currentDpy) {
- __glXSetCurrentContext(&dummyContext);
-#ifdef GLX_DIRECT_RENDERING
- _glapi_set_dispatch(NULL); /* no-op functions */
-#endif
+ __glXSetCurrentContextNull();
__glXFreeContext(gc);
}
/************************************************************************/
-PUBLIC GLXContext glXGetCurrentContext(void)
-{
- GLXContext cx = __glXGetCurrentContext();
-
- if (cx == &dummyContext) {
- return NULL;
- } else {
- return cx;
- }
-}
-
-PUBLIC GLXDrawable glXGetCurrentDrawable(void)
-{
- GLXContext gc = __glXGetCurrentContext();
- return gc->currentDrawable;
-}
-
-
-/************************************************************************/
-
-static Bool SendMakeCurrentRequest( Display *dpy, CARD8 opcode,
- GLXContextID gc, GLXContextTag old_gc, GLXDrawable draw, GLXDrawable read,
- xGLXMakeCurrentReply * reply );
-
-/**
- * Sends a GLX protocol message to the specified display to make the context
- * and the drawables current.
- *
- * \param dpy Display to send the message to.
- * \param opcode Major opcode value for the display.
- * \param gc_id Context tag for the context to be made current.
- * \param draw Drawable ID for the "draw" drawable.
- * \param read Drawable ID for the "read" drawable.
- * \param reply Space to store the X-server's reply.
- *
- * \warning
- * This function assumes that \c dpy is locked with \c LockDisplay on entry.
- */
-static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode,
- GLXContextID gc_id, GLXContextTag gc_tag,
- GLXDrawable draw, GLXDrawable read,
- xGLXMakeCurrentReply *reply)
-{
- Bool ret;
-
-
- LockDisplay(dpy);
-
- if (draw == read) {
- xGLXMakeCurrentReq *req;
-
- GetReq(GLXMakeCurrent,req);
- req->reqType = opcode;
- req->glxCode = X_GLXMakeCurrent;
- req->drawable = draw;
- req->context = gc_id;
- req->oldContextTag = gc_tag;
- }
- else {
- __GLXdisplayPrivate *priv = __glXInitialize(dpy);
-
- /* If the server can support the GLX 1.3 version, we should
- * perfer that. Not only that, some servers support GLX 1.3 but
- * not the SGI extension.
- */
-
- if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
- xGLXMakeContextCurrentReq *req;
-
- GetReq(GLXMakeContextCurrent,req);
- req->reqType = opcode;
- req->glxCode = X_GLXMakeContextCurrent;
- req->drawable = draw;
- req->readdrawable = read;
- req->context = gc_id;
- req->oldContextTag = gc_tag;
- }
- else {
- xGLXVendorPrivateWithReplyReq *vpreq;
- xGLXMakeCurrentReadSGIReq *req;
-
- GetReqExtra(GLXVendorPrivateWithReply,
- sz_xGLXMakeCurrentReadSGIReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
- req = (xGLXMakeCurrentReadSGIReq *)vpreq;
- req->reqType = opcode;
- req->glxCode = X_GLXVendorPrivateWithReply;
- req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
- req->drawable = draw;
- req->readable = read;
- req->context = gc_id;
- req->oldContextTag = gc_tag;
- }
- }
-
- ret = _XReply(dpy, (xReply*) reply, 0, False);
-
- UnlockDisplay(dpy);
- SyncHandle();
-
- return ret;
-}
-
-
-#ifdef GLX_DIRECT_RENDERING
-static __GLXDRIdrawable *
-FetchDRIDrawable(Display *dpy,
- GLXDrawable glxDrawable, GLXContext gc, Bool pre13)
-{
- __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
- __GLXDRIdrawable *pdraw;
- __GLXscreenConfigs *psc;
- XID drawable;
-
- if (priv == NULL)
- return NULL;
-
- psc = &priv->screenConfigs[gc->screen];
- if (psc->drawHash == NULL)
- return NULL;
-
- if (__glxHashLookup(psc->drawHash, glxDrawable, (void *) &pdraw) == 0)
- return pdraw;
-
- /* If this is glXMakeCurrent (pre GLX 1.3) we allow creating the
- * GLX drawable on the fly. Otherwise we pass None as the X
- * drawable */
- if (pre13)
- drawable = glxDrawable;
- else
- drawable = None;
-
- pdraw = psc->driScreen->createDrawable(psc, drawable,
- glxDrawable, gc->mode);
- if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) {
- (*pdraw->destroyDrawable)(pdraw);
- return NULL;
- }
-
- return pdraw;
-}
-#endif /* GLX_DIRECT_RENDERING */
-
-
-/**
- * Make a particular context current.
- *
- * \note This is in this file so that it can access dummyContext.
- */
-static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
- GLXDrawable read, GLXContext gc,
- Bool pre13)
-{
- xGLXMakeCurrentReply reply;
- const GLXContext oldGC = __glXGetCurrentContext();
- const CARD8 opcode = __glXSetupForCommand(dpy);
- const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext))
- ? opcode : __glXSetupForCommand(oldGC->currentDpy);
- Bool bindReturnValue;
-
-
- if (!opcode || !oldOpcode) {
- return GL_FALSE;
- }
-
- /* Make sure that the new context has a nonzero ID. In the request,
- * a zero context ID is used only to mean that we bind to no current
- * context.
- */
- if ((gc != NULL) && (gc->xid == None)) {
- return GL_FALSE;
- }
-
- _glapi_check_multithread();
-
-#ifdef GLX_DIRECT_RENDERING
- /* Bind the direct rendering context to the drawable */
- if (gc && gc->driContext) {
- __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc, pre13);
- __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc, pre13);
-
- bindReturnValue =
- (gc->driContext->bindContext) (gc->driContext, pdraw, pread);
- } else
-#endif
- {
- /* Send a glXMakeCurrent request to bind the new context. */
- bindReturnValue =
- SendMakeCurrentRequest(dpy, opcode, gc ? gc->xid : None,
- ((dpy != oldGC->currentDpy) || oldGC->isDirect)
- ? None : oldGC->currentContextTag,
- draw, read, &reply);
- }
-
-
- if (!bindReturnValue) {
- return False;
- }
-
- if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) &&
- !oldGC->isDirect && oldGC != &dummyContext) {
- xGLXMakeCurrentReply dummy_reply;
-
- /* We are either switching from one dpy to another and have to
- * send a request to the previous dpy to unbind the previous
- * context, or we are switching away from a indirect context to
- * a direct context and have to send a request to the dpy to
- * unbind the previous context.
- */
- (void) SendMakeCurrentRequest(oldGC->currentDpy, oldOpcode, None,
- oldGC->currentContextTag, None, None,
- & dummy_reply);
- }
-#ifdef GLX_DIRECT_RENDERING
- else if (oldGC->driContext) {
- oldGC->driContext->unbindContext(oldGC->driContext);
- }
-#endif
-
-
- /* Update our notion of what is current */
- __glXLock();
- if (gc == oldGC) {
- /* Even though the contexts are the same the drawable might have
- * changed. Note that gc cannot be the dummy, and that oldGC
- * cannot be NULL, therefore if they are the same, gc is not
- * NULL and not the dummy.
- */
- gc->currentDrawable = draw;
- gc->currentReadable = read;
- } else {
- if (oldGC != &dummyContext) {
- /* Old current context is no longer current to anybody */
- oldGC->currentDpy = 0;
- oldGC->currentDrawable = None;
- oldGC->currentReadable = None;
- oldGC->currentContextTag = 0;
-
- if (oldGC->xid == None) {
- /* We are switching away from a context that was
- * previously destroyed, so we need to free the memory
- * for the old handle.
- */
-#ifdef GLX_DIRECT_RENDERING
- /* Destroy the old direct rendering context */
- if (oldGC->driContext) {
- oldGC->driContext->destroyContext(oldGC->driContext,
- oldGC->psc,
- oldGC->createDpy);
- oldGC->driContext = NULL;
- }
-#endif
- __glXFreeContext(oldGC);
- }
- }
- if (gc) {
- __glXSetCurrentContext(gc);
-
- gc->currentDpy = dpy;
- gc->currentDrawable = draw;
- gc->currentReadable = read;
-
- if (!gc->driContext) {
- if (!IndirectAPI)
- IndirectAPI = __glXNewIndirectAPI();
- _glapi_set_dispatch(IndirectAPI);
-
-#ifdef GLX_USE_APPLEGL
- do {
- extern void XAppleDRIUseIndirectDispatch(void);
- XAppleDRIUseIndirectDispatch();
- } while (0);
-#endif
-
- __GLXattribute *state =
- (__GLXattribute *)(gc->client_state_private);
-
- gc->currentContextTag = reply.contextTag;
- if (state->array_state == NULL) {
- (void) glGetString(GL_EXTENSIONS);
- (void) glGetString(GL_VERSION);
- __glXInitVertexArrayState(gc);
- }
- }
- else {
- gc->currentContextTag = -1;
- }
- } else {
- __glXSetCurrentContext(&dummyContext);
-#ifdef GLX_DIRECT_RENDERING
- _glapi_set_dispatch(NULL); /* no-op functions */
-#endif
- }
- }
- __glXUnlock();
- return GL_TRUE;
-}
-
-
-PUBLIC Bool glXMakeCurrent(Display *dpy, GLXDrawable draw, GLXContext gc)
-{
- return MakeContextCurrent(dpy, draw, draw, gc, True);
-}
-
-PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
- (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
- (dpy, d, r, ctx, False), MakeContextCurrent)
-
-PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent,
- (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
- (dpy, d, r, ctx, False), MakeContextCurrent)
-
-
#ifdef DEBUG
_X_HIDDEN void __glXDumpDrawBuffer(__GLXcontext *ctx)
{
#ifdef USE_SPARC_ASM
/*
- * Used only when we are sparc, using sparc assembler.
+ * This is where our dispatch table's bounds are.
+ * And the static mesa_init is taken directly from
+ * Mesa's 'sparc.c' initializer.
*
+ * We need something like this here, because this version
+ * of openGL/glx never initializes a Mesa context, and so
+ * the address of the dispatch table pointer never gets stuffed
+ * into the dispatch jump table otherwise.
+ *
+ * It matters only on SPARC, and only if you are using assembler
+ * code instead of C-code indirect dispatch.
+ *
+ * -- FEM, 04.xii.03
*/
+extern unsigned int _mesa_sparc_glapi_begin;
+extern unsigned int _mesa_sparc_glapi_end;
+extern void __glapi_sparc_icache_flush(unsigned int *);
static void
_glx_mesa_init_sparc_glapi_relocs(void)
--- /dev/null
+/*
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file glx_texture_compression.c
+ * Contains the routines required to implement GLX protocol for
+ * ARB_texture_compression and related extensions.
+ *
+ * \sa http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_compression.txt
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "packrender.h"
+#include "packsingle.h"
+#include "indirect.h"
+
+#include <assert.h>
+
+
+void
+__indirect_glGetCompressedTexImageARB( GLenum target, GLint level,
+ GLvoid * img )
+{
+ __GLX_SINGLE_DECLARE_VARIABLES();
+ xGLXGetTexImageReply reply;
+ size_t image_bytes;
+
+ __GLX_SINGLE_LOAD_VARIABLES();
+ __GLX_SINGLE_BEGIN( X_GLsop_GetCompressedTexImage, 8 );
+ __GLX_SINGLE_PUT_LONG( 0, target );
+ __GLX_SINGLE_PUT_LONG( 4, level );
+ __GLX_SINGLE_READ_XREPLY();
+
+ image_bytes = reply.width;
+ assert( image_bytes <= ((4 * reply.length) - 0) );
+ assert( image_bytes >= ((4 * reply.length) - 3) );
+
+ if ( image_bytes != 0 ) {
+ _XRead( dpy, (char *) img, image_bytes );
+ if ( image_bytes < (4 * reply.length) ) {
+ _XEatData( dpy, (4 * reply.length) - image_bytes );
+ }
+ }
+
+ __GLX_SINGLE_END();
+}
+
+
+/**
+ * Internal function used for \c glCompressedTexImage1D and
+ * \c glCompressedTexImage2D.
+ */
+static void
+CompressedTexImage1D2D( GLenum target, GLint level,
+ GLenum internal_format,
+ GLsizei width, GLsizei height,
+ GLint border, GLsizei image_size,
+ const GLvoid *data, CARD32 rop )
+{
+ __GLX_DECLARE_VARIABLES();
+
+ __GLX_LOAD_VARIABLES();
+ if ( gc->currentDpy == NULL ) {
+ return;
+ }
+
+ if ( (target == GL_PROXY_TEXTURE_1D)
+ || (target == GL_PROXY_TEXTURE_2D)
+ || (target == GL_PROXY_TEXTURE_CUBE_MAP) ) {
+ compsize = 0;
+ }
+ else {
+ compsize = image_size;
+ }
+
+ cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE
+ + compsize );
+ if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+ __GLX_BEGIN_VARIABLE( rop, cmdlen );
+ __GLX_PUT_LONG( 4, target );
+ __GLX_PUT_LONG( 8, level );
+ __GLX_PUT_LONG( 12, internal_format );
+ __GLX_PUT_LONG( 16, width );
+ __GLX_PUT_LONG( 20, height );
+ __GLX_PUT_LONG( 24, border );
+ __GLX_PUT_LONG( 28, image_size );
+ if ( compsize != 0 ) {
+ __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE,
+ data, image_size );
+ }
+ __GLX_END( cmdlen );
+ }
+ else {
+ assert( compsize != 0 );
+
+ __GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
+ __GLX_PUT_LONG( 8, target );
+ __GLX_PUT_LONG( 12, level );
+ __GLX_PUT_LONG( 16, internal_format );
+ __GLX_PUT_LONG( 20, width );
+ __GLX_PUT_LONG( 24, height );
+ __GLX_PUT_LONG( 28, border );
+ __GLX_PUT_LONG( 32, image_size );
+ __glXSendLargeCommand( gc, gc->pc,
+ __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE + 4,
+ data, image_size );
+ }
+}
+
+
+/**
+ * Internal function used for \c glCompressedTexSubImage1D and
+ * \c glCompressedTexSubImage2D.
+ */
+static void
+CompressedTexSubImage1D2D( GLenum target, GLint level,
+ GLsizei xoffset, GLsizei yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLsizei image_size,
+ const GLvoid *data, CARD32 rop )
+{
+ __GLX_DECLARE_VARIABLES();
+
+ __GLX_LOAD_VARIABLES();
+ if ( gc->currentDpy == NULL ) {
+ return;
+ }
+
+ if ( target == GL_PROXY_TEXTURE_3D ) {
+ compsize = 0;
+ }
+ else {
+ compsize = image_size;
+ }
+
+ cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE
+ + compsize );
+ if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+ __GLX_BEGIN_VARIABLE( rop, cmdlen );
+ __GLX_PUT_LONG( 4, target );
+ __GLX_PUT_LONG( 8, level );
+ __GLX_PUT_LONG( 12, xoffset );
+ __GLX_PUT_LONG( 16, yoffset );
+ __GLX_PUT_LONG( 20, width );
+ __GLX_PUT_LONG( 24, height );
+ __GLX_PUT_LONG( 28, format );
+ __GLX_PUT_LONG( 32, image_size );
+ if ( compsize != 0 ) {
+ __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE,
+ data, image_size );
+ }
+ __GLX_END( cmdlen );
+ }
+ else {
+ assert( compsize != 0 );
+
+ __GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
+ __GLX_PUT_LONG( 8, target );
+ __GLX_PUT_LONG( 12, level );
+ __GLX_PUT_LONG( 16, xoffset );
+ __GLX_PUT_LONG( 20, yoffset );
+ __GLX_PUT_LONG( 24, width );
+ __GLX_PUT_LONG( 28, height );
+ __GLX_PUT_LONG( 32, format );
+ __GLX_PUT_LONG( 36, image_size );
+ __glXSendLargeCommand( gc, gc->pc,
+ __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE + 4,
+ data, image_size );
+ }
+}
+
+
+void
+__indirect_glCompressedTexImage1DARB( GLenum target, GLint level,
+ GLenum internal_format, GLsizei width,
+ GLint border, GLsizei image_size,
+ const GLvoid *data )
+{
+ CompressedTexImage1D2D( target, level, internal_format, width, 0,
+ border, image_size, data,
+ X_GLrop_CompressedTexImage1D );
+}
+
+
+void
+__indirect_glCompressedTexImage2DARB( GLenum target, GLint level,
+ GLenum internal_format,
+ GLsizei width, GLsizei height,
+ GLint border, GLsizei image_size,
+ const GLvoid *data )
+{
+ CompressedTexImage1D2D( target, level, internal_format, width, height,
+ border, image_size, data,
+ X_GLrop_CompressedTexImage2D );
+}
+
+
+void
+__indirect_glCompressedTexImage3DARB( GLenum target, GLint level,
+ GLenum internal_format,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLsizei image_size,
+ const GLvoid *data )
+{
+ __GLX_DECLARE_VARIABLES();
+
+ __GLX_LOAD_VARIABLES();
+ if ( gc->currentDpy == NULL ) {
+ return;
+ }
+
+ cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE
+ + image_size );
+ if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+ __GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexImage3D, cmdlen );
+ __GLX_PUT_LONG( 4, target );
+ __GLX_PUT_LONG( 8, level );
+ __GLX_PUT_LONG( 12, internal_format );
+ __GLX_PUT_LONG( 16, width );
+ __GLX_PUT_LONG( 20, height );
+ __GLX_PUT_LONG( 24, depth );
+ __GLX_PUT_LONG( 28, border );
+ __GLX_PUT_LONG( 32, image_size );
+ if ( image_size != 0 ) {
+ __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE,
+ data, image_size );
+ }
+ __GLX_END( cmdlen );
+ }
+ else {
+ __GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexImage3D,
+ cmdlen + 4 );
+ __GLX_PUT_LONG( 8, target );
+ __GLX_PUT_LONG( 12, level );
+ __GLX_PUT_LONG( 16, internal_format );
+ __GLX_PUT_LONG( 20, width );
+ __GLX_PUT_LONG( 24, height );
+ __GLX_PUT_LONG( 28, depth );
+ __GLX_PUT_LONG( 32, border );
+ __GLX_PUT_LONG( 36, image_size );
+ __glXSendLargeCommand( gc, gc->pc,
+ __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE + 4,
+ data, image_size );
+ }
+}
+
+
+void
+__indirect_glCompressedTexSubImage1DARB( GLenum target, GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLsizei image_size,
+ const GLvoid *data )
+{
+ CompressedTexSubImage1D2D( target, level, xoffset, 0, width, 0,
+ format, image_size, data,
+ X_GLrop_CompressedTexSubImage1D );
+}
+
+
+void
+__indirect_glCompressedTexSubImage2DARB( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLsizei image_size,
+ const GLvoid *data )
+{
+ CompressedTexSubImage1D2D( target, level, xoffset, yoffset, width, height,
+ format, image_size, data,
+ X_GLrop_CompressedTexSubImage2D );
+}
+
+
+void
+__indirect_glCompressedTexSubImage3DARB( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei image_size,
+ const GLvoid *data )
+{
+ __GLX_DECLARE_VARIABLES();
+
+ __GLX_LOAD_VARIABLES();
+ if ( gc->currentDpy == NULL ) {
+ return;
+ }
+
+ cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE
+ + image_size );
+ if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+ __GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexSubImage3D, cmdlen );
+ __GLX_PUT_LONG( 4, target );
+ __GLX_PUT_LONG( 8, level );
+ __GLX_PUT_LONG( 12, xoffset );
+ __GLX_PUT_LONG( 16, yoffset );
+ __GLX_PUT_LONG( 20, zoffset );
+ __GLX_PUT_LONG( 24, width );
+ __GLX_PUT_LONG( 28, height );
+ __GLX_PUT_LONG( 32, depth );
+ __GLX_PUT_LONG( 36, format );
+ __GLX_PUT_LONG( 40, image_size );
+ if ( image_size != 0 ) {
+ __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE,
+ data, image_size );
+ }
+ __GLX_END( cmdlen );
+ }
+ else {
+ __GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexSubImage3D,
+ cmdlen + 4 );
+ __GLX_PUT_LONG( 8, target );
+ __GLX_PUT_LONG( 12, level );
+ __GLX_PUT_LONG( 16, xoffset );
+ __GLX_PUT_LONG( 20, yoffset );
+ __GLX_PUT_LONG( 24, zoffset );
+ __GLX_PUT_LONG( 28, width );
+ __GLX_PUT_LONG( 32, height );
+ __GLX_PUT_LONG( 36, depth );
+ __GLX_PUT_LONG( 40, format );
+ __GLX_PUT_LONG( 44, image_size );
+ __glXSendLargeCommand( gc, gc->pc,
+ __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE + 4,
+ data, image_size );
+ }
+}
+++ /dev/null
-/*
- * (C) Copyright IBM Corporation 2004, 2005
- * 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
- * IBM,
- * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _INDIRECT_VA_PRIVATE_
-#define _INDIRECT_VA_PRIVATE_
-
-/**
- * \file indirect_va_private.h
- *
- * \author Ian Romanick <idr@us.ibm.com>
- */
-
-#include <inttypes.h>
-
-#include "glxclient.h"
-#include "indirect.h"
-#include <GL/glxproto.h>
-
-
-/**
- * State descriptor for a single array of vertex data.
- */
-struct array_state {
- /**
- * Pointer to the application supplied data.
- */
- const void * data;
-
- /**
- * Enum representing the type of the application supplied data.
- */
- GLenum data_type;
-
- /**
- * Stride value supplied by the application. This value is not used
- * internally. It is only kept so that it can be queried by the
- * application using glGet*v.
- */
- GLsizei user_stride;
-
- /**
- * Calculated size, in bytes, of a single element in the array. This
- * is calculated based on \c count and the size of the data type
- * represented by \c data_type.
- */
- GLsizei element_size;
-
- /**
- * Actual byte-stride from one element to the next. This value will
- * be equal to either \c user_stride or \c element_stride.
- */
- GLsizei true_stride;
-
- /**
- * Number of data values in each element.
- */
- GLint count;
-
- /**
- * "Normalized" data is on the range [0,1] (unsigned) or [-1,1] (signed).
- * This is used for mapping integral types to floating point types.
- */
- GLboolean normalized;
-
- /**
- * Pre-calculated GLX protocol command header.
- */
- uint32_t header[2];
-
- /**
- * Size of the header data. For simple data, like glColorPointerfv,
- * this is 4. For complex data that requires either a count (e.g.,
- * glWeightfvARB), an index (e.g., glVertexAttrib1fvARB), or a
- * selector enum (e.g., glMultiTexCoord2fv) this is 8.
- */
- unsigned header_size;
-
- /**
- * Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
- * to \c GL_FALSE.
- */
- GLboolean enabled;
-
- /**
- * For multi-arrayed data (e.g., texture coordinates, generic vertex
- * program attributes, etc.), this specifies which array this is.
- */
- unsigned index;
-
- /**
- * Per-array-type key. For most arrays, this will be the GL enum for
- * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
- * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
- * etc.).
- */
- GLenum key;
-
- /**
- * If this array can be used with the "classic" \c glDrawArrays protocol,
- * this is set to \c GL_TRUE. Otherwise, it is set to \c GL_FALSE.
- */
- GLboolean old_DrawArrays_possible;
-};
-
-
-/**
- * Array state that is pushed / poped by \c glPushClientAttrib and
- * \c glPopClientAttrib.
- */
-struct array_stack_state {
- /**
- * Pointer to the application supplied data.
- */
- const void * data;
-
- /**
- * Enum representing the type of the application supplied data.
- */
- GLenum data_type;
-
- /**
- * Stride value supplied by the application. This value is not used
- * internally. It is only kept so that it can be queried by the
- * application using glGet*v.
- */
- GLsizei user_stride;
-
- /**
- * Number of data values in each element.
- */
- GLint count;
-
- /**
- * Per-array-type key. For most arrays, this will be the GL enum for
- * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
- * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
- * etc.).
- */
- GLenum key;
-
- /**
- * For multi-arrayed data (e.g., texture coordinates, generic vertex
- * program attributes, etc.), this specifies which array this is.
- */
- unsigned index;
-
- /**
- * Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
- * to \c GL_FALSE.
- */
- GLboolean enabled;
-};
-
-
-/**
- * Collection of all the vertex array state.
- */
-struct array_state_vector {
- /**
- * Number of arrays tracked by \c ::arrays.
- */
- size_t num_arrays;
-
- /**
- * Array of vertex array state. This array contains all of the valid
- * vertex arrays. If a vertex array isn't in this array, then it isn't
- * valid. For example, if an implementation does not support
- * EXT_fog_coord, there won't be a GL_FOG_COORD_ARRAY entry in this
- * array.
- */
- struct array_state * arrays;
-
- /**
- * Number of currently enabled client-side arrays. The value of this
- * field is only valid if \c array_info_cache_valid is true.
- */
- size_t enabled_client_array_count;
-
- /**
- * \name ARRAY_INFO cache.
- *
- * These fields track the state of the ARRAY_INFO cache. The
- * \c array_info_cache_size is the size of the actual data stored in
- * \c array_info_cache. \c array_info_cache_buffer_size is the size of
- * the buffer. This will always be greater than or equal to
- * \c array_info_cache_size.
- *
- * \note
- * There are some bytes of extra data before \c array_info_cache that is
- * used to hold the header for RenderLarge commands. This is
- * \b not included in \c array_info_cache_size or
- * \c array_info_cache_buffer_size. \c array_info_cache_base stores a
- * pointer to the true start of the buffer (i.e., what malloc returned).
- */
- /*@{*/
- size_t array_info_cache_size;
- size_t array_info_cache_buffer_size;
- void * array_info_cache;
- void * array_info_cache_base;
- /*@}*/
-
-
- /**
- * Is the cache of ARRAY_INFO data valid? The cache can become invalid
- * when one of several state changes occur. Among these chages are
- * modifying the array settings for an enabled array and enabling /
- * disabling an array.
- */
- GLboolean array_info_cache_valid;
-
- /**
- * Is it possible to use the GL 1.1 / EXT_vertex_arrays protocol? Use
- * of this protocol is disabled with really old servers (i.e., servers
- * that don't support GL 1.1 or EXT_vertex_arrays) or when an environment
- * variable is set.
- *
- * \todo
- * GL 1.1 and EXT_vertex_arrays use identical protocol, but have different
- * opcodes for \c glDrawArrays. For servers that advertise one or the
- * other, there should be a way to select which opcode to use.
- */
- GLboolean old_DrawArrays_possible;
-
- /**
- * Is it possible to use the new GL X.X / ARB_vertex_buffer_object
- * protocol?
- *
- * \todo
- * This protocol has not yet been defined by the ARB, but is currently a
- * work in progress. This field is a place-holder.
- */
- GLboolean new_DrawArrays_possible;
-
- /**
- * Active texture unit set by \c glClientActiveTexture.
- *
- * \sa __glXGetActiveTextureUnit
- */
- unsigned active_texture_unit;
-
- /**
- * Number of supported texture units. Even if ARB_multitexture /
- * GL 1.3 are not supported, this will be at least 1. When multitexture
- * is supported, this will be the value queried by calling
- * \c glGetIntegerv with \c GL_MAX_TEXTURE_UNITS.
- *
- * \todo
- * Investigate if this should be the value of \c GL_MAX_TEXTURE_COORDS
- * instead (if GL 2.0 / ARB_fragment_shader / ARB_fragment_program /
- * NV_fragment_program are supported).
- */
- unsigned num_texture_units;
-
- /**
- * Number of generic vertex program attribs. If GL_ARB_vertex_program
- * is not supported, this will be zero. Otherwise it will be the value
- * queries by calling \c glGetProgramiv with \c GL_VERTEX_PROGRAM_ARB
- * and \c GL_MAX_PROGRAM_ATTRIBS_ARB.
- */
- unsigned num_vertex_program_attribs;
-
- /**
- * \n Methods for implementing various GL functions.
- *
- * These method pointers are only valid \c array_info_cache_valid is set.
- * When each function starts, it much check \c array_info_cache_valid.
- * If it is not set, it must call \c fill_array_info_cache and call
- * the new method.
- *
- * \sa fill_array_info_cache
- *
- * \todo
- * Write code to plug these functions directly into the dispatch table.
- */
- /*@{*/
- void (*DrawArrays)( GLenum, GLint, GLsizei );
- void (*DrawElements)( GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices );
- /*@}*/
-
- struct array_stack_state * stack;
- unsigned active_texture_unit_stack[ __GL_CLIENT_ATTRIB_STACK_DEPTH ];
- unsigned stack_index;
-};
-
-#endif /* _INDIRECT_VA_PRIVATE_ */
#include <GL/glxproto.h>
#include "glxextensions.h"
#include "indirect_vertex_array.h"
-#include "indirect_va_private.h"
+#include "indirect_vertex_array_priv.h"
#define __GLX_PAD(n) (((n)+3) & ~3)
--- /dev/null
+/*
+ * (C) Copyright IBM Corporation 2004, 2005
+ * 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
+ * IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _INDIRECT_VA_PRIVATE_
+#define _INDIRECT_VA_PRIVATE_
+
+/**
+ * \file indirect_va_private.h
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <inttypes.h>
+
+#include "glxclient.h"
+#include "indirect.h"
+#include <GL/glxproto.h>
+
+
+/**
+ * State descriptor for a single array of vertex data.
+ */
+struct array_state {
+ /**
+ * Pointer to the application supplied data.
+ */
+ const void * data;
+
+ /**
+ * Enum representing the type of the application supplied data.
+ */
+ GLenum data_type;
+
+ /**
+ * Stride value supplied by the application. This value is not used
+ * internally. It is only kept so that it can be queried by the
+ * application using glGet*v.
+ */
+ GLsizei user_stride;
+
+ /**
+ * Calculated size, in bytes, of a single element in the array. This
+ * is calculated based on \c count and the size of the data type
+ * represented by \c data_type.
+ */
+ GLsizei element_size;
+
+ /**
+ * Actual byte-stride from one element to the next. This value will
+ * be equal to either \c user_stride or \c element_stride.
+ */
+ GLsizei true_stride;
+
+ /**
+ * Number of data values in each element.
+ */
+ GLint count;
+
+ /**
+ * "Normalized" data is on the range [0,1] (unsigned) or [-1,1] (signed).
+ * This is used for mapping integral types to floating point types.
+ */
+ GLboolean normalized;
+
+ /**
+ * Pre-calculated GLX protocol command header.
+ */
+ uint32_t header[2];
+
+ /**
+ * Size of the header data. For simple data, like glColorPointerfv,
+ * this is 4. For complex data that requires either a count (e.g.,
+ * glWeightfvARB), an index (e.g., glVertexAttrib1fvARB), or a
+ * selector enum (e.g., glMultiTexCoord2fv) this is 8.
+ */
+ unsigned header_size;
+
+ /**
+ * Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
+ * to \c GL_FALSE.
+ */
+ GLboolean enabled;
+
+ /**
+ * For multi-arrayed data (e.g., texture coordinates, generic vertex
+ * program attributes, etc.), this specifies which array this is.
+ */
+ unsigned index;
+
+ /**
+ * Per-array-type key. For most arrays, this will be the GL enum for
+ * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
+ * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
+ * etc.).
+ */
+ GLenum key;
+
+ /**
+ * If this array can be used with the "classic" \c glDrawArrays protocol,
+ * this is set to \c GL_TRUE. Otherwise, it is set to \c GL_FALSE.
+ */
+ GLboolean old_DrawArrays_possible;
+};
+
+
+/**
+ * Array state that is pushed / poped by \c glPushClientAttrib and
+ * \c glPopClientAttrib.
+ */
+struct array_stack_state {
+ /**
+ * Pointer to the application supplied data.
+ */
+ const void * data;
+
+ /**
+ * Enum representing the type of the application supplied data.
+ */
+ GLenum data_type;
+
+ /**
+ * Stride value supplied by the application. This value is not used
+ * internally. It is only kept so that it can be queried by the
+ * application using glGet*v.
+ */
+ GLsizei user_stride;
+
+ /**
+ * Number of data values in each element.
+ */
+ GLint count;
+
+ /**
+ * Per-array-type key. For most arrays, this will be the GL enum for
+ * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
+ * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
+ * etc.).
+ */
+ GLenum key;
+
+ /**
+ * For multi-arrayed data (e.g., texture coordinates, generic vertex
+ * program attributes, etc.), this specifies which array this is.
+ */
+ unsigned index;
+
+ /**
+ * Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
+ * to \c GL_FALSE.
+ */
+ GLboolean enabled;
+};
+
+
+/**
+ * Collection of all the vertex array state.
+ */
+struct array_state_vector {
+ /**
+ * Number of arrays tracked by \c ::arrays.
+ */
+ size_t num_arrays;
+
+ /**
+ * Array of vertex array state. This array contains all of the valid
+ * vertex arrays. If a vertex array isn't in this array, then it isn't
+ * valid. For example, if an implementation does not support
+ * EXT_fog_coord, there won't be a GL_FOG_COORD_ARRAY entry in this
+ * array.
+ */
+ struct array_state * arrays;
+
+ /**
+ * Number of currently enabled client-side arrays. The value of this
+ * field is only valid if \c array_info_cache_valid is true.
+ */
+ size_t enabled_client_array_count;
+
+ /**
+ * \name ARRAY_INFO cache.
+ *
+ * These fields track the state of the ARRAY_INFO cache. The
+ * \c array_info_cache_size is the size of the actual data stored in
+ * \c array_info_cache. \c array_info_cache_buffer_size is the size of
+ * the buffer. This will always be greater than or equal to
+ * \c array_info_cache_size.
+ *
+ * \note
+ * There are some bytes of extra data before \c array_info_cache that is
+ * used to hold the header for RenderLarge commands. This is
+ * \b not included in \c array_info_cache_size or
+ * \c array_info_cache_buffer_size. \c array_info_cache_base stores a
+ * pointer to the true start of the buffer (i.e., what malloc returned).
+ */
+ /*@{*/
+ size_t array_info_cache_size;
+ size_t array_info_cache_buffer_size;
+ void * array_info_cache;
+ void * array_info_cache_base;
+ /*@}*/
+
+
+ /**
+ * Is the cache of ARRAY_INFO data valid? The cache can become invalid
+ * when one of several state changes occur. Among these chages are
+ * modifying the array settings for an enabled array and enabling /
+ * disabling an array.
+ */
+ GLboolean array_info_cache_valid;
+
+ /**
+ * Is it possible to use the GL 1.1 / EXT_vertex_arrays protocol? Use
+ * of this protocol is disabled with really old servers (i.e., servers
+ * that don't support GL 1.1 or EXT_vertex_arrays) or when an environment
+ * variable is set.
+ *
+ * \todo
+ * GL 1.1 and EXT_vertex_arrays use identical protocol, but have different
+ * opcodes for \c glDrawArrays. For servers that advertise one or the
+ * other, there should be a way to select which opcode to use.
+ */
+ GLboolean old_DrawArrays_possible;
+
+ /**
+ * Is it possible to use the new GL X.X / ARB_vertex_buffer_object
+ * protocol?
+ *
+ * \todo
+ * This protocol has not yet been defined by the ARB, but is currently a
+ * work in progress. This field is a place-holder.
+ */
+ GLboolean new_DrawArrays_possible;
+
+ /**
+ * Active texture unit set by \c glClientActiveTexture.
+ *
+ * \sa __glXGetActiveTextureUnit
+ */
+ unsigned active_texture_unit;
+
+ /**
+ * Number of supported texture units. Even if ARB_multitexture /
+ * GL 1.3 are not supported, this will be at least 1. When multitexture
+ * is supported, this will be the value queried by calling
+ * \c glGetIntegerv with \c GL_MAX_TEXTURE_UNITS.
+ *
+ * \todo
+ * Investigate if this should be the value of \c GL_MAX_TEXTURE_COORDS
+ * instead (if GL 2.0 / ARB_fragment_shader / ARB_fragment_program /
+ * NV_fragment_program are supported).
+ */
+ unsigned num_texture_units;
+
+ /**
+ * Number of generic vertex program attribs. If GL_ARB_vertex_program
+ * is not supported, this will be zero. Otherwise it will be the value
+ * queries by calling \c glGetProgramiv with \c GL_VERTEX_PROGRAM_ARB
+ * and \c GL_MAX_PROGRAM_ATTRIBS_ARB.
+ */
+ unsigned num_vertex_program_attribs;
+
+ /**
+ * \n Methods for implementing various GL functions.
+ *
+ * These method pointers are only valid \c array_info_cache_valid is set.
+ * When each function starts, it much check \c array_info_cache_valid.
+ * If it is not set, it must call \c fill_array_info_cache and call
+ * the new method.
+ *
+ * \sa fill_array_info_cache
+ *
+ * \todo
+ * Write code to plug these functions directly into the dispatch table.
+ */
+ /*@{*/
+ void (*DrawArrays)( GLenum, GLint, GLsizei );
+ void (*DrawElements)( GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices );
+ /*@}*/
+
+ struct array_stack_state * stack;
+ unsigned active_texture_unit_stack[ __GL_CLIENT_ATTRIB_STACK_DEPTH ];
+ unsigned stack_index;
+};
+
+#endif /* _INDIRECT_VA_PRIVATE_ */
$(OSMESA_DRIVER_OBJECTS)
-stand-alone: depend subdirs $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
+stand-alone: depend subdirs libmesa.a \
+ $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
-osmesa-only: depend subdirs $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME)
+osmesa-only: depend subdirs \
+ $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME)
# Make the GL library
$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(STAND_ALONE_OBJECTS)
+++ /dev/null
-MESA_DRIVER_COMMON_SOURCES = \
-driverfuncs.c
dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
dri_bufmgr_fake *bufmgr_fake= (dri_bufmgr_fake *)bo->bufmgr;
struct block *block = (struct block *)calloc(sizeof *block, 1);
- unsigned int align_log2 = _mesa_ffs(bo_fake->alignment);
+ unsigned int align_log2 = _mesa_ffs(bo_fake->alignment) - 1;
GLuint sz;
if (!block)
static void free_block(dri_bufmgr_fake *bufmgr_fake, struct block *block)
{
dri_bo_fake *bo_fake;
- DBG("free block %p\n", block);
+ DBG("free block %p %08x %d %d\n", block, block->mem->ofs, block->on_hardware, block->fenced);
if (!block)
return;
bo_fake = (dri_bo_fake *)block->bo;
- if (bo_fake->card_dirty == GL_TRUE) {
- memcpy(bo_fake->backing_store, block->virtual, block->bo->size);
- bo_fake->card_dirty = GL_FALSE;
- bo_fake->dirty = GL_TRUE;
+ if (!(bo_fake->flags & BM_NO_BACKING_STORE) && (bo_fake->card_dirty == 1)) {
+ memcpy(bo_fake->backing_store, block->virtual, block->bo->size);
+ bo_fake->card_dirty = 1;
+ bo_fake->dirty = 1;
}
if (block->on_hardware) {
/* Blocks are ordered by fence, so if one fails, all from
* here will fail also:
*/
+ DBG("fence not passed: offset %x sz %x %d %d \n",
+ block->mem->ofs, block->mem->size, block->fence, bufmgr_fake->last_fence);
break;
}
}
struct block *block, *tmp;
foreach_s (block, tmp, &bufmgr_fake->on_hardware) {
- DBG("Fence block %p (sz 0x%x buf %p) with fence %d\n", block,
- block->mem->size, block->bo, fence);
+ DBG("Fence block %p (sz 0x%x ofs %x buf %p) with fence %d\n", block,
+ block->mem->size, block->mem->ofs, block->bo, fence);
block->fence = fence;
block->on_hardware = 0;
free_block(bufmgr_fake, block);
bo_fake->block = NULL;
bo_fake->validated = GL_FALSE;
- bo_fake->dirty = GL_TRUE;
- block->bo->offset = -1;
+ if (!(bo_fake->flags & BM_NO_BACKING_STORE))
+ bo_fake->dirty = 1;
}
}
*/
dri_bufmgr_fake_wait_idle(bufmgr_fake);
- /* we may never have mapped this BO so it might not have any backing store */
- /* if this happens it should be rare, but 0 the card memory in any case */
+ /* we may never have mapped this BO so it might not have any backing
+ * store if this happens it should be rare, but 0 the card memory
+ * in any case */
if (bo_fake->backing_store)
- memcpy(bo_fake->block->virtual, bo_fake->backing_store, bo->size);
+ memcpy(bo_fake->block->virtual, bo_fake->backing_store, bo->size);
else
- memset(bo_fake->block->virtual, 0, bo->size);
+ memset(bo_fake->block->virtual, 0, bo->size);
bo_fake->dirty = 0;
}
+ bo_fake->block->fenced = 0;
bo_fake->block->on_hardware = 1;
move_to_tail(&bufmgr_fake->on_hardware, bo_fake->block);
struct fake_buffer_reloc *r;
dri_bo_fake *reloc_fake = (dri_bo_fake *)reloc_buf;
dri_bo_fake *target_fake = (dri_bo_fake *)target_buf;
- int ret, i;
+ int i;
assert(reloc_buf);
assert(target_buf);
- if (!target_fake->is_static && !target_fake->size_accounted) {
- ret = dri_fake_check_aperture_space(target_buf);
- if (ret)
- return ret;
- }
+ assert(target_fake->is_static || target_fake->size_accounted);
if (reloc_fake->relocs == NULL) {
reloc_fake->relocs = malloc(sizeof(struct fake_buffer_reloc) *
/* Validate the target buffer if that hasn't been done. */
if (!target_fake->validated) {
- ret = dri_fake_reloc_and_validate_buffer(r->target_buf);
- if (ret != 0) {
- if (bo->virtual != NULL)
- dri_bo_unmap(bo);
- return ret;
- }
+ ret = dri_fake_reloc_and_validate_buffer(r->target_buf);
+ if (ret != 0) {
+ if (bo->virtual != NULL)
+ dri_bo_unmap(bo);
+ return ret;
+ }
}
/* Calculate the value of the relocation entry. */
if (bo_fake->validate_flags & DRM_BO_FLAG_WRITE) {
if (!(bo_fake->flags & (BM_NO_BACKING_STORE|BM_PINNED))) {
if (bo_fake->backing_store == 0)
- alloc_backing_store(bo);
+ alloc_backing_store(bo);
- bo_fake->card_dirty = GL_TRUE;
+ bo_fake->card_dirty = 1;
}
bufmgr_fake->performed_rendering = GL_TRUE;
}
ret = dri_fake_reloc_and_validate_buffer(batch_buf);
if (bufmgr_fake->fail == 1) {
if (retry_count == 0) {
- retry_count++;
- dri_fake_kick_all(bufmgr_fake);
- bufmgr_fake->fail = 0;
- goto restart;
- }
+ retry_count++;
+ dri_fake_kick_all(bufmgr_fake);
+ bufmgr_fake->fail = 0;
+ goto restart;
+ } else /* dump out the memory here */
+ mmDumpMemInfo(bufmgr_fake->heap);
}
+
assert(ret == 0);
*count_p = 0; /* junk */
return 0;
if (bufmgr_fake->current_total_size + sz > bufmgr_fake->size) {
- DBG("check_space: bo %d %d overflowed bufmgr\n", bo_fake->id, sz);
+ DBG("check_space: %s bo %d %d overflowed bufmgr size %d\n", bo_fake->name, bo_fake->id, sz, bufmgr_fake->size);
return -1;
}
bufmgr_fake->current_total_size += sz;
bo_fake->size_accounted = 1;
- DBG("check_space: bo %d %d %d\n", bo_fake->id, bo->size, bufmgr_fake->current_total_size);
+ DBG("drm_check_space: buf %d, %s %d %d\n", bo_fake->id, bo_fake->name, bo->size, bufmgr_fake->current_total_size);
return 0;
}
#define _DRI_UTIL_H_
#include <GL/gl.h>
-#include "drm.h"
-#include "drm_sarea.h"
-#include "xf86drm.h"
+#include <drm.h>
+#include <drm_sarea.h>
+#include <xf86drm.h>
+#include <xf86mm.h>
#include "GL/internal/glcore.h"
#include "GL/internal/dri_interface.h"
#include "GL/internal/dri_sarea.h"
/** \brief Parse a value of a given type. */
static GLboolean parseValue (driOptionValue *v, driOptionType type,
const XML_Char *string) {
- const XML_Char *tail;
+ const XML_Char *tail = NULL;
/* skip leading white-space */
string += strspn (string, " \f\n\r\t\v");
switch (type) {
ret = 0;
if (dirty & I915_UPLOAD_BUFFERS) {
ret |= dri_bufmgr_check_aperture_space(state->draw_region->buffer);
- ret |= dri_bufmgr_check_aperture_space(state->depth_region->buffer);
+ if (state->depth_region)
+ ret |= dri_bufmgr_check_aperture_space(state->depth_region->buffer);
}
if (dirty & I915_UPLOAD_TEX_ALL) {
#include "macros.h"
#include "enums.h"
-static void upload_cc_vp( struct brw_context *brw )
+static int upload_cc_vp( struct brw_context *brw )
{
struct brw_cc_viewport ccv;
dri_bo_unreference(brw->cc.vp_bo);
brw->cc.vp_bo = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0 );
+ return dri_bufmgr_check_aperture_space(brw->cc.vp_bo);
}
const struct brw_tracked_state brw_cc_vp = {
.brw = BRW_NEW_CONTEXT,
.cache = 0
},
- .update = upload_cc_vp
+ .prepare = upload_cc_vp
};
struct brw_cc_unit_key {
return bo;
}
-static void upload_cc_unit( struct brw_context *brw )
+static int prepare_cc_unit( struct brw_context *brw )
{
struct brw_cc_unit_key key;
if (brw->cc.state_bo == NULL)
brw->cc.state_bo = cc_unit_create_from_key(brw, &key);
+ return dri_bufmgr_check_aperture_space(brw->cc.state_bo);
}
const struct brw_tracked_state brw_cc_unit = {
.brw = 0,
.cache = CACHE_NEW_CC_VP
},
- .update = upload_cc_unit,
+ .prepare = prepare_cc_unit,
};
/* Calculate interpolants for triangle and line rasterization.
*/
-static void upload_clip_prog( struct brw_context *brw )
+static int upload_clip_prog( struct brw_context *brw )
{
GLcontext *ctx = &brw->intel.ctx;
struct brw_clip_prog_key key;
&brw->clip.prog_data);
if (brw->clip.prog_bo == NULL)
compile_clip_prog( brw, &key );
+
+ return dri_bufmgr_check_aperture_space(brw->clip.prog_bo);
}
.brw = (BRW_NEW_REDUCED_PRIMITIVE),
.cache = CACHE_NEW_VS_PROG
},
- .update = upload_clip_prog
+ .prepare = upload_clip_prog
};
brw_clip_init_clipmask(c);
/* -ve rhw workaround */
- brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
- brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
- brw_imm_ud(1<<20));
- brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
+ if (!BRW_IS_IGD(p->brw)) {
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
+ brw_imm_ud(1<<20));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
+ }
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
return bo;
}
-static void upload_clip_unit( struct brw_context *brw )
+static int upload_clip_unit( struct brw_context *brw )
{
struct brw_clip_unit_key key;
+ int ret = 0;
clip_unit_populate_key(brw, &key);
if (brw->clip.state_bo == NULL) {
brw->clip.state_bo = clip_unit_create_from_key(brw, &key);
}
+
+ ret = dri_bufmgr_check_aperture_space(brw->clip.state_bo);
+ return ret;
}
const struct brw_tracked_state brw_clip_unit = {
BRW_NEW_URB_FENCE),
.cache = CACHE_NEW_CLIP_PROG
},
- .update = upload_clip_unit,
+ .prepare = upload_clip_unit,
};
/* if -ve rhw workaround bit is set,
do cliptest */
- brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
- brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
- brw_imm_ud(1<<20));
- neg_rhw = brw_IF(p, BRW_EXECUTE_1);
- {
- brw_clip_test(c);
+ if (!BRW_IS_IGD(p->brw)) {
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
+ brw_imm_ud(1<<20));
+ neg_rhw = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_test(c);
+ }
+ brw_ENDIF(p, neg_rhw);
}
- brw_ENDIF(p, neg_rhw);
/* Can't push into do_clip_tri because with polygon (or quad)
* flatshading, need to apply the flatshade here because we don't
* respect the PV when converting to trifan for emit:
*/
struct brw_tracked_state {
struct brw_state_flags dirty;
- void (*update)( struct brw_context *brw );
+ int (*prepare)( struct brw_context *brw );
+ void (*emit)( struct brw_context *brw );
};
/* Flags for brw->state.cache.
/*======================================================================
* brw_state.c
*/
-void brw_validate_state( struct brw_context *brw );
+int brw_validate_state( struct brw_context *brw );
void brw_init_state( struct brw_context *brw );
void brw_destroy_state( struct brw_context *brw );
/* Partition the CURBE between the various users of constant values:
*/
-static void calculate_curbe_offsets( struct brw_context *brw )
+static int calculate_curbe_offsets( struct brw_context *brw )
{
/* CACHE_NEW_WM_PROG */
GLuint nr_fp_regs = (brw->wm.prog_data->nr_params + 15) / 16;
brw->state.dirty.brw |= BRW_NEW_CURBE_OFFSETS;
}
+ return 0;
}
.brw = BRW_NEW_VERTEX_PROGRAM,
.cache = CACHE_NEW_WM_PROG
},
- .update = calculate_curbe_offsets
+ .prepare = calculate_curbe_offsets
};
* cache mechanism, but maybe would benefit from a comparison against
* the current uploaded set of constants.
*/
-static void upload_constant_buffer(struct brw_context *brw)
+static int prepare_constant_buffer(struct brw_context *brw)
{
- struct intel_context *intel = &brw->intel;
GLcontext *ctx = &brw->intel.ctx;
struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program;
struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program;
brw->curbe.tracked_state.dirty.mesa |= fp->param_state;
if (sz == 0) {
- BEGIN_BATCH(2, IGNORE_CLIPRECTS);
- OUT_BATCH((CMD_CONST_BUFFER << 16) | (2 - 2));
- OUT_BATCH(0);
- ADVANCE_BATCH();
if (brw->curbe.last_buf) {
free(brw->curbe.last_buf);
brw->curbe.last_bufsz = 0;
}
- return;
+ return 0;
}
buf = (GLfloat *)malloc(bufsz);
dri_bo_subdata(brw->curbe.curbe_bo, brw->curbe.curbe_offset, bufsz, buf);
}
+
/* Because this provokes an action (ie copy the constants into the
* URB), it shouldn't be shortcircuited if identical to the
* previous time - because eg. the urb destination may have
* flushes as necessary when doublebuffering of CURBEs isn't
* possible.
*/
+
+ /* check aperture space for this bo */
+ return dri_bufmgr_check_aperture_space(brw->curbe.curbe_bo);
+}
+
+
+static void emit_constant_buffer(struct brw_context *brw)
+{
+ struct intel_context *intel = &brw->intel;
+ GLuint sz = brw->curbe.total_size;
+
BEGIN_BATCH(2, IGNORE_CLIPRECTS);
- OUT_BATCH((CMD_CONST_BUFFER << 16) | (1 << 8) | (2 - 2));
- OUT_RELOC(brw->curbe.curbe_bo, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- (sz - 1) + brw->curbe.curbe_offset);
+ if (sz == 0) {
+ OUT_BATCH((CMD_CONST_BUFFER << 16) | (2 - 2));
+ OUT_BATCH(0);
+ } else {
+ OUT_BATCH((CMD_CONST_BUFFER << 16) | (1 << 8) | (2 - 2));
+ OUT_RELOC(brw->curbe.curbe_bo, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ (sz - 1) + brw->curbe.curbe_offset);
+ }
ADVANCE_BATCH();
}
BRW_NEW_BATCH),
.cache = (CACHE_NEW_WM_PROG)
},
- .update = upload_constant_buffer,
+ .prepare = prepare_constant_buffer,
+ .emit = emit_constant_buffer,
};
* programs be immune to the active primitive (ie. cope with all
* possibilities). That may not be realistic however.
*/
-static GLuint brw_set_prim(struct brw_context *brw, GLenum prim)
+static GLuint brw_set_prim(struct brw_context *brw, GLenum prim, GLboolean *need_flush)
{
+ int ret;
if (INTEL_DEBUG & DEBUG_PRIMS)
_mesa_printf("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim));
brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE;
}
- brw_validate_state(brw);
+ ret = brw_validate_state(brw);
+ if (ret)
+ *need_flush = GL_TRUE;
}
return hw_prim[prim];
{
struct brw_3d_primitive prim_packet;
+ GLboolean need_flush = GL_FALSE;
if (INTEL_DEBUG & DEBUG_PRIMS)
_mesa_printf("PRIM: %s %d %d\n", _mesa_lookup_enum_by_nr(prim->mode),
prim_packet.header.opcode = CMD_3D_PRIM;
prim_packet.header.length = sizeof(prim_packet)/4 - 2;
prim_packet.header.pad = 0;
- prim_packet.header.topology = brw_set_prim(brw, prim->mode);
+ prim_packet.header.topology = brw_set_prim(brw, prim->mode, &need_flush);
prim_packet.header.indexed = prim->indexed;
prim_packet.verts_per_instance = trim(prim->mode, prim->count);
intel_batchbuffer_data( brw->intel.batch, &prim_packet,
sizeof(prim_packet), LOOP_CLIPRECTS);
}
+
+ assert(need_flush == GL_FALSE);
}
static void brw_merge_inputs( struct brw_context *brw,
struct intel_context *intel = intel_context(ctx);
struct brw_context *brw = brw_context(ctx);
GLboolean retval = GL_FALSE;
- GLuint i;
-
+ GLuint i, ret;
+ GLuint ib_offset;
+ dri_bo *ib_bo;
+ GLboolean force_flush = GL_FALSE;
if (ctx->NewState)
_mesa_update_state( ctx );
* an upper bound of how much we might emit in a single
* brw_try_draw_prims().
*/
+ flush:
+ if (force_flush)
+ brw->no_batch_wrap = GL_FALSE;
+
if (intel->batch->ptr - intel->batch->map > intel->batch->size * 3 / 4
/* brw_emit_prim may change the cliprect_mode to LOOP_CLIPRECTS */
- || intel->batch->cliprect_mode != LOOP_CLIPRECTS)
+ || intel->batch->cliprect_mode != LOOP_CLIPRECTS || (force_flush == GL_TRUE))
intel_batchbuffer_flush(intel->batch);
+ force_flush = GL_FALSE;
brw->no_batch_wrap = GL_TRUE;
/* Set the first primitive early, ahead of validate_state:
*/
- brw_set_prim(brw, prim[0].mode);
+ brw_set_prim(brw, prim[0].mode, &force_flush);
/* XXX: Need to separate validate and upload of state.
*/
- brw_validate_state( brw );
+ ret = brw_validate_state( brw );
+ if (ret) {
+ force_flush = GL_TRUE;
+ goto flush;
+ }
+
+ /* need to account for index buffer and vertex buffer */
+ if (ib) {
+ ret = brw_prepare_indices( brw, ib , &ib_bo, &ib_offset);
+ if (ret) {
+ force_flush = GL_TRUE;
+ goto flush;
+ }
+ }
+
+ ret = brw_prepare_vertices( brw, min_index, max_index);
+ if (ret < 0)
+ goto out;
+
+ if (ret > 0) {
+ force_flush = GL_TRUE;
+ goto flush;
+ }
+
+
/* Various fallback checks:
*/
/* Upload index, vertex data:
*/
if (ib)
- brw_upload_indices( brw, ib );
+ brw_emit_indices( brw, ib, ib_bo, ib_offset);
- if (!brw_upload_vertices( brw, min_index, max_index)) {
- goto out;
- }
+ brw_emit_vertices( brw, min_index, max_index);
for (i = 0; i < nr_prims; i++) {
brw_emit_prim(brw, &prim[i]);
#include "mtypes.h" /* for GLcontext... */
#include "vbo/vbo.h"
+#include "dri_bufmgr.h"
struct brw_context;
/* brw_draw_upload.c
*/
-void brw_upload_indices( struct brw_context *brw,
- const struct _mesa_index_buffer *index_buffer);
+int brw_prepare_indices( struct brw_context *brw,
+ const struct _mesa_index_buffer *index_buffer,
+ dri_bo **bo_return,
+ GLuint *offset_return);
-GLboolean brw_upload_vertices( struct brw_context *brw,
+void brw_emit_indices( struct brw_context *brw,
+ const struct _mesa_index_buffer *index_buffer,
+ dri_bo *bo,
+ GLuint offset);
+
+int brw_prepare_vertices( struct brw_context *brw,
+ GLuint min_index,
+ GLuint max_index );
+
+void brw_emit_vertices( struct brw_context *brw,
GLuint min_index,
GLuint max_index );
/* Set the internal VBO\ to no-backing-store. We only use them as a
* temporary within a brw_try_draw_prims while the lock is held.
*/
- if (!brw->intel.ttm)
- dri_bo_fake_disable_backing_store(brw->vb.upload.bo, NULL, NULL);
+ /* DON'T DO THIS AS IF WE HAVE TO RE-ORG MEMORY WE NEED SOMEWHERE WITH
+ FAKE TO PUSH THIS STUFF */
+// if (!brw->intel.ttm)
+// dri_bo_fake_disable_backing_store(brw->vb.upload.bo, NULL, NULL);
}
static void get_space( struct brw_context *brw,
dri_bo_unmap(element->bo);
}
-GLboolean brw_upload_vertices( struct brw_context *brw,
+int brw_prepare_vertices( struct brw_context *brw,
GLuint min_index,
GLuint max_index )
{
GLuint i;
const unsigned char *ptr = NULL;
GLuint interleave = 0;
+ int ret = 0;
struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
GLuint nr_enabled = 0;
* isn't an issue at this point.
*/
if (nr_enabled >= BRW_VEP_MAX)
- return GL_FALSE;
+ return -1;
for (i = 0; i < nr_enabled; i++) {
struct brw_vertex_element *input = enabled[i];
dri_bo_reference(input->bo);
input->offset = (unsigned long)input->glarray->Ptr;
input->stride = input->glarray->StrideB;
+
+ ret |= dri_bufmgr_check_aperture_space(input->bo);
} else {
/* Queue the buffer object up to be uploaded in the next pass,
* when we've decided if we're doing interleaved or not.
/* Position array not properly enabled:
*/
if (input->glarray->StrideB == 0)
- return GL_FALSE;
+ return -1;
interleave = input->glarray->StrideB;
ptr = input->glarray->Ptr;
}
}
+ if (brw->vb.upload.bo) {
+ ret |= dri_bufmgr_check_aperture_space(brw->vb.upload.bo);
+ }
+
+ if (ret)
+ return 1;
+
+
+ return 0;
+}
+
+void brw_emit_vertices( struct brw_context *brw,
+ GLuint min_index,
+ GLuint max_index )
+{
+ GLcontext *ctx = &brw->intel.ctx;
+ struct intel_context *intel = intel_context(ctx);
+ GLuint tmp = brw->vs.prog_data->inputs_read;
+ struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
+ GLuint i;
+ GLuint nr_enabled = 0;
+
+ /* Accumulate the list of enabled arrays. */
+ while (tmp) {
+ i = _mesa_ffsll(tmp)-1;
+ struct brw_vertex_element *input = &brw->vb.inputs[i];
+
+ tmp &= ~(1<<i);
+ enabled[nr_enabled++] = input;
+ }
+
+
/* Now emit VB and VEP state packets.
*
* This still defines a hardware VB for each input, even if they
((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
}
ADVANCE_BATCH();
-
- return GL_TRUE;
}
-void brw_upload_indices( struct brw_context *brw,
- const struct _mesa_index_buffer *index_buffer )
+int brw_prepare_indices( struct brw_context *brw,
+ const struct _mesa_index_buffer *index_buffer,
+ dri_bo **bo_return,
+ GLuint *offset_return)
{
GLcontext *ctx = &brw->intel.ctx;
struct intel_context *intel = &brw->intel;
dri_bo *bo;
struct gl_buffer_object *bufferobj = index_buffer->obj;
GLuint offset = (GLuint)index_buffer->ptr;
+ int ret;
/* Turn into a proper VBO:
*/
}
}
+ *bo_return = bo;
+ *offset_return = offset;
+ ret = dri_bufmgr_check_aperture_space(bo);
+ return ret;
+}
+
+void brw_emit_indices(struct brw_context *brw,
+ const struct _mesa_index_buffer *index_buffer,
+ dri_bo *bo,
+ GLuint offset)
+{
+ struct intel_context *intel = &brw->intel;
+ GLuint ib_size = get_size(index_buffer->type) * index_buffer->count;
/* Emit the indexbuffer packet:
*/
{
dri_bo_unreference(bo);
}
}
+
static __inline struct brw_reg brw_imm_uw( GLushort uw )
{
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
- imm.dw1.ud = uw;
+ imm.dw1.ud = uw | (uw << 16);
return imm;
}
static __inline struct brw_reg brw_imm_w( GLshort w )
{
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
- imm.dw1.d = w;
+ imm.dw1.d = w | (w << 16);
return imm;
}
return GL_FALSE;
}
-static void check_fallback(struct brw_context *brw)
+static int check_fallback(struct brw_context *brw)
{
brw->intel.Fallback = do_check_fallback(brw);
+ return 0;
}
const struct brw_tracked_state brw_check_fallback = {
.brw = BRW_NEW_METAOPS,
.cache = 0
},
- .update = check_fallback
+ .prepare = check_fallback
};
/* Calculate interpolants for triangle and line rasterization.
*/
-static void upload_gs_prog( struct brw_context *brw )
+static int prepare_gs_prog( struct brw_context *brw )
{
struct brw_gs_prog_key key;
-
+ int ret = 0;
/* Populate the key:
*/
populate_key(brw, &key);
&brw->gs.prog_data);
if (brw->gs.prog_bo == NULL)
compile_gs_prog( brw, &key );
+
+ ret |= dri_bufmgr_check_aperture_space(brw->gs.prog_bo);
}
+
+ return ret;
}
.brw = BRW_NEW_PRIMITIVE,
.cache = CACHE_NEW_VS_PROG
},
- .update = upload_gs_prog
+ .prepare = prepare_gs_prog
};
return bo;
}
-static void upload_gs_unit( struct brw_context *brw )
+static int prepare_gs_unit( struct brw_context *brw )
{
struct brw_gs_unit_key key;
if (brw->gs.state_bo == NULL) {
brw->gs.state_bo = gs_unit_create_from_key(brw, &key);
}
+ return dri_bufmgr_check_aperture_space(brw->gs.state_bo);
}
const struct brw_tracked_state brw_gs_unit = {
BRW_NEW_URB_FENCE),
.cache = CACHE_NEW_GS_PROG
},
- .update = upload_gs_unit,
+ .prepare = prepare_gs_unit,
};
.brw = 0,
.cache = 0
},
- .update = upload_blend_constant_color
+ .emit = upload_blend_constant_color
};
/**
.brw = BRW_NEW_BATCH,
.cache = CACHE_NEW_SURF_BIND,
},
- .update = upload_binding_table_pointers,
+ .emit = upload_binding_table_pointers,
};
CACHE_NEW_WM_UNIT |
CACHE_NEW_CC_UNIT)
},
- .update = upload_pipelined_state_pointers
+ .emit = upload_pipelined_state_pointers
};
#endif
CACHE_NEW_WM_UNIT |
CACHE_NEW_CC_UNIT)
},
- .update = upload_psp_urb_cbs,
+ .emit = upload_psp_urb_cbs,
};
/**
* We have to do this per state validation as we need to emit the relocation
* in the batch buffer.
*/
-static void upload_depthbuffer(struct brw_context *brw)
+
+static int prepare_depthbuffer(struct brw_context *brw)
+{
+ struct intel_region *region = brw->state.depth_region;
+
+ if (!region || !region->buffer)
+ return 0;
+ return dri_bufmgr_check_aperture_space(region->buffer);
+}
+
+static void emit_depthbuffer(struct brw_context *brw)
{
struct intel_context *intel = &brw->intel;
struct intel_region *region = brw->state.depth_region;
.brw = BRW_NEW_DEPTH_BUFFER | BRW_NEW_BATCH,
.cache = 0,
},
- .update = upload_depthbuffer,
+ .prepare = prepare_depthbuffer,
+ .emit = emit_depthbuffer,
};
.brw = 0,
.cache = 0
},
- .update = upload_polygon_stipple
+ .emit = upload_polygon_stipple
};
.brw = 0,
.cache = 0
},
- .update = upload_polygon_stipple_offset
+ .emit = upload_polygon_stipple_offset
};
/**********************************************************************
.brw = BRW_NEW_CONTEXT,
.cache = 0
},
- .update = upload_aa_line_parameters
+ .emit = upload_aa_line_parameters
};
/***********************************************************************
.brw = 0,
.cache = 0
},
- .update = upload_line_stipple
+ .emit = upload_line_stipple
};
.brw = BRW_NEW_BATCH,
.cache = 0
},
- .update = upload_pipe_control
+ .emit = upload_pipe_control
};
.brw = BRW_NEW_CONTEXT,
.cache = 0
},
- .update = upload_invarient_state
+ .emit = upload_invarient_state
};
/**
.brw = BRW_NEW_CONTEXT,
.cache = 0,
},
- .update = upload_state_base_address
+ .emit = upload_state_base_address
};
/* Calculate interpolants for triangle and line rasterization.
*/
-static void upload_sf_prog( struct brw_context *brw )
+static int upload_sf_prog( struct brw_context *brw )
{
struct brw_sf_prog_key key;
&brw->sf.prog_data);
if (brw->sf.prog_bo == NULL)
compile_sf_prog( brw, &key );
+ return dri_bufmgr_check_aperture_space(brw->sf.prog_bo);
}
.brw = (BRW_NEW_REDUCED_PRIMITIVE),
.cache = CACHE_NEW_VS_PROG
},
- .update = upload_sf_prog
+ .prepare = upload_sf_prog
};
#include "macros.h"
#include "intel_fbo.h"
-static void upload_sf_vp(struct brw_context *brw)
+static int upload_sf_vp(struct brw_context *brw)
{
GLcontext *ctx = &brw->intel.ctx;
const GLfloat depth_scale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
dri_bo_unreference(brw->sf.vp_bo);
brw->sf.vp_bo = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0 );
+
+ return dri_bufmgr_check_aperture_space(brw->sf.vp_bo);
}
const struct brw_tracked_state brw_sf_vp = {
.brw = BRW_NEW_METAOPS,
.cache = 0
},
- .update = upload_sf_vp
+ .prepare = upload_sf_vp
};
struct brw_sf_unit_key {
return bo;
}
-static void upload_sf_unit( struct brw_context *brw )
+static int upload_sf_unit( struct brw_context *brw )
{
struct brw_sf_unit_key key;
dri_bo *reloc_bufs[2];
+ int ret = 0;
sf_unit_populate_key(brw, &key);
if (brw->sf.state_bo == NULL) {
brw->sf.state_bo = sf_unit_create_from_key(brw, &key, reloc_bufs);
}
+
+ if (reloc_bufs[0])
+ ret |= dri_bufmgr_check_aperture_space(reloc_bufs[0]);
+
+ if (reloc_bufs[1])
+ ret |= dri_bufmgr_check_aperture_space(reloc_bufs[1]);
+
+ ret |= dri_bufmgr_check_aperture_space(brw->sf.state_bo);
+ return ret;
}
const struct brw_tracked_state brw_sf_unit = {
.cache = (CACHE_NEW_SF_VP |
CACHE_NEW_SF_PROG)
},
- .update = upload_sf_unit,
+ .prepare = upload_sf_unit,
};
/***********************************************************************
* Emit all state:
*/
-void brw_validate_state( struct brw_context *brw )
+int brw_validate_state( struct brw_context *brw )
{
struct brw_state_flags *state = &brw->state.dirty;
- GLuint i;
+ GLuint i, ret, count;
state->mesa |= brw->intel.NewGLState;
brw->intel.NewGLState = 0;
if (state->mesa == 0 &&
state->cache == 0 &&
state->brw == 0)
- return;
+ return 0;
if (brw->state.dirty.brw & BRW_NEW_CONTEXT)
brw_clear_batch_cache_flush(brw);
brw->intel.Fallback = 0;
+ count = 0;
+
+ /* do prepare stage for all atoms */
+ for (i = 0; i < Elements(atoms); i++) {
+ const struct brw_tracked_state *atom = brw->state.atoms[i];
+
+ if (brw->intel.Fallback)
+ break;
+
+ if (check_state(state, &atom->dirty)) {
+ if (atom->prepare) {
+ ret = atom->prepare(brw);
+ if (ret)
+ return ret;
+ }
+ }
+ }
+
+ if (brw->intel.Fallback)
+ return 0;
+
if (INTEL_DEBUG) {
/* Debug version which enforces various sanity checks on the
* state flags which are generated and checked to help ensure
assert(atom->dirty.mesa ||
atom->dirty.brw ||
atom->dirty.cache);
- assert(atom->update);
if (brw->intel.Fallback)
break;
if (check_state(state, &atom->dirty)) {
- atom->update( brw );
-
-/* emit_foo(brw); */
+ if (atom->emit)
+ atom->emit( brw );
}
accumulate_state(&examined, &atom->dirty);
if (brw->intel.Fallback)
break;
- if (check_state(state, &atom->dirty))
- atom->update( brw );
+ if (check_state(state, &atom->dirty)) {
+ if (atom->emit)
+ atom->emit( brw );
+ }
}
}
if (!brw->intel.Fallback)
memset(state, 0, sizeof(*state));
+ return 0;
}
GLuint min_entry_size;
GLuint max_entry_size;
} limits[CS+1] = {
- { 8, 32, 1, 5 }, /* vs */
+ { 16, 32, 1, 5 }, /* vs */
{ 4, 8, 1, 5 }, /* gs */
{ 6, 8, 1, 5 }, /* clp */
{ 1, 8, 1, 12 }, /* sf */
/* Most minimal update, forces re-emit of URB fence packet after GS
* unit turned on/off.
*/
-static void recalculate_urb_fence( struct brw_context *brw )
+static int recalculate_urb_fence( struct brw_context *brw )
{
GLuint csize = brw->curbe.total_size;
GLuint vsize = brw->vs.prog_data->urb_entry_size;
brw->state.dirty.brw |= BRW_NEW_URB_FENCE;
}
+ return 0;
}
.cache = (CACHE_NEW_VS_PROG |
CACHE_NEW_SF_PROG)
},
- .update = recalculate_urb_fence
+ .prepare = recalculate_urb_fence
};
}
-static void brw_upload_vs_prog( struct brw_context *brw )
+static int brw_upload_vs_prog( struct brw_context *brw )
{
struct brw_vs_prog_key key;
struct brw_vertex_program *vp =
&brw->vs.prog_data);
if (brw->vs.prog_bo == NULL)
do_vs_prog(brw, vp, &key);
+ return dri_bufmgr_check_aperture_space(brw->vs.prog_bo);
}
.brw = BRW_NEW_VERTEX_PROGRAM | BRW_NEW_METAOPS,
.cache = 0
},
- .update = brw_upload_vs_prog
+ .prepare = brw_upload_vs_prog
};
/* Calculate sizes of vertex program outputs. Size is the largest
* component index which might vary from [0,0,0,1]
*/
-static void calc_wm_input_sizes( struct brw_context *brw )
+static int calc_wm_input_sizes( struct brw_context *brw )
{
/* BRW_NEW_VERTEX_PROGRAM */
struct brw_vertex_program *vp =
memcpy(brw->wm.input_size_masks, t.size_masks, sizeof(t.size_masks));
brw->state.dirty.brw |= BRW_NEW_WM_INPUT_DIMENSIONS;
}
+ return 0;
}
const struct brw_tracked_state brw_wm_input_sizes = {
.brw = BRW_NEW_VERTEX_PROGRAM | BRW_NEW_INPUT_DIMENSIONS,
.cache = 0
},
- .update = calc_wm_input_sizes
+ .prepare = calc_wm_input_sizes
};
* Later, clipping will detect ucp[6] and ensure the primitive is
* clipped against all fixed planes.
*/
- if (!c->key.know_w_is_one) {
+ if (!BRW_IS_IGD(p->brw) && !c->key.know_w_is_one) {
brw_CMP(p,
vec8(brw_null_reg()),
BRW_CONDITIONAL_L,
return bo;
}
-static void upload_vs_unit( struct brw_context *brw )
+static int prepare_vs_unit( struct brw_context *brw )
{
struct brw_vs_unit_key key;
if (brw->vs.state_bo == NULL) {
brw->vs.state_bo = vs_unit_create_from_key(brw, &key);
}
+ return dri_bufmgr_check_aperture_space(brw->vs.state_bo);
}
const struct brw_tracked_state brw_vs_unit = {
BRW_NEW_URB_FENCE),
.cache = CACHE_NEW_VS_PROG
},
- .update = upload_vs_unit,
+ .prepare = prepare_vs_unit,
};
return hash;
}
-static void update_tnl_program( struct brw_context *brw )
+static int prepare_tnl_program( struct brw_context *brw )
{
GLcontext *ctx = &brw->intel.ctx;
struct state_key key;
/* _NEW_PROGRAM */
if (brw->attribs.VertexProgram->_Current)
- return;
+ return 0;
/* Grab all the relevent state and put it in a single structure:
*/
if (old != brw->tnl_program)
brw->state.dirty.brw |= BRW_NEW_TNL_PROGRAM;
+ return 0;
}
/* Note: See brw_draw.c - the vertex program must not rely on
BRW_NEW_INPUT_VARYING),
.cache = 0
},
- .update = update_tnl_program
+ .prepare = prepare_tnl_program
};
-static void update_active_vertprog( struct brw_context *brw )
+static int prepare_active_vertprog( struct brw_context *brw )
{
const struct gl_vertex_program *prev = brw->vertex_program;
if (brw->vertex_program != prev)
brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM;
+
+ return 0;
}
.brw = BRW_NEW_TNL_PROGRAM,
.cache = 0
},
- .update = update_active_vertprog
+ .prepare = prepare_active_vertprog
};
}
-static void brw_upload_wm_prog( struct brw_context *brw )
+static int brw_prepare_wm_prog( struct brw_context *brw )
{
struct brw_wm_prog_key key;
struct brw_fragment_program *fp = (struct brw_fragment_program *)
&brw->wm.prog_data);
if (brw->wm.prog_bo == NULL)
do_wm_prog(brw, fp, &key);
+
+ return dri_bufmgr_check_aperture_space(brw->wm.prog_bo);
}
BRW_NEW_REDUCED_PRIMITIVE),
.cache = 0
},
- .update = brw_upload_wm_prog
+ .prepare = brw_prepare_wm_prog
};
responseLength,
msgLength,
0);
-
- if (shadow)
- brw_MOV(p, dst[3], brw_imm_f(1.0));
}
* complicates various things. However, this is still too confusing -
* FIXME: simplify all the different new texture state flags.
*/
-static void upload_wm_samplers( struct brw_context *brw )
+static int upload_wm_samplers( struct brw_context *brw )
{
struct wm_sampler_key key;
int i;
+ int ret = 0;
brw_wm_sampler_populate_key(brw, &key);
dri_bo_unreference(brw->wm.sampler_bo);
brw->wm.sampler_bo = NULL;
if (brw->wm.sampler_count == 0)
- return;
+ return 0;
brw->wm.sampler_bo = brw_search_cache(&brw->cache, BRW_SAMPLER,
&key, sizeof(key),
if (!brw->attribs.Texture->Unit[i]._ReallyEnabled)
continue;
+ ret |= dri_bufmgr_check_aperture_space(brw->wm.sdc_bo[i]);
dri_emit_reloc(brw->wm.sampler_bo,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
0,
brw->wm.sdc_bo[i]);
}
}
+
+ ret |= dri_bufmgr_check_aperture_space(brw->wm.sampler_bo);
+ return ret;
+
}
const struct brw_tracked_state brw_wm_samplers = {
.brw = 0,
.cache = 0
},
- .update = upload_wm_samplers,
+ .prepare = upload_wm_samplers,
};
}
-static void upload_wm_unit( struct brw_context *brw )
+static int upload_wm_unit( struct brw_context *brw )
{
struct intel_context *intel = &brw->intel;
struct brw_wm_unit_key key;
dri_bo *reloc_bufs[3];
-
+ int ret = 0, i;
wm_unit_populate_key(brw, &key);
/* Allocate the necessary scratch space if we haven't already. Don't
if (brw->wm.state_bo == NULL) {
brw->wm.state_bo = wm_unit_create_from_key(brw, &key, reloc_bufs);
}
+
+ for (i = 0; i < 3; i++)
+ if (reloc_bufs[i])
+ ret |= dri_bufmgr_check_aperture_space(reloc_bufs[i]);
+ ret |= dri_bufmgr_check_aperture_space(brw->wm.state_bo);
+ return ret;
}
const struct brw_tracked_state brw_wm_unit = {
CACHE_NEW_WM_PROG |
CACHE_NEW_SAMPLER)
},
- .update = upload_wm_unit,
+ .prepare = upload_wm_unit,
};
}
-static GLuint translate_tex_format( GLuint mesa_format )
+static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
{
switch( mesa_format ) {
case MESA_FORMAT_L8:
return BRW_SURFACEFORMAT_FXT1;
case MESA_FORMAT_Z16:
- return BRW_SURFACEFORMAT_I16_UNORM;
+ if (depth_mode == GL_INTENSITY)
+ return BRW_SURFACEFORMAT_I16_UNORM;
+ else if (depth_mode == GL_ALPHA)
+ return BRW_SURFACEFORMAT_A16_UNORM;
+ else
+ return BRW_SURFACEFORMAT_L16_UNORM;
case MESA_FORMAT_RGB_DXT1:
return BRW_SURFACEFORMAT_DXT1_RGB;
}
struct brw_wm_surface_key {
- GLenum target;
+ GLenum target, depthmode;
dri_bo *bo;
GLint format;
GLint first_level, last_level;
surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
surf.ss0.surface_type = translate_tex_target(key->target);
- surf.ss0.surface_format = translate_tex_format(key->format);
+ surf.ss0.surface_format = translate_tex_format(key->format, key->depthmode);
/* This is ok for all textures with channel width 8bit or less:
*/
return bo;
}
-static void
+static int
brw_update_texture_surface( GLcontext *ctx, GLuint unit )
{
struct brw_context *brw = brw_context(ctx);
struct intel_texture_object *intelObj = intel_texture_object(tObj);
struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel];
struct brw_wm_surface_key key;
+ int ret = 0;
memset(&key, 0, sizeof(key));
key.target = tObj->Target;
+ key.depthmode = tObj->DepthMode;
key.format = firstImage->TexFormat->MesaFormat;
key.bo = intelObj->mt->region->buffer;
key.first_level = intelObj->firstLevel;
key.depth = firstImage->Depth;
key.tiled = intelObj->mt->region->tiled;
+ ret |= dri_bufmgr_check_aperture_space(key.bo);
+
dri_bo_unreference(brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS]);
brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
&key, sizeof(key),
&key.bo, 1,
NULL);
- if (brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] == NULL)
+ if (brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] == NULL) {
brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] = brw_create_texture_surface(brw, &key);
+ }
+
+ ret |= dri_bufmgr_check_aperture_space(brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS]);
+ return ret;
}
/**
* While it is only used for the front/back buffer currently, it should be
* usable for further buffers when doing ARB_draw_buffer support.
*/
-static void
+static int
brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
unsigned int unit, GLboolean cached)
{
dri_bo *region_bo = NULL;
-
+ int ret = 0;
struct {
unsigned int surface_type;
unsigned int surface_format;
key.width = region->pitch; /* XXX: not really! */
key.height = region->height;
key.cpp = region->cpp;
+
+ ret |= dri_bufmgr_check_aperture_space(region->buffer);
} else {
key.surface_type = BRW_SURFACE_NULL;
key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
region_bo);
}
}
+
+ ret |= dri_bufmgr_check_aperture_space(brw->wm.surf_bo[unit]);
+
+ return ret;
}
return bind_bo;
}
-static void upload_wm_surfaces(struct brw_context *brw )
+static int prepare_wm_surfaces(struct brw_context *brw )
{
GLcontext *ctx = &brw->intel.ctx;
struct intel_context *intel = &brw->intel;
- GLuint i;
+ GLuint i, ret;
+
if (brw->state.nr_draw_regions > 1) {
- for (i = 0; i < brw->state.nr_draw_regions; i++)
- brw_update_region_surface(brw, brw->state.draw_regions[i], i,
- GL_FALSE);
- }else
- brw_update_region_surface(brw, brw->state.draw_regions[0], 0, GL_TRUE);
+ for (i = 0; i < brw->state.nr_draw_regions; i++) {
+ ret = brw_update_region_surface(brw, brw->state.draw_regions[i], i,
+ GL_FALSE);
+ if (ret)
+ return ret;
+ }
+ }else {
+ ret = brw_update_region_surface(brw, brw->state.draw_regions[0], 0, GL_TRUE);
+ if (ret)
+ return ret;
+ }
brw->wm.nr_surfaces = MAX_DRAW_BUFFERS;
struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i];
/* _NEW_TEXTURE, BRW_NEW_TEXDATA */
- if(texUnit->_ReallyEnabled &&
- texUnit->_Current == intel->frame_buffer_texobj)
- {
- dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
- brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = brw->wm.surf_bo[0];
- dri_bo_reference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
- brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
- } else if (texUnit->_ReallyEnabled) {
- brw_update_texture_surface(ctx, i);
- brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
+ if(texUnit->_ReallyEnabled) {
+ if (texUnit->_Current == intel->frame_buffer_texobj) {
+ dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
+ brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = brw->wm.surf_bo[0];
+ dri_bo_reference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
+ brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
+ } else {
+ ret = brw_update_texture_surface(ctx, i);
+ brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
+
+ if (ret)
+ return ret;
+ }
} else {
- dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
- brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = NULL;
+ dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
+ brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = NULL;
}
+
}
dri_bo_unreference(brw->wm.bind_bo);
brw->wm.bind_bo = brw_wm_get_binding_table(brw);
+
+ return dri_bufmgr_check_aperture_space(brw->wm.bind_bo);
}
+
const struct brw_tracked_state brw_wm_surfaces = {
.dirty = {
.mesa = _NEW_COLOR | _NEW_TEXTURE | _NEW_BUFFERS,
.brw = BRW_NEW_CONTEXT,
.cache = 0
},
- .update = upload_wm_surfaces,
+ .prepare = prepare_wm_surfaces,
};
GLuint CMD, BR13;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
+ int ret;
BATCH_LOCALS;
+ again:
+ ret = dri_bufmgr_check_aperture_space(dst_buffer);
+ ret |= dri_bufmgr_check_aperture_space(src_buffer);
+ if (ret) {
+ intel_batchbuffer_flush(intel->batch);
+ goto again;
+ }
DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
__FUNCTION__,
struct intel_validate_entry *entry =
&bufmgr_ttm->validate_array[target_buf_ttm->validate_index];
- entry->bo_arg.d.req.bo_req.flags &= ~DRM_BO_HINT_PRESUMED_OFFSET;
+ entry->bo_arg.d.req.bo_req.hint &= ~DRM_BO_HINT_PRESUMED_OFFSET;
}
}
}
/* Continue walking the tree depth-first. */
dri_ttm_bo_post_submit(r->target_buf);
- r->last_target_offset = bo->offset;
+ r->last_target_offset = r->target_buf->offset;
}
}
image->IsCompressed != mt->compressed)
return GL_FALSE;
+ if (!image->IsCompressed &&
+ !mt->compressed &&
+ image->TexFormat->TexelBytes != mt->cpp)
+ return GL_FALSE;
+
/* Test image dimensions against the base level image adjusted for
* minification. This will also catch images not present in the
* tree, changed targets, etc.
DRI_CONF_SECTION_END
DRI_CONF_SECTION_QUALITY
DRI_CONF_FORCE_S3TC_ENABLE(false)
- DRI_CONF_ALLOW_LARGE_TEXTURES(1)
+ DRI_CONF_ALLOW_LARGE_TEXTURES(2)
DRI_CONF_SECTION_END
DRI_CONF_SECTION_DEBUG
DRI_CONF_NO_RAST(false)
postConvWidth = 32 / texelBytes;
texImage->RowStride = postConvWidth;
}
-
- assert(texImage->RowStride == postConvWidth);
+
+ if (!intelImage->mt) {
+ assert(texImage->RowStride == postConvWidth);
+ }
}
/* Release the reference to a potentially orphaned buffer.
#define need_GL_ATI_fragment_shader
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_fog_coord
+#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
{ "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
{ "GL_EXT_blend_subtract", NULL },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+ { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_edge_clamp", NULL },
GLboolean ok;
GLuint dbg;
+ /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
+ rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
+ we use these to determine if we want to emit the corresponding state
+ atoms. */
+ R200_NEWPRIM( rmesa );
+
if (ctx->ATIFragmentShader._Enabled) {
GLuint i;
for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
case PROGRAM_LOCAL_PARAM:
case PROGRAM_ENV_PARAM:
case PROGRAM_NAMED_PARAM:
+ case PROGRAM_CONSTANT:
case PROGRAM_STATE_VAR:
return VSF_IN_CLASS_PARAM;
/*
#define need_GL_ARB_vertex_program
#define need_GL_EXT_blend_minmax
//#define need_GL_EXT_fog_coord
+#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
{"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
{"GL_EXT_blend_subtract", NULL},
// {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+ {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
{"GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions},
{"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
{"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions},
GLuint optimization;
};
+struct r500_fragment_program {
+ struct gl_fragment_program mesa_program;
+
+ GLcontext *ctx;
+ GLboolean translated;
+ GLboolean error;
+ struct r300_pfs_compile_state *cs;
+
+ struct {
+ GLuint inst0;
+ GLuint inst1;
+ GLuint inst2;
+ GLuint inst3;
+ GLuint inst4;
+ GLuint inst5;
+ } inst[512];
+ /* TODO: This is magic! */
+
+ struct {
+ int tex_offset;
+ int tex_end;
+ int alu_offset;
+ int alu_end;
+ int flags;
+ } node[4];
+ int cur_node;
+ int first_node_has_tex;
+
+ int alu_offset;
+ int alu_end;
+ int tex_offset;
+ int tex_end;
+
+ /* Hardware constants.
+ * Contains a pointer to the value. The destination of the pointer
+ * is supposed to be updated when GL state changes.
+ * Typically, this is either a pointer into
+ * gl_program_parameter_list::ParameterValues, or a pointer to a
+ * global constant (e.g. for sin/cos-approximation)
+ */
+ const GLfloat *constant[PFS_NUM_CONST_REGS];
+ int const_nr;
+
+ int max_temp_idx;
+
+ GLuint optimization;
+};
+
#define R300_MAX_AOS_ARRAYS 16
#define REG_COORDS 0
void r300TranslateFragmentShader(r300ContextPtr r300,
struct r300_fragment_program *fp)
{
+
struct r300_pfs_compile_state *cs = NULL;
if (!fp->translated) {
static int r300Fallback(GLcontext * ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- struct r300_fragment_program *fp = (struct r300_fragment_program *)
+ /* Do we need to use new-style shaders?
+ * Also is there a better way to do this? */
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ struct r500_fragment_program *fp = (struct r500_fragment_program *)
(char *)ctx->FragmentProgram._Current;
-
- if (fp) {
- if (!fp->translated)
- r300TranslateFragmentShader(r300, fp);
- FALLBACK_IF(!fp->translated);
+ if (fp) {
+ if (!fp->translated) {
+ r500TranslateFragmentShader(r300, fp);
+ FALLBACK_IF(!fp->translated);
+ }
+ }
+ } else {
+ struct r300_fragment_program *fp = (struct r300_fragment_program *)
+ (char *)ctx->FragmentProgram._Current;
+ if (fp) {
+ if (!fp->translated) {
+ r300TranslateFragmentShader(r300, fp);
+ FALLBACK_IF(!fp->translated);
+ }
+ }
}
FALLBACK_IF(ctx->RenderMode != GL_RENDER);
static void r500SetupPixelShader(r300ContextPtr rmesa)
{
GLcontext *ctx = rmesa->radeon.glCtx;
- struct r300_fragment_program *fp = (struct r300_fragment_program *)
+ struct r500_fragment_program *fp = (struct r500_fragment_program *)
(char *)ctx->FragmentProgram._Current;
int i, k;
- if (!fp) /* should only happenen once, just after context is created */
+ if (!fp) /* should only happen once, just after context is created */
+ return;
+
+ r500TranslateFragmentShader(rmesa, fp);
+ if (!fp->translated) {
+ fprintf(stderr, "%s: No valid fragment shader, exiting\n",
+ __FUNCTION__);
return;
+ }
- /* emit the standard zero shader */
R300_STATECHANGE(rmesa, r500fp);
- i = 1;
- rmesa->hw.r500fp.cmd[i++] = 0x7808;
- rmesa->hw.r500fp.cmd[i++] = R500_TEX_ID(0) | R500_TEX_INST_LD | R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED;
- rmesa->hw.r500fp.cmd[i++] = R500_TEX_SRC_ADDR(0) | R500_TEX_SRC_S_SWIZ_R |
- R500_TEX_SRC_T_SWIZ_G |
- R500_TEX_DST_ADDR(0) |
- R500_TEX_DST_R_SWIZ_R |
- R500_TEX_DST_G_SWIZ_G |
- R500_TEX_DST_B_SWIZ_B |
- R500_TEX_DST_A_SWIZ_A;
- rmesa->hw.r500fp.cmd[i++] = R500_DX_ADDR(0) |
- R500_DX_S_SWIZ_R |
- R500_DX_T_SWIZ_R |
- R500_DX_R_SWIZ_R |
- R500_DX_Q_SWIZ_R |
- R500_DY_ADDR(0) |
- R500_DY_S_SWIZ_R |
- R500_DY_T_SWIZ_R |
- R500_DY_R_SWIZ_R |
- R500_DY_Q_SWIZ_R;
- rmesa->hw.r500fp.cmd[i++] = 0x0;
- rmesa->hw.r500fp.cmd[i++] = 0x0;
-
- rmesa->hw.r500fp.cmd[i++] = R500_INST_TYPE_OUT |
- R500_INST_TEX_SEM_WAIT |
- R500_INST_LAST |
- R500_INST_RGB_OMASK_R |
- R500_INST_RGB_OMASK_G |
- R500_INST_RGB_OMASK_B |
- R500_INST_ALPHA_OMASK;
-
- rmesa->hw.r500fp.cmd[i++] = R500_RGB_ADDR0(0) |
- R500_RGB_ADDR1(0) |
- R500_RGB_ADDR1_CONST |
- R500_RGB_ADDR2(0) |
- R500_RGB_ADDR2_CONST |
- R500_RGB_SRCP_OP_1_MINUS_2RGB0;
- rmesa->hw.r500fp.cmd[i++] = R500_ALPHA_ADDR0(0) |
- R500_ALPHA_ADDR1(0) |
- R500_ALPHA_ADDR1_CONST |
- R500_ALPHA_ADDR2(0) |
- R500_ALPHA_ADDR2_CONST |
- R500_ALPHA_SRCP_OP_1_MINUS_2A0;
- rmesa->hw.r500fp.cmd[i++] = R500_ALU_RGB_SEL_A_SRC0 |
- R500_ALU_RGB_R_SWIZ_A_R |
- R500_ALU_RGB_G_SWIZ_A_G |
- R500_ALU_RGB_B_SWIZ_A_B |
- R500_ALU_RGB_SEL_B_SRC0 |
- R500_ALU_RGB_R_SWIZ_B_1 |
- R500_ALU_RGB_B_SWIZ_B_1 |
- R500_ALU_RGB_G_SWIZ_B_1;
- rmesa->hw.r500fp.cmd[i++] = R500_ALPHA_OP_MAD |
- R500_ALPHA_SWIZ_A_A |
- R500_ALPHA_SWIZ_B_1;
- rmesa->hw.r500fp.cmd[i++] = R500_ALU_RGBA_OP_MAD |
- R500_ALU_RGBA_R_SWIZ_0 |
- R500_ALU_RGBA_G_SWIZ_0 |
- R500_ALU_RGBA_B_SWIZ_0 |
- R500_ALU_RGBA_A_SWIZ_0;
-
- bump_r500fp_count(rmesa->hw.r500fp.cmd, 12);
+ /* Emit our shader... */
+ for (i = 0; i < fp->cs->nrslots; i++) {
+ rmesa->hw.r500fp.cmd[i*6+1] = fp->inst[i].inst0;
+ rmesa->hw.r500fp.cmd[i*6+2] = fp->inst[i].inst1;
+ rmesa->hw.r500fp.cmd[i*6+3] = fp->inst[i].inst2;
+ rmesa->hw.r500fp.cmd[i*6+4] = fp->inst[i].inst3;
+ rmesa->hw.r500fp.cmd[i*6+5] = fp->inst[i].inst4;
+ rmesa->hw.r500fp.cmd[i*6+6] = fp->inst[i].inst5;
+ }
+
+ bump_r500fp_count(rmesa->hw.r500fp.cmd, fp->cs->nrslots * 6);
R300_STATECHANGE(rmesa, r500fp_const);
for (i = 0; i < fp->const_nr; i++) {
*
* \author Jerome Glisse <j.glisse@gmail.com>
*
+ * \author Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
* \todo Depth write, WPOS/FOGC inputs
*
* \todo FogOption
#include "shader/prog_print.h"
#include "r300_context.h"
-#include "r300_fragprog.h"
+#include "r500_fragprog.h"
#include "r300_reg.h"
#include "r300_state.h"
/*
- * Usefull macros and values
+ * Useful macros and values
*/
#define ERROR(fmt, args...) do { \
fprintf(stderr, "%s::%s(): " fmt "\n", \
fp->error = GL_TRUE; \
} while(0)
-#define PFS_INVAL 0xFFFFFFFF
#define COMPILE_STATE struct r300_pfs_compile_state *cs = fp->cs
-#define SWIZZLE_XYZ 0
-#define SWIZZLE_XXX 1
-#define SWIZZLE_YYY 2
-#define SWIZZLE_ZZZ 3
-#define SWIZZLE_WWW 4
-#define SWIZZLE_YZX 5
-#define SWIZZLE_ZXY 6
-#define SWIZZLE_WZY 7
-#define SWIZZLE_111 8
-#define SWIZZLE_000 9
-#define SWIZZLE_HHH 10
-
-#define swizzle(r, x, y, z, w) do_swizzle(fp, r, \
- ((SWIZZLE_##x<<0)| \
- (SWIZZLE_##y<<3)| \
- (SWIZZLE_##z<<6)| \
- (SWIZZLE_##w<<9)), \
- 0)
-
-#define REG_TYPE_INPUT 0
-#define REG_TYPE_OUTPUT 1
-#define REG_TYPE_TEMP 2
-#define REG_TYPE_CONST 3
-
-#define REG_TYPE_SHIFT 0
-#define REG_INDEX_SHIFT 2
-#define REG_VSWZ_SHIFT 8
-#define REG_SSWZ_SHIFT 13
-#define REG_NEGV_SHIFT 18
-#define REG_NEGS_SHIFT 19
-#define REG_ABS_SHIFT 20
-#define REG_NO_USE_SHIFT 21 // Hack for refcounting
-#define REG_VALID_SHIFT 22 // Does the register contain a defined value?
-#define REG_BUILTIN_SHIFT 23 // Is it a builtin (like all zero/all one)?
-
-#define REG_TYPE_MASK (0x03 << REG_TYPE_SHIFT)
-#define REG_INDEX_MASK (0x3F << REG_INDEX_SHIFT)
-#define REG_VSWZ_MASK (0x1F << REG_VSWZ_SHIFT)
-#define REG_SSWZ_MASK (0x1F << REG_SSWZ_SHIFT)
-#define REG_NEGV_MASK (0x01 << REG_NEGV_SHIFT)
-#define REG_NEGS_MASK (0x01 << REG_NEGS_SHIFT)
-#define REG_ABS_MASK (0x01 << REG_ABS_SHIFT)
-#define REG_NO_USE_MASK (0x01 << REG_NO_USE_SHIFT)
-#define REG_VALID_MASK (0x01 << REG_VALID_SHIFT)
-#define REG_BUILTIN_MASK (0x01 << REG_BUILTIN_SHIFT)
-
-#define REG(type, index, vswz, sswz, nouse, valid, builtin) \
- (((type << REG_TYPE_SHIFT) & REG_TYPE_MASK) | \
- ((index << REG_INDEX_SHIFT) & REG_INDEX_MASK) | \
- ((nouse << REG_NO_USE_SHIFT) & REG_NO_USE_MASK) | \
- ((valid << REG_VALID_SHIFT) & REG_VALID_MASK) | \
- ((builtin << REG_BUILTIN_SHIFT) & REG_BUILTIN_MASK) | \
- ((vswz << REG_VSWZ_SHIFT) & REG_VSWZ_MASK) | \
- ((sswz << REG_SSWZ_SHIFT) & REG_SSWZ_MASK))
-#define REG_GET_TYPE(reg) \
- ((reg & REG_TYPE_MASK) >> REG_TYPE_SHIFT)
-#define REG_GET_INDEX(reg) \
- ((reg & REG_INDEX_MASK) >> REG_INDEX_SHIFT)
-#define REG_GET_VSWZ(reg) \
- ((reg & REG_VSWZ_MASK) >> REG_VSWZ_SHIFT)
-#define REG_GET_SSWZ(reg) \
- ((reg & REG_SSWZ_MASK) >> REG_SSWZ_SHIFT)
-#define REG_GET_NO_USE(reg) \
- ((reg & REG_NO_USE_MASK) >> REG_NO_USE_SHIFT)
-#define REG_GET_VALID(reg) \
- ((reg & REG_VALID_MASK) >> REG_VALID_SHIFT)
-#define REG_GET_BUILTIN(reg) \
- ((reg & REG_BUILTIN_MASK) >> REG_BUILTIN_SHIFT)
-#define REG_SET_TYPE(reg, type) \
- reg = ((reg & ~REG_TYPE_MASK) | \
- ((type << REG_TYPE_SHIFT) & REG_TYPE_MASK))
-#define REG_SET_INDEX(reg, index) \
- reg = ((reg & ~REG_INDEX_MASK) | \
- ((index << REG_INDEX_SHIFT) & REG_INDEX_MASK))
-#define REG_SET_VSWZ(reg, vswz) \
- reg = ((reg & ~REG_VSWZ_MASK) | \
- ((vswz << REG_VSWZ_SHIFT) & REG_VSWZ_MASK))
-#define REG_SET_SSWZ(reg, sswz) \
- reg = ((reg & ~REG_SSWZ_MASK) | \
- ((sswz << REG_SSWZ_SHIFT) & REG_SSWZ_MASK))
-#define REG_SET_NO_USE(reg, nouse) \
- reg = ((reg & ~REG_NO_USE_MASK) | \
- ((nouse << REG_NO_USE_SHIFT) & REG_NO_USE_MASK))
-#define REG_SET_VALID(reg, valid) \
- reg = ((reg & ~REG_VALID_MASK) | \
- ((valid << REG_VALID_SHIFT) & REG_VALID_MASK))
-#define REG_SET_BUILTIN(reg, builtin) \
- reg = ((reg & ~REG_BUILTIN_MASK) | \
- ((builtin << REG_BUILTIN_SHIFT) & REG_BUILTIN_MASK))
-#define REG_ABS(reg) \
- reg = (reg | REG_ABS_MASK)
-#define REG_NEGV(reg) \
- reg = (reg | REG_NEGV_MASK)
-#define REG_NEGS(reg) \
- reg = (reg | REG_NEGS_MASK)
-
-/*
- * Datas structures for fragment program generation
- */
-
-/* description of r300 native hw instructions */
-static const struct {
- const char *name;
- int argc;
- int v_op;
- int s_op;
-} r300_fpop[] = {
- /* *INDENT-OFF* */
- {"MAD", 3, R300_FPI0_OUTC_MAD, R300_FPI2_OUTA_MAD},
- {"DP3", 2, R300_FPI0_OUTC_DP3, R300_FPI2_OUTA_DP4},
- {"DP4", 2, R300_FPI0_OUTC_DP4, R300_FPI2_OUTA_DP4},
- {"MIN", 2, R300_FPI0_OUTC_MIN, R300_FPI2_OUTA_MIN},
- {"MAX", 2, R300_FPI0_OUTC_MAX, R300_FPI2_OUTA_MAX},
- {"CMP", 3, R300_FPI0_OUTC_CMP, R300_FPI2_OUTA_CMP},
- {"FRC", 1, R300_FPI0_OUTC_FRC, R300_FPI2_OUTA_FRC},
- {"EX2", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_EX2},
- {"LG2", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_LG2},
- {"RCP", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_RCP},
- {"RSQ", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_RSQ},
- {"REPL_ALPHA", 1, R300_FPI0_OUTC_REPL_ALPHA, PFS_INVAL},
- {"CMPH", 3, R300_FPI0_OUTC_CMPH, PFS_INVAL},
- /* *INDENT-ON* */
-};
-
-/* vector swizzles r300 can support natively, with a couple of
- * cases we handle specially
- *
- * REG_VSWZ/REG_SSWZ is an index into this table
- */
-
-/* mapping from SWIZZLE_* to r300 native values for scalar insns */
-#define SWIZZLE_HALF 6
-
-#define MAKE_SWZ3(x, y, z) (MAKE_SWIZZLE4(SWIZZLE_##x, \
- SWIZZLE_##y, \
- SWIZZLE_##z, \
- SWIZZLE_ZERO))
-/* native swizzles */
-static const struct r300_pfs_swizzle {
- GLuint hash; /* swizzle value this matches */
- GLuint base; /* base value for hw swizzle */
- GLuint stride; /* difference in base between arg0/1/2 */
- GLuint flags;
-} v_swiz[] = {
- /* *INDENT-OFF* */
- {MAKE_SWZ3(X, Y, Z), R300_FPI0_ARGC_SRC0C_XYZ, 4, SLOT_SRC_VECTOR},
- {MAKE_SWZ3(X, X, X), R300_FPI0_ARGC_SRC0C_XXX, 4, SLOT_SRC_VECTOR},
- {MAKE_SWZ3(Y, Y, Y), R300_FPI0_ARGC_SRC0C_YYY, 4, SLOT_SRC_VECTOR},
- {MAKE_SWZ3(Z, Z, Z), R300_FPI0_ARGC_SRC0C_ZZZ, 4, SLOT_SRC_VECTOR},
- {MAKE_SWZ3(W, W, W), R300_FPI0_ARGC_SRC0A, 1, SLOT_SRC_SCALAR},
- {MAKE_SWZ3(Y, Z, X), R300_FPI0_ARGC_SRC0C_YZX, 1, SLOT_SRC_VECTOR},
- {MAKE_SWZ3(Z, X, Y), R300_FPI0_ARGC_SRC0C_ZXY, 1, SLOT_SRC_VECTOR},
- {MAKE_SWZ3(W, Z, Y), R300_FPI0_ARGC_SRC0CA_WZY, 1, SLOT_SRC_BOTH},
- {MAKE_SWZ3(ONE, ONE, ONE), R300_FPI0_ARGC_ONE, 0, 0},
- {MAKE_SWZ3(ZERO, ZERO, ZERO), R300_FPI0_ARGC_ZERO, 0, 0},
- {MAKE_SWZ3(HALF, HALF, HALF), R300_FPI0_ARGC_HALF, 0, 0},
- {PFS_INVAL, 0, 0, 0},
- /* *INDENT-ON* */
-};
-
-/* used during matching of non-native swizzles */
-#define SWZ_X_MASK (7 << 0)
-#define SWZ_Y_MASK (7 << 3)
-#define SWZ_Z_MASK (7 << 6)
-#define SWZ_W_MASK (7 << 9)
-static const struct {
- GLuint hash; /* used to mask matching swizzle components */
- int mask; /* actual outmask */
- int count; /* count of components matched */
-} s_mask[] = {
- /* *INDENT-OFF* */
- {SWZ_X_MASK | SWZ_Y_MASK | SWZ_Z_MASK, 1 | 2 | 4, 3},
- {SWZ_X_MASK | SWZ_Y_MASK, 1 | 2, 2},
- {SWZ_X_MASK | SWZ_Z_MASK, 1 | 4, 2},
- {SWZ_Y_MASK | SWZ_Z_MASK, 2 | 4, 2},
- {SWZ_X_MASK, 1, 1},
- {SWZ_Y_MASK, 2, 1},
- {SWZ_Z_MASK, 4, 1},
- {PFS_INVAL, PFS_INVAL, PFS_INVAL}
- /* *INDENT-ON* */
-};
-
-static const struct {
- int base; /* hw value of swizzle */
- int stride; /* difference between SRC0/1/2 */
- GLuint flags;
-} s_swiz[] = {
- /* *INDENT-OFF* */
- {R300_FPI2_ARGA_SRC0C_X, 3, SLOT_SRC_VECTOR},
- {R300_FPI2_ARGA_SRC0C_Y, 3, SLOT_SRC_VECTOR},
- {R300_FPI2_ARGA_SRC0C_Z, 3, SLOT_SRC_VECTOR},
- {R300_FPI2_ARGA_SRC0A, 1, SLOT_SRC_SCALAR},
- {R300_FPI2_ARGA_ZERO, 0, 0},
- {R300_FPI2_ARGA_ONE, 0, 0},
- {R300_FPI2_ARGA_HALF, 0, 0}
- /* *INDENT-ON* */
-};
-
-/* boiler-plate reg, for convenience */
-static const GLuint undef = REG(REG_TYPE_TEMP,
- 0,
- SWIZZLE_XYZ,
- SWIZZLE_W,
- GL_FALSE,
- GL_FALSE,
- GL_FALSE);
-
-/* constant one source */
-static const GLuint pfs_one = REG(REG_TYPE_CONST,
- 0,
- SWIZZLE_111,
- SWIZZLE_ONE,
- GL_FALSE,
- GL_TRUE,
- GL_TRUE);
-
-/* constant half source */
-static const GLuint pfs_half = REG(REG_TYPE_CONST,
- 0,
- SWIZZLE_HHH,
- SWIZZLE_HALF,
- GL_FALSE,
- GL_TRUE,
- GL_TRUE);
-
-/* constant zero source */
-static const GLuint pfs_zero = REG(REG_TYPE_CONST,
- 0,
- SWIZZLE_000,
- SWIZZLE_ZERO,
- GL_FALSE,
- GL_TRUE,
- GL_TRUE);
-
-/*
- * Common functions prototypes
- */
-static void dump_program(struct r300_fragment_program *fp);
-static void emit_arith(struct r300_fragment_program *fp, int op,
- GLuint dest, int mask,
- GLuint src0, GLuint src1, GLuint src2, int flags);
-
-/**
- * Get an R300 temporary that can be written to in the given slot.
- */
-static int get_hw_temp(struct r300_fragment_program *fp, int slot)
-{
- COMPILE_STATE;
- int r;
-
- for (r = 0; r < PFS_NUM_TEMP_REGS; ++r) {
- if (cs->hwtemps[r].free >= 0 && cs->hwtemps[r].free <= slot)
- break;
- }
-
- if (r >= PFS_NUM_TEMP_REGS) {
- ERROR("Out of hardware temps\n");
- return 0;
- }
- // Reserved is used to avoid the following scenario:
- // R300 temporary X is first assigned to Mesa temporary Y during vector ops
- // R300 temporary X is then assigned to Mesa temporary Z for further vector ops
- // Then scalar ops on Mesa temporary Z are emitted and move back in time
- // to overwrite the value of temporary Y.
- // End scenario.
- cs->hwtemps[r].reserved = cs->hwtemps[r].free;
- cs->hwtemps[r].free = -1;
-
- // Reset to some value that won't mess things up when the user
- // tries to read from a temporary that hasn't been assigned a value yet.
- // In the normal case, vector_valid and scalar_valid should be set to
- // a sane value by the first emit that writes to this temporary.
- cs->hwtemps[r].vector_valid = 0;
- cs->hwtemps[r].scalar_valid = 0;
-
- if (r > fp->max_temp_idx)
- fp->max_temp_idx = r;
-
- return r;
-}
-
-/**
- * Get an R300 temporary that will act as a TEX destination register.
- */
-static int get_hw_temp_tex(struct r300_fragment_program *fp)
-{
- COMPILE_STATE;
- int r;
-
- for (r = 0; r < PFS_NUM_TEMP_REGS; ++r) {
- if (cs->used_in_node & (1 << r))
- continue;
-
- // Note: Be very careful here
- if (cs->hwtemps[r].free >= 0 && cs->hwtemps[r].free <= 0)
- break;
- }
-
- if (r >= PFS_NUM_TEMP_REGS)
- return get_hw_temp(fp, 0); /* Will cause an indirection */
-
- cs->hwtemps[r].reserved = cs->hwtemps[r].free;
- cs->hwtemps[r].free = -1;
-
- // Reset to some value that won't mess things up when the user
- // tries to read from a temporary that hasn't been assigned a value yet.
- // In the normal case, vector_valid and scalar_valid should be set to
- // a sane value by the first emit that writes to this temporary.
- cs->hwtemps[r].vector_valid = cs->nrslots;
- cs->hwtemps[r].scalar_valid = cs->nrslots;
-
- if (r > fp->max_temp_idx)
- fp->max_temp_idx = r;
-
- return r;
-}
-
-/**
- * Mark the given hardware register as free.
- */
-static void free_hw_temp(struct r300_fragment_program *fp, int idx)
-{
- COMPILE_STATE;
-
- // Be very careful here. Consider sequences like
- // MAD r0, r1,r2,r3
- // TEX r4, ...
- // The TEX instruction may be moved in front of the MAD instruction
- // due to the way nodes work. We don't want to alias r1 and r4 in
- // this case.
- // I'm certain the register allocation could be further sanitized,
- // but it's tricky because of stuff that can happen inside emit_tex
- // and emit_arith.
- cs->hwtemps[idx].free = cs->nrslots + 1;
-}
-
-/**
- * Create a new Mesa temporary register.
- */
-static GLuint get_temp_reg(struct r300_fragment_program *fp)
-{
- COMPILE_STATE;
- GLuint r = undef;
- GLuint index;
-
- index = ffs(~cs->temp_in_use);
- if (!index) {
- ERROR("Out of program temps\n");
- return r;
- }
-
- cs->temp_in_use |= (1 << --index);
- cs->temps[index].refcount = 0xFFFFFFFF;
- cs->temps[index].reg = -1;
-
- REG_SET_TYPE(r, REG_TYPE_TEMP);
- REG_SET_INDEX(r, index);
- REG_SET_VALID(r, GL_TRUE);
- return r;
+/* "Register" flags */
+#define REG_CONSTANT (1 << 8)
+
+/* Swizzle tools */
+#define R500_SWIZZLE_ZERO 4
+#define R500_SWIZZLE_HALF 5
+#define R500_SWIZZLE_ONE 6
+#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6))
+#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6))
+/* Swizzles for inst2 */
+#define MAKE_SWIZ_TEX_STRQ(x) (x << 8)
+#define MAKE_SWIZ_TEX_RGBA(x) (x << 24)
+/* Swizzles for inst3 */
+#define MAKE_SWIZ_RGB_A(x) (x << 2)
+#define MAKE_SWIZ_RGB_B(x) (x << 15)
+/* Swizzles for inst4 */
+#define MAKE_SWIZ_ALPHA_A(x) (x << 14)
+#define MAKE_SWIZ_ALPHA_B(x) (x << 21)
+/* Swizzle for inst5 */
+#define MAKE_SWIZ_RGBA_C(x) (x << 14)
+#define MAKE_SWIZ_ALPHA_C(x) (x << 27)
+
+static inline GLuint make_rgb_swizzle(struct prog_src_register src) {
+ GLuint swiz = 0x0;
+ GLuint temp;
+ /* This could be optimized, but it should be plenty fast already. */
+ for (int i = 0; i < 3; i++) {
+ temp = (src.Swizzle >> i*3) & 0x7;
+ /* Fix SWIZZLE_ONE */
+ if (temp == 5) temp++;
+ swiz += temp << i*3;
+ }
+ return swiz;
}
-/**
- * Create a new Mesa temporary register that will act as the destination
- * register for a texture read.
- */
-static GLuint get_temp_reg_tex(struct r300_fragment_program *fp)
-{
- COMPILE_STATE;
- GLuint r = undef;
- GLuint index;
-
- index = ffs(~cs->temp_in_use);
- if (!index) {
- ERROR("Out of program temps\n");
- return r;
- }
-
- cs->temp_in_use |= (1 << --index);
- cs->temps[index].refcount = 0xFFFFFFFF;
- cs->temps[index].reg = get_hw_temp_tex(fp);
-
- REG_SET_TYPE(r, REG_TYPE_TEMP);
- REG_SET_INDEX(r, index);
- REG_SET_VALID(r, GL_TRUE);
- return r;
+static inline GLuint make_alpha_swizzle(struct prog_src_register src) {
+ GLuint swiz = (src.Swizzle >> 12) & 0x7;
+ if (swiz == 5) swiz++;
+ return swiz;
}
-/**
- * Free a Mesa temporary and the associated R300 temporary.
- */
-static void free_temp(struct r300_fragment_program *fp, GLuint r)
-{
- COMPILE_STATE;
- GLuint index = REG_GET_INDEX(r);
-
- if (!(cs->temp_in_use & (1 << index)))
- return;
-
- if (REG_GET_TYPE(r) == REG_TYPE_TEMP) {
- free_hw_temp(fp, cs->temps[index].reg);
- cs->temps[index].reg = -1;
- cs->temp_in_use &= ~(1 << index);
- } else if (REG_GET_TYPE(r) == REG_TYPE_INPUT) {
- free_hw_temp(fp, cs->inputs[index].reg);
- cs->inputs[index].reg = -1;
+static inline GLuint make_strq_swizzle(struct prog_src_register src) {
+ GLuint swiz = 0x0;
+ GLuint temp = src.Swizzle;
+ for (int i = 0; i < 4; i++) {
+ swiz += (temp & 0x3) << i*2;
+ temp >>= 3;
}
+ return swiz;
}
-/**
- * Emit a hardware constant/parameter.
- *
- * \p cp Stable pointer to an array of 4 floats.
- * The pointer must be stable in the sense that it remains to be valid
- * and hold the contents of the constant/parameter throughout the lifetime
- * of the fragment program (actually, up until the next time the fragment
- * program is translated).
- */
-static GLuint emit_const4fv(struct r300_fragment_program *fp,
+/* Borrowed verbatim from r300_fragprog since it hasn't changed. */
+static GLuint emit_const4fv(struct r500_fragment_program *fp,
const GLfloat * cp)
{
- GLuint reg = undef;
+ GLuint reg = 0x0;
int index;
for (index = 0; index < fp->const_nr; ++index) {
}
if (index >= fp->const_nr) {
+ /* TODO: This should be r5xx nums, not r300 */
if (index >= PFS_NUM_CONST_REGS) {
ERROR("Out of hw constants!\n");
return reg;
fp->constant[index] = cp;
}
- REG_SET_TYPE(reg, REG_TYPE_CONST);
- REG_SET_INDEX(reg, index);
- REG_SET_VALID(reg, GL_TRUE);
+ reg = index | REG_CONSTANT;
return reg;
}
-static inline GLuint negate(GLuint r)
-{
- REG_NEGS(r);
- REG_NEGV(r);
- return r;
-}
-
-/* Hack, to prevent clobbering sources used multiple times when
- * emulating non-native instructions
- */
-static inline GLuint keep(GLuint r)
-{
- REG_SET_NO_USE(r, GL_TRUE);
- return r;
-}
-
-static inline GLuint absolute(GLuint r)
-{
- REG_ABS(r);
- return r;
-}
-
-static int swz_native(struct r300_fragment_program *fp,
- GLuint src, GLuint * r, GLuint arbneg)
-{
- /* Native swizzle, handle negation */
- src = (src & ~REG_NEGS_MASK) | (((arbneg >> 3) & 1) << REG_NEGS_SHIFT);
-
- if ((arbneg & 0x7) == 0x0) {
- src = src & ~REG_NEGV_MASK;
- *r = src;
- } else if ((arbneg & 0x7) == 0x7) {
- src |= REG_NEGV_MASK;
- *r = src;
- } else {
- if (!REG_GET_VALID(*r))
- *r = get_temp_reg(fp);
- src |= REG_NEGV_MASK;
- emit_arith(fp,
- PFS_OP_MAD,
- *r, arbneg & 0x7, keep(src), pfs_one, pfs_zero, 0);
- src = src & ~REG_NEGV_MASK;
- emit_arith(fp,
- PFS_OP_MAD,
- *r,
- (arbneg ^ 0x7) | WRITEMASK_W,
- src, pfs_one, pfs_zero, 0);
- }
-
- return 3;
-}
-
-static int swz_emit_partial(struct r300_fragment_program *fp,
- GLuint src,
- GLuint * r, int mask, int mc, GLuint arbneg)
-{
- GLuint tmp;
- GLuint wmask = 0;
-
- if (!REG_GET_VALID(*r))
- *r = get_temp_reg(fp);
-
- /* A partial match, VSWZ/mask define what parts of the
- * desired swizzle we match
- */
- if (mc + s_mask[mask].count == 3) {
- wmask = WRITEMASK_W;
- src |= ((arbneg >> 3) & 1) << REG_NEGS_SHIFT;
- }
-
- tmp = arbneg & s_mask[mask].mask;
- if (tmp) {
- tmp = tmp ^ s_mask[mask].mask;
- if (tmp) {
- emit_arith(fp,
- PFS_OP_MAD,
- *r,
- arbneg & s_mask[mask].mask,
- keep(src) | REG_NEGV_MASK,
- pfs_one, pfs_zero, 0);
- if (!wmask) {
- REG_SET_NO_USE(src, GL_TRUE);
- } else {
- REG_SET_NO_USE(src, GL_FALSE);
- }
- emit_arith(fp,
- PFS_OP_MAD,
- *r, tmp | wmask, src, pfs_one, pfs_zero, 0);
- } else {
- if (!wmask) {
- REG_SET_NO_USE(src, GL_TRUE);
- } else {
- REG_SET_NO_USE(src, GL_FALSE);
- }
- emit_arith(fp,
- PFS_OP_MAD,
- *r,
- (arbneg & s_mask[mask].mask) | wmask,
- src | REG_NEGV_MASK, pfs_one, pfs_zero, 0);
- }
- } else {
- if (!wmask) {
- REG_SET_NO_USE(src, GL_TRUE);
- } else {
- REG_SET_NO_USE(src, GL_FALSE);
- }
- emit_arith(fp, PFS_OP_MAD,
- *r,
- s_mask[mask].mask | wmask,
- src, pfs_one, pfs_zero, 0);
- }
-
- return s_mask[mask].count;
-}
-
-static GLuint do_swizzle(struct r300_fragment_program *fp,
- GLuint src, GLuint arbswz, GLuint arbneg)
-{
- GLuint r = undef;
- GLuint vswz;
- int c_mask = 0;
- int v_match = 0;
-
- /* If swizzling from something without an XYZW native swizzle,
- * emit result to a temp, and do new swizzle from the temp.
- */
-#if 0
- if (REG_GET_VSWZ(src) != SWIZZLE_XYZ || REG_GET_SSWZ(src) != SWIZZLE_W) {
- GLuint temp = get_temp_reg(fp);
- emit_arith(fp,
- PFS_OP_MAD,
- temp, WRITEMASK_XYZW, src, pfs_one, pfs_zero, 0);
- src = temp;
- }
-#endif
-
- if (REG_GET_VSWZ(src) != SWIZZLE_XYZ || REG_GET_SSWZ(src) != SWIZZLE_W) {
- GLuint vsrcswz =
- (v_swiz[REG_GET_VSWZ(src)].
- hash & (SWZ_X_MASK | SWZ_Y_MASK | SWZ_Z_MASK)) |
- REG_GET_SSWZ(src) << 9;
- GLint i;
-
- GLuint newswz = 0;
- GLuint offset;
- for (i = 0; i < 4; ++i) {
- offset = GET_SWZ(arbswz, i);
-
- newswz |=
- (offset <= 3) ? GET_SWZ(vsrcswz,
- offset) << i *
- 3 : offset << i * 3;
- }
-
- arbswz = newswz & (SWZ_X_MASK | SWZ_Y_MASK | SWZ_Z_MASK);
- REG_SET_SSWZ(src, GET_SWZ(newswz, 3));
- } else {
- /* set scalar swizzling */
- REG_SET_SSWZ(src, GET_SWZ(arbswz, 3));
-
- }
- do {
- vswz = REG_GET_VSWZ(src);
- do {
- int chash;
-
- REG_SET_VSWZ(src, vswz);
- chash = v_swiz[REG_GET_VSWZ(src)].hash &
- s_mask[c_mask].hash;
-
- if (chash == (arbswz & s_mask[c_mask].hash)) {
- if (s_mask[c_mask].count == 3) {
- v_match += swz_native(fp,
- src, &r, arbneg);
- } else {
- v_match += swz_emit_partial(fp,
- src,
- &r,
- c_mask,
- v_match,
- arbneg);
- }
-
- if (v_match == 3)
- return r;
-
- /* Fill with something invalid.. all 0's was
- * wrong before, matched SWIZZLE_X. So all
- * 1's will be okay for now
- */
- arbswz |= (PFS_INVAL & s_mask[c_mask].hash);
- }
- } while (v_swiz[++vswz].hash != PFS_INVAL);
- REG_SET_VSWZ(src, SWIZZLE_XYZ);
- } while (s_mask[++c_mask].hash != PFS_INVAL);
-
- ERROR("should NEVER get here\n");
- return r;
-}
-
-static GLuint t_src(struct r300_fragment_program *fp,
- struct prog_src_register fpsrc)
-{
- GLuint r = undef;
-
- switch (fpsrc.File) {
- case PROGRAM_TEMPORARY:
- REG_SET_INDEX(r, fpsrc.Index);
- REG_SET_VALID(r, GL_TRUE);
- REG_SET_TYPE(r, REG_TYPE_TEMP);
- break;
- case PROGRAM_INPUT:
- REG_SET_INDEX(r, fpsrc.Index);
- REG_SET_VALID(r, GL_TRUE);
- REG_SET_TYPE(r, REG_TYPE_INPUT);
- break;
- case PROGRAM_LOCAL_PARAM:
- r = emit_const4fv(fp,
- fp->mesa_program.Base.LocalParams[fpsrc.
- Index]);
- break;
- case PROGRAM_ENV_PARAM:
- r = emit_const4fv(fp,
- fp->ctx->FragmentProgram.Parameters[fpsrc.
- Index]);
- break;
- case PROGRAM_STATE_VAR:
- case PROGRAM_NAMED_PARAM:
- r = emit_const4fv(fp,
- fp->mesa_program.Base.Parameters->
- ParameterValues[fpsrc.Index]);
- break;
- default:
- ERROR("unknown SrcReg->File %x\n", fpsrc.File);
- return r;
- }
-
- /* no point swizzling ONE/ZERO/HALF constants... */
- if (REG_GET_VSWZ(r) < SWIZZLE_111 || REG_GET_SSWZ(r) < SWIZZLE_ZERO)
- r = do_swizzle(fp, r, fpsrc.Swizzle, fpsrc.NegateBase);
- return r;
-}
-
-static GLuint t_scalar_src(struct r300_fragment_program *fp,
- struct prog_src_register fpsrc)
-{
- struct prog_src_register src = fpsrc;
- int sc = GET_SWZ(fpsrc.Swizzle, 0); /* X */
-
- src.Swizzle = ((sc << 0) | (sc << 3) | (sc << 6) | (sc << 9));
-
- return t_src(fp, src);
-}
-
-static GLuint t_dst(struct r300_fragment_program *fp,
- struct prog_dst_register dest)
-{
- GLuint r = undef;
-
- switch (dest.File) {
- case PROGRAM_TEMPORARY:
- REG_SET_INDEX(r, dest.Index);
- REG_SET_VALID(r, GL_TRUE);
- REG_SET_TYPE(r, REG_TYPE_TEMP);
- return r;
- case PROGRAM_OUTPUT:
- REG_SET_TYPE(r, REG_TYPE_OUTPUT);
- switch (dest.Index) {
- case FRAG_RESULT_COLR:
- case FRAG_RESULT_DEPR:
- REG_SET_INDEX(r, dest.Index);
- REG_SET_VALID(r, GL_TRUE);
- return r;
+static GLuint make_src(struct r500_fragment_program *fp, struct prog_src_register src) {
+ GLuint reg;
+ switch (src.File) {
+ case PROGRAM_TEMPORARY:
+ reg = (src.Index << 0x1) | 0x1;
+ break;
+ case PROGRAM_INPUT:
+ /* Ugly hack needed to work around Mesa;
+ * fragments don't get loaded right otherwise! */
+ reg = 0x0;
+ break;
+ case PROGRAM_CONSTANT:
+ reg = emit_const4fv(fp, fp->mesa_program.Base.Parameters->
+ ParameterValues[src.Index]);
+ break;
default:
- ERROR("Bad DstReg->Index 0x%x\n", dest.Index);
- return r;
- }
- default:
- ERROR("Bad DstReg->File 0x%x\n", dest.File);
- return r;
- }
-}
-
-static int t_hw_src(struct r300_fragment_program *fp, GLuint src, GLboolean tex)
-{
- COMPILE_STATE;
- int idx;
- int index = REG_GET_INDEX(src);
-
- switch (REG_GET_TYPE(src)) {
- case REG_TYPE_TEMP:
- /* NOTE: if reg==-1 here, a source is being read that
- * hasn't been written to. Undefined results.
- */
- if (cs->temps[index].reg == -1)
- cs->temps[index].reg = get_hw_temp(fp, cs->nrslots);
-
- idx = cs->temps[index].reg;
-
- if (!REG_GET_NO_USE(src) && (--cs->temps[index].refcount == 0))
- free_temp(fp, src);
- break;
- case REG_TYPE_INPUT:
- idx = cs->inputs[index].reg;
-
- if (!REG_GET_NO_USE(src) && (--cs->inputs[index].refcount == 0))
- free_hw_temp(fp, cs->inputs[index].reg);
- break;
- case REG_TYPE_CONST:
- return (index | SRC_CONST);
- default:
- ERROR("Invalid type for source reg\n");
- return (0 | SRC_CONST);
+ ERROR("Can't handle src.File %x\n", src.File);
+ reg = 0x0;
+ break;
}
-
- if (!tex)
- cs->used_in_node |= (1 << idx);
-
- return idx;
+ return reg;
}
-static int t_hw_dst(struct r300_fragment_program *fp,
- GLuint dest, GLboolean tex, int slot)
-{
- COMPILE_STATE;
- int idx;
- GLuint index = REG_GET_INDEX(dest);
- assert(REG_GET_VALID(dest));
-
- switch (REG_GET_TYPE(dest)) {
- case REG_TYPE_TEMP:
- if (cs->temps[REG_GET_INDEX(dest)].reg == -1) {
- if (!tex) {
- cs->temps[index].reg = get_hw_temp(fp, slot);
- } else {
- cs->temps[index].reg = get_hw_temp_tex(fp);
- }
- }
- idx = cs->temps[index].reg;
-
- if (!REG_GET_NO_USE(dest) && (--cs->temps[index].refcount == 0))
- free_temp(fp, dest);
-
- cs->dest_in_node |= (1 << idx);
- cs->used_in_node |= (1 << idx);
- break;
- case REG_TYPE_OUTPUT:
- switch (index) {
- case FRAG_RESULT_COLR:
- fp->node[fp->cur_node].flags |=
- R300_PFS_NODE_OUTPUT_COLOR;
+static GLuint make_dest(struct r500_fragment_program *fp, struct prog_dst_register dest) {
+ GLuint reg;
+ switch (dest.File) {
+ case PROGRAM_TEMPORARY:
+ reg = (dest.Index << 0x1) | 0x1;
break;
- case FRAG_RESULT_DEPR:
- fp->node[fp->cur_node].flags |=
- R300_PFS_NODE_OUTPUT_DEPTH;
+ case PROGRAM_OUTPUT:
+ /* Eventually we may need to handle multiple
+ * rendering targets... */
+ reg = dest.Index;
break;
- }
- return index;
- break;
- default:
- ERROR("invalid dest reg type %d\n", REG_GET_TYPE(dest));
- return 0;
- }
-
- return idx;
-}
-
-static void emit_nop(struct r300_fragment_program *fp)
-{
- COMPILE_STATE;
-
- if (cs->nrslots >= PFS_MAX_ALU_INST) {
- ERROR("Out of ALU instruction slots\n");
- return;
- }
-
- fp->alu.inst[cs->nrslots].inst0 = NOP_INST0;
- fp->alu.inst[cs->nrslots].inst1 = NOP_INST1;
- fp->alu.inst[cs->nrslots].inst2 = NOP_INST2;
- fp->alu.inst[cs->nrslots].inst3 = NOP_INST3;
- cs->nrslots++;
-}
-
-static void emit_tex(struct r300_fragment_program *fp,
- struct prog_instruction *fpi, int opcode)
-{
- COMPILE_STATE;
- GLuint coord = t_src(fp, fpi->SrcReg[0]);
- GLuint dest = undef, rdest = undef;
- GLuint din, uin;
- int unit = fpi->TexSrcUnit;
- int hwsrc, hwdest;
- GLuint tempreg = 0;
-
- uin = cs->used_in_node;
- din = cs->dest_in_node;
-
- /* Resolve source/dest to hardware registers */
- if (opcode != R300_FPITX_OP_KIL) {
- if (fpi->TexSrcTarget == TEXTURE_RECT_INDEX) {
- /**
- * Hardware uses [0..1]x[0..1] range for rectangle textures
- * instead of [0..Width]x[0..Height].
- * Add a scaling instruction.
- *
- * \todo Refactor this once we have proper rewriting/optimization
- * support for programs.
- */
- gl_state_index tokens[STATE_LENGTH] = {
- STATE_INTERNAL, STATE_R300_TEXRECT_FACTOR, 0, 0,
- 0
- };
- int factor_index;
- GLuint factorreg;
-
- tokens[2] = unit;
- factor_index =
- _mesa_add_state_reference(fp->mesa_program.Base.
- Parameters, tokens);
- factorreg =
- emit_const4fv(fp,
- fp->mesa_program.Base.Parameters->
- ParameterValues[factor_index]);
- tempreg = keep(get_temp_reg(fp));
-
- emit_arith(fp, PFS_OP_MAD, tempreg, WRITEMASK_XYZW,
- coord, factorreg, pfs_zero, 0);
-
- /* Ensure correct node indirection */
- uin = cs->used_in_node;
- din = cs->dest_in_node;
-
- hwsrc = t_hw_src(fp, tempreg, GL_TRUE);
- } else {
- hwsrc = t_hw_src(fp, coord, GL_TRUE);
- }
-
- dest = t_dst(fp, fpi->DstReg);
-
- /* r300 doesn't seem to be able to do TEX->output reg */
- if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT) {
- rdest = dest;
- dest = get_temp_reg_tex(fp);
- } else if (fpi->DstReg.WriteMask != WRITEMASK_XYZW) {
- /* in case write mask isn't XYZW */
- rdest = dest;
- dest = get_temp_reg_tex(fp);
- }
- hwdest =
- t_hw_dst(fp, dest, GL_TRUE,
- fp->node[fp->cur_node].alu_offset);
-
- /* Use a temp that hasn't been used in this node, rather
- * than causing an indirection
- */
- if (uin & (1 << hwdest)) {
- free_hw_temp(fp, hwdest);
- hwdest = get_hw_temp_tex(fp);
- cs->temps[REG_GET_INDEX(dest)].reg = hwdest;
- }
- } else {
- hwdest = 0;
- unit = 0;
- hwsrc = t_hw_src(fp, coord, GL_TRUE);
- }
-
- /* Indirection if source has been written in this node, or if the
- * dest has been read/written in this node
- */
- if ((REG_GET_TYPE(coord) != REG_TYPE_CONST &&
- (din & (1 << hwsrc))) || (uin & (1 << hwdest))) {
-
- /* Finish off current node */
- if (fp->node[fp->cur_node].alu_offset == cs->nrslots)
- emit_nop(fp);
-
- fp->node[fp->cur_node].alu_end =
- cs->nrslots - fp->node[fp->cur_node].alu_offset - 1;
- assert(fp->node[fp->cur_node].alu_end >= 0);
-
- if (++fp->cur_node >= PFS_MAX_TEX_INDIRECT) {
- ERROR("too many levels of texture indirection\n");
- return;
- }
-
- /* Start new node */
- fp->node[fp->cur_node].tex_offset = fp->tex.length;
- fp->node[fp->cur_node].alu_offset = cs->nrslots;
- fp->node[fp->cur_node].tex_end = -1;
- fp->node[fp->cur_node].alu_end = -1;
- fp->node[fp->cur_node].flags = 0;
- cs->used_in_node = 0;
- cs->dest_in_node = 0;
- }
-
- if (fp->cur_node == 0)
- fp->first_node_has_tex = 1;
-
- fp->tex.inst[fp->tex.length++] = 0 | (hwsrc << R300_FPITX_SRC_SHIFT)
- | (hwdest << R300_FPITX_DST_SHIFT)
- | (unit << R300_FPITX_IMAGE_SHIFT)
- /* not entirely sure about this */
- | (opcode << R300_FPITX_OPCODE_SHIFT);
-
- cs->dest_in_node |= (1 << hwdest);
- if (REG_GET_TYPE(coord) != REG_TYPE_CONST)
- cs->used_in_node |= (1 << hwsrc);
-
- fp->node[fp->cur_node].tex_end++;
-
- /* Copy from temp to output if needed */
- if (REG_GET_VALID(rdest)) {
- emit_arith(fp, PFS_OP_MAD, rdest, fpi->DstReg.WriteMask, dest,
- pfs_one, pfs_zero, 0);
- free_temp(fp, dest);
- }
-
- /* Free temp register */
- if (tempreg != 0)
- free_temp(fp, tempreg);
-}
-
-/**
- * Returns the first slot where we could possibly allow writing to dest,
- * according to register allocation.
- */
-static int get_earliest_allowed_write(struct r300_fragment_program *fp,
- GLuint dest, int mask)
-{
- COMPILE_STATE;
- int idx;
- int pos;
- GLuint index = REG_GET_INDEX(dest);
- assert(REG_GET_VALID(dest));
-
- switch (REG_GET_TYPE(dest)) {
- case REG_TYPE_TEMP:
- if (cs->temps[index].reg == -1)
- return 0;
-
- idx = cs->temps[index].reg;
- break;
- case REG_TYPE_OUTPUT:
- return 0;
- default:
- ERROR("invalid dest reg type %d\n", REG_GET_TYPE(dest));
- return 0;
- }
-
- pos = cs->hwtemps[idx].reserved;
- if (mask & WRITEMASK_XYZ) {
- if (pos < cs->hwtemps[idx].vector_lastread)
- pos = cs->hwtemps[idx].vector_lastread;
- }
- if (mask & WRITEMASK_W) {
- if (pos < cs->hwtemps[idx].scalar_lastread)
- pos = cs->hwtemps[idx].scalar_lastread;
- }
-
- return pos;
-}
-
-/**
- * Allocates a slot for an ALU instruction that can consist of
- * a vertex part or a scalar part or both.
- *
- * Sources from src (src[0] to src[argc-1]) are added to the slot in the
- * appropriate position (vector and/or scalar), and their positions are
- * recorded in the srcpos array.
- *
- * This function emits instruction code for the source fetch and the
- * argument selection. It does not emit instruction code for the
- * opcode or the destination selection.
- *
- * @return the index of the slot
- */
-static int find_and_prepare_slot(struct r300_fragment_program *fp,
- GLboolean emit_vop,
- GLboolean emit_sop,
- int argc, GLuint * src, GLuint dest, int mask)
-{
- COMPILE_STATE;
- int hwsrc[3];
- int srcpos[3];
- unsigned int used;
- int tempused;
- int tempvsrc[3];
- int tempssrc[3];
- int pos;
- int regnr;
- int i, j;
-
- // Determine instruction slots, whether sources are required on
- // vector or scalar side, and the smallest slot number where
- // all source registers are available
- used = 0;
- if (emit_vop)
- used |= SLOT_OP_VECTOR;
- if (emit_sop)
- used |= SLOT_OP_SCALAR;
-
- pos = get_earliest_allowed_write(fp, dest, mask);
-
- if (fp->node[fp->cur_node].alu_offset > pos)
- pos = fp->node[fp->cur_node].alu_offset;
- for (i = 0; i < argc; ++i) {
- if (!REG_GET_BUILTIN(src[i])) {
- if (emit_vop)
- used |= v_swiz[REG_GET_VSWZ(src[i])].flags << i;
- if (emit_sop)
- used |= s_swiz[REG_GET_SSWZ(src[i])].flags << i;
- }
-
- hwsrc[i] = t_hw_src(fp, src[i], GL_FALSE); /* Note: sideeffects wrt refcounting! */
- regnr = hwsrc[i] & 31;
-
- if (REG_GET_TYPE(src[i]) == REG_TYPE_TEMP) {
- if (used & (SLOT_SRC_VECTOR << i)) {
- if (cs->hwtemps[regnr].vector_valid > pos)
- pos = cs->hwtemps[regnr].vector_valid;
- }
- if (used & (SLOT_SRC_SCALAR << i)) {
- if (cs->hwtemps[regnr].scalar_valid > pos)
- pos = cs->hwtemps[regnr].scalar_valid;
- }
- }
- }
-
- // Find a slot that fits
- for (;; ++pos) {
- if (cs->slot[pos].used & used & SLOT_OP_BOTH)
- continue;
-
- if (pos >= cs->nrslots) {
- if (cs->nrslots >= PFS_MAX_ALU_INST) {
- ERROR("Out of ALU instruction slots\n");
- return -1;
- }
-
- fp->alu.inst[pos].inst0 = NOP_INST0;
- fp->alu.inst[pos].inst1 = NOP_INST1;
- fp->alu.inst[pos].inst2 = NOP_INST2;
- fp->alu.inst[pos].inst3 = NOP_INST3;
-
- cs->nrslots++;
- }
- // Note: When we need both parts (vector and scalar) of a source,
- // we always try to put them into the same position. This makes the
- // code easier to read, and it is optimal (i.e. one doesn't gain
- // anything by splitting the parts).
- // It also avoids headaches with swizzles that access both parts (i.e WXY)
- tempused = cs->slot[pos].used;
- for (i = 0; i < 3; ++i) {
- tempvsrc[i] = cs->slot[pos].vsrc[i];
- tempssrc[i] = cs->slot[pos].ssrc[i];
- }
-
- for (i = 0; i < argc; ++i) {
- int flags = (used >> i) & SLOT_SRC_BOTH;
-
- if (!flags) {
- srcpos[i] = 0;
- continue;
- }
-
- for (j = 0; j < 3; ++j) {
- if ((tempused >> j) & flags & SLOT_SRC_VECTOR) {
- if (tempvsrc[j] != hwsrc[i])
- continue;
- }
-
- if ((tempused >> j) & flags & SLOT_SRC_SCALAR) {
- if (tempssrc[j] != hwsrc[i])
- continue;
- }
-
- break;
- }
-
- if (j == 3)
- break;
-
- srcpos[i] = j;
- tempused |= flags << j;
- if (flags & SLOT_SRC_VECTOR)
- tempvsrc[j] = hwsrc[i];
- if (flags & SLOT_SRC_SCALAR)
- tempssrc[j] = hwsrc[i];
- }
-
- if (i == argc)
+ default:
+ ERROR("Can't handle dest.File %x\n", dest.File);
+ reg = 0x0;
break;
}
-
- // Found a slot, reserve it
- cs->slot[pos].used = tempused | (used & SLOT_OP_BOTH);
- for (i = 0; i < 3; ++i) {
- cs->slot[pos].vsrc[i] = tempvsrc[i];
- cs->slot[pos].ssrc[i] = tempssrc[i];
- }
-
- for (i = 0; i < argc; ++i) {
- if (REG_GET_TYPE(src[i]) == REG_TYPE_TEMP) {
- int regnr = hwsrc[i] & 31;
-
- if (used & (SLOT_SRC_VECTOR << i)) {
- if (cs->hwtemps[regnr].vector_lastread < pos)
- cs->hwtemps[regnr].vector_lastread =
- pos;
- }
- if (used & (SLOT_SRC_SCALAR << i)) {
- if (cs->hwtemps[regnr].scalar_lastread < pos)
- cs->hwtemps[regnr].scalar_lastread =
- pos;
- }
- }
- }
-
- // Emit the source fetch code
- fp->alu.inst[pos].inst1 &= ~R300_FPI1_SRC_MASK;
- fp->alu.inst[pos].inst1 |=
- ((cs->slot[pos].vsrc[0] << R300_FPI1_SRC0C_SHIFT) |
- (cs->slot[pos].vsrc[1] << R300_FPI1_SRC1C_SHIFT) |
- (cs->slot[pos].vsrc[2] << R300_FPI1_SRC2C_SHIFT));
-
- fp->alu.inst[pos].inst3 &= ~R300_FPI3_SRC_MASK;
- fp->alu.inst[pos].inst3 |=
- ((cs->slot[pos].ssrc[0] << R300_FPI3_SRC0A_SHIFT) |
- (cs->slot[pos].ssrc[1] << R300_FPI3_SRC1A_SHIFT) |
- (cs->slot[pos].ssrc[2] << R300_FPI3_SRC2A_SHIFT));
-
- // Emit the argument selection code
- if (emit_vop) {
- int swz[3];
-
- for (i = 0; i < 3; ++i) {
- if (i < argc) {
- swz[i] = (v_swiz[REG_GET_VSWZ(src[i])].base +
- (srcpos[i] *
- v_swiz[REG_GET_VSWZ(src[i])].
- stride)) | ((src[i] & REG_NEGV_MASK)
- ? ARG_NEG : 0) | ((src[i]
- &
- REG_ABS_MASK)
- ?
- ARG_ABS
- : 0);
- } else {
- swz[i] = R300_FPI0_ARGC_ZERO;
- }
- }
-
- fp->alu.inst[pos].inst0 &=
- ~(R300_FPI0_ARG0C_MASK | R300_FPI0_ARG1C_MASK |
- R300_FPI0_ARG2C_MASK);
- fp->alu.inst[pos].inst0 |=
- (swz[0] << R300_FPI0_ARG0C_SHIFT) | (swz[1] <<
- R300_FPI0_ARG1C_SHIFT)
- | (swz[2] << R300_FPI0_ARG2C_SHIFT);
- }
-
- if (emit_sop) {
- int swz[3];
-
- for (i = 0; i < 3; ++i) {
- if (i < argc) {
- swz[i] = (s_swiz[REG_GET_SSWZ(src[i])].base +
- (srcpos[i] *
- s_swiz[REG_GET_SSWZ(src[i])].
- stride)) | ((src[i] & REG_NEGV_MASK)
- ? ARG_NEG : 0) | ((src[i]
- &
- REG_ABS_MASK)
- ?
- ARG_ABS
- : 0);
- } else {
- swz[i] = R300_FPI2_ARGA_ZERO;
- }
- }
-
- fp->alu.inst[pos].inst2 &=
- ~(R300_FPI2_ARG0A_MASK | R300_FPI2_ARG1A_MASK |
- R300_FPI2_ARG2A_MASK);
- fp->alu.inst[pos].inst2 |=
- (swz[0] << R300_FPI2_ARG0A_SHIFT) | (swz[1] <<
- R300_FPI2_ARG1A_SHIFT)
- | (swz[2] << R300_FPI2_ARG2A_SHIFT);
- }
-
- return pos;
-}
-
-/**
- * Append an ALU instruction to the instruction list.
- */
-static void emit_arith(struct r300_fragment_program *fp,
- int op,
- GLuint dest,
- int mask,
- GLuint src0, GLuint src1, GLuint src2, int flags)
-{
- COMPILE_STATE;
- GLuint src[3] = { src0, src1, src2 };
- int hwdest;
- GLboolean emit_vop, emit_sop;
- int vop, sop, argc;
- int pos;
-
- vop = r300_fpop[op].v_op;
- sop = r300_fpop[op].s_op;
- argc = r300_fpop[op].argc;
-
- if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT &&
- REG_GET_INDEX(dest) == FRAG_RESULT_DEPR) {
- if (mask & WRITEMASK_Z) {
- mask = WRITEMASK_W;
- } else {
- return;
- }
- }
-
- emit_vop = GL_FALSE;
- emit_sop = GL_FALSE;
- if ((mask & WRITEMASK_XYZ) || vop == R300_FPI0_OUTC_DP3)
- emit_vop = GL_TRUE;
- if ((mask & WRITEMASK_W) || vop == R300_FPI0_OUTC_REPL_ALPHA)
- emit_sop = GL_TRUE;
-
- pos =
- find_and_prepare_slot(fp, emit_vop, emit_sop, argc, src, dest,
- mask);
- if (pos < 0)
- return;
-
- hwdest = t_hw_dst(fp, dest, GL_FALSE, pos); /* Note: Side effects wrt register allocation */
-
- if (flags & PFS_FLAG_SAT) {
- vop |= R300_FPI0_OUTC_SAT;
- sop |= R300_FPI2_OUTA_SAT;
- }
-
- /* Throw the pieces together and get FPI0/1 */
- if (emit_vop) {
- fp->alu.inst[pos].inst0 |= vop;
-
- fp->alu.inst[pos].inst1 |= hwdest << R300_FPI1_DSTC_SHIFT;
-
- if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT) {
- if (REG_GET_INDEX(dest) == FRAG_RESULT_COLR) {
- fp->alu.inst[pos].inst1 |=
- (mask & WRITEMASK_XYZ) <<
- R300_FPI1_DSTC_OUTPUT_MASK_SHIFT;
- } else
- assert(0);
- } else {
- fp->alu.inst[pos].inst1 |=
- (mask & WRITEMASK_XYZ) <<
- R300_FPI1_DSTC_REG_MASK_SHIFT;
-
- cs->hwtemps[hwdest].vector_valid = pos + 1;
- }
- }
-
- /* And now FPI2/3 */
- if (emit_sop) {
- fp->alu.inst[pos].inst2 |= sop;
-
- if (mask & WRITEMASK_W) {
- if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT) {
- if (REG_GET_INDEX(dest) == FRAG_RESULT_COLR) {
- fp->alu.inst[pos].inst3 |=
- (hwdest << R300_FPI3_DSTA_SHIFT) |
- R300_FPI3_DSTA_OUTPUT;
- } else if (REG_GET_INDEX(dest) ==
- FRAG_RESULT_DEPR) {
- fp->alu.inst[pos].inst3 |=
- R300_FPI3_DSTA_DEPTH;
- } else
- assert(0);
- } else {
- fp->alu.inst[pos].inst3 |=
- (hwdest << R300_FPI3_DSTA_SHIFT) |
- R300_FPI3_DSTA_REG;
-
- cs->hwtemps[hwdest].scalar_valid = pos + 1;
- }
- }
- }
-
- return;
+ return reg;
}
-#if 0
-static GLuint get_attrib(struct r300_fragment_program *fp, GLuint attr)
+static void dumb_shader(struct r500_fragment_program *fp)
{
- struct gl_fragment_program *mp = &fp->mesa_program;
- GLuint r = undef;
-
- if (!(mp->Base.InputsRead & (1 << attr))) {
- ERROR("Attribute %d was not provided!\n", attr);
- return undef;
- }
-
- REG_SET_TYPE(r, REG_TYPE_INPUT);
- REG_SET_INDEX(r, attr);
- REG_SET_VALID(r, GL_TRUE);
- return r;
+ /* R500_INST_TYPE_TEX? */
+ fp->inst[0].inst0 = 0x7808;
+ fp->inst[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD | R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED;
+ fp->inst[0].inst2 = R500_TEX_SRC_ADDR(0) | R500_TEX_SRC_S_SWIZ_R |
+ R500_TEX_SRC_T_SWIZ_G |
+ R500_TEX_DST_ADDR(0) |
+ R500_TEX_DST_R_SWIZ_R |
+ R500_TEX_DST_G_SWIZ_G |
+ R500_TEX_DST_B_SWIZ_B |
+ R500_TEX_DST_A_SWIZ_A;
+ fp->inst[0].inst3 = R500_DX_ADDR(0) |
+ R500_DX_S_SWIZ_R |
+ R500_DX_T_SWIZ_R |
+ R500_DX_R_SWIZ_R |
+ R500_DX_Q_SWIZ_R |
+ R500_DY_ADDR(0) |
+ R500_DY_S_SWIZ_R |
+ R500_DY_T_SWIZ_R |
+ R500_DY_R_SWIZ_R |
+ R500_DY_Q_SWIZ_R;
+ fp->inst[0].inst4 = 0x0;
+ fp->inst[0].inst5 = 0x0;
+
+ fp->inst[1].inst0 = R500_INST_TYPE_OUT |
+ R500_INST_TEX_SEM_WAIT |
+ R500_INST_LAST |
+ R500_INST_RGB_OMASK_R |
+ R500_INST_RGB_OMASK_G |
+ R500_INST_RGB_OMASK_B |
+ R500_INST_ALPHA_OMASK;
+ fp->inst[1].inst1 = R500_RGB_ADDR0(0) |
+ R500_RGB_ADDR1(0) |
+ R500_RGB_ADDR1_CONST |
+ R500_RGB_ADDR2(0) |
+ R500_RGB_ADDR2_CONST |
+ R500_RGB_SRCP_OP_1_MINUS_2RGB0;
+ fp->inst[1].inst2 = R500_ALPHA_ADDR0(0) |
+ R500_ALPHA_ADDR1(0) |
+ R500_ALPHA_ADDR1_CONST |
+ R500_ALPHA_ADDR2(0) |
+ R500_ALPHA_ADDR2_CONST |
+ R500_ALPHA_SRCP_OP_1_MINUS_2A0;
+ fp->inst[1].inst3 = R500_ALU_RGB_SEL_A_SRC0 |
+ R500_ALU_RGB_R_SWIZ_A_R |
+ R500_ALU_RGB_G_SWIZ_A_G |
+ R500_ALU_RGB_B_SWIZ_A_B |
+ R500_ALU_RGB_SEL_B_SRC0 |
+ R500_ALU_RGB_R_SWIZ_B_1 |
+ R500_ALU_RGB_B_SWIZ_B_1 |
+ R500_ALU_RGB_G_SWIZ_B_1;
+ fp->inst[1].inst4 = R500_ALPHA_OP_MAD |
+ R500_ALPHA_SWIZ_A_A |
+ R500_ALPHA_SWIZ_B_1;
+ fp->inst[1].inst5 = R500_ALU_RGBA_OP_MAD |
+ R500_ALU_RGBA_R_SWIZ_0 |
+ R500_ALU_RGBA_G_SWIZ_0 |
+ R500_ALU_RGBA_B_SWIZ_0 |
+ R500_ALU_RGBA_A_SWIZ_0;
+
+ fp->cs->nrslots = 2;
+ fp->translated = GL_TRUE;
}
-#endif
-
-static GLfloat SinCosConsts[2][4] = {
- {
- 1.273239545, // 4/PI
- -0.405284735, // -4/(PI*PI)
- 3.141592654, // PI
- 0.2225 // weight
- },
- {
- 0.75,
- 0.0,
- 0.159154943, // 1/(2*PI)
- 6.283185307 // 2*PI
- }
-};
-
-/**
- * Emit a LIT instruction.
- * \p flags may be PFS_FLAG_SAT
- *
- * Definition of LIT (from ARB_fragment_program):
- * tmp = VectorLoad(op0);
- * if (tmp.x < 0) tmp.x = 0;
- * if (tmp.y < 0) tmp.y = 0;
- * if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
- * else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
- * result.x = 1.0;
- * result.y = tmp.x;
- * result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
- * result.w = 1.0;
- *
- * The longest path of computation is the one leading to result.z,
- * consisting of 5 operations. This implementation of LIT takes
- * 5 slots. So unless there's some special undocumented opcode,
- * this implementation is potentially optimal. Unfortunately,
- * emit_arith is a bit too conservative because it doesn't understand
- * partial writes to the vector component.
- */
-static const GLfloat LitConst[4] =
- { 127.999999, 127.999999, 127.999999, -127.999999 };
-
-static void emit_lit(struct r300_fragment_program *fp,
- GLuint dest, int mask, GLuint src, int flags)
-{
- COMPILE_STATE;
- GLuint cnst;
- int needTemporary;
- GLuint temp;
-
- cnst = emit_const4fv(fp, LitConst);
-
- needTemporary = 0;
- if ((mask & WRITEMASK_XYZW) != WRITEMASK_XYZW) {
- needTemporary = 1;
- } else if (REG_GET_TYPE(dest) == REG_TYPE_OUTPUT) {
- // LIT is typically followed by DP3/DP4, so there's no point
- // in creating special code for this case
- needTemporary = 1;
- }
-
- if (needTemporary) {
- temp = keep(get_temp_reg(fp));
- } else {
- temp = keep(dest);
- }
-
- // Note: The order of emit_arith inside the slots is relevant,
- // because emit_arith only looks at scalar vs. vector when resolving
- // dependencies, and it does not consider individual vector components,
- // so swizzling between the two parts can create fake dependencies.
- // First slot
- emit_arith(fp, PFS_OP_MAX, temp, WRITEMASK_XY,
- keep(src), pfs_zero, undef, 0);
- emit_arith(fp, PFS_OP_MAX, temp, WRITEMASK_W, src, cnst, undef, 0);
-
- // Second slot
- emit_arith(fp, PFS_OP_MIN, temp, WRITEMASK_Z,
- swizzle(temp, W, W, W, W), cnst, undef, 0);
- emit_arith(fp, PFS_OP_LG2, temp, WRITEMASK_W,
- swizzle(temp, Y, Y, Y, Y), undef, undef, 0);
-
- // Third slot
- // If desired, we saturate the y result here.
- // This does not affect the use as a condition variable in the CMP later
- emit_arith(fp, PFS_OP_MAD, temp, WRITEMASK_W,
- temp, swizzle(temp, Z, Z, Z, Z), pfs_zero, 0);
- emit_arith(fp, PFS_OP_MAD, temp, WRITEMASK_Y,
- swizzle(temp, X, X, X, X), pfs_one, pfs_zero, flags);
-
- // Fourth slot
- emit_arith(fp, PFS_OP_MAD, temp, WRITEMASK_X,
- pfs_one, pfs_one, pfs_zero, 0);
- emit_arith(fp, PFS_OP_EX2, temp, WRITEMASK_W, temp, undef, undef, 0);
-
- // Fifth slot
- emit_arith(fp, PFS_OP_CMP, temp, WRITEMASK_Z,
- pfs_zero, swizzle(temp, W, W, W, W),
- negate(swizzle(temp, Y, Y, Y, Y)), flags);
- emit_arith(fp, PFS_OP_MAD, temp, WRITEMASK_W, pfs_one, pfs_one,
- pfs_zero, 0);
-
- if (needTemporary) {
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- temp, pfs_one, pfs_zero, flags);
- free_temp(fp, temp);
- } else {
- // Decrease refcount of the destination
- t_hw_dst(fp, dest, GL_FALSE, cs->nrslots);
- }
+static void emit_alu(struct r500_fragment_program *fp) {
}
-static GLboolean parse_program(struct r300_fragment_program *fp)
+static GLboolean parse_program(struct r500_fragment_program *fp)
{
struct gl_fragment_program *mp = &fp->mesa_program;
const struct prog_instruction *inst = mp->Base.Instructions;
struct prog_instruction *fpi;
GLuint src[3], dest, temp[2];
- int flags, mask = 0;
- int const_sin[2];
+ int flags, mask, counter = 0;
if (!inst || inst[0].Opcode == OPCODE_END) {
- ERROR("empty program?\n");
+ ERROR("The program is empty!\n");
return GL_FALSE;
}
for (fpi = mp->Base.Instructions; fpi->Opcode != OPCODE_END; fpi++) {
- if (fpi->SaturateMode == SATURATE_ZERO_ONE)
- flags = PFS_FLAG_SAT;
- else
- flags = 0;
if (fpi->Opcode != OPCODE_KIL) {
- dest = t_dst(fp, fpi->DstReg);
- mask = fpi->DstReg.WriteMask;
+ dest = make_dest(fp, fpi->DstReg);
+ mask = fpi->DstReg.WriteMask << 11;
}
switch (fpi->Opcode) {
- case OPCODE_ABS:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- absolute(src[0]), pfs_one, pfs_zero, flags);
- break;
- case OPCODE_ADD:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- src[0], pfs_one, src[1], flags);
- break;
- case OPCODE_CMP:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- src[2] = t_src(fp, fpi->SrcReg[2]);
- /* ARB_f_p - if src0.c < 0.0 ? src1.c : src2.c
- * r300 - if src2.c < 0.0 ? src1.c : src0.c
- */
- emit_arith(fp, PFS_OP_CMP, dest, mask,
- src[2], src[1], src[0], flags);
- break;
- case OPCODE_COS:
- /*
- * cos using a parabola (see SIN):
- * cos(x):
- * x = (x/(2*PI))+0.75
- * x = frac(x)
- * x = (x*2*PI)-PI
- * result = sin(x)
- */
- temp[0] = get_temp_reg(fp);
- const_sin[0] = emit_const4fv(fp, SinCosConsts[0]);
- const_sin[1] = emit_const4fv(fp, SinCosConsts[1]);
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
-
- /* add 0.5*PI and do range reduction */
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_X,
- swizzle(src[0], X, X, X, X),
- swizzle(const_sin[1], Z, Z, Z, Z),
- swizzle(const_sin[1], X, X, X, X), 0);
-
- emit_arith(fp, PFS_OP_FRC, temp[0], WRITEMASK_X,
- swizzle(temp[0], X, X, X, X),
- undef, undef, 0);
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_Z, swizzle(temp[0], X, X, X, X), swizzle(const_sin[1], W, W, W, W), //2*PI
- negate(swizzle(const_sin[0], Z, Z, Z, Z)), //-PI
- 0);
-
- /* SIN */
-
- emit_arith(fp, PFS_OP_MAD, temp[0],
- WRITEMASK_X | WRITEMASK_Y, swizzle(temp[0],
- Z, Z, Z,
- Z),
- const_sin[0], pfs_zero, 0);
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_X,
- swizzle(temp[0], Y, Y, Y, Y),
- absolute(swizzle(temp[0], Z, Z, Z, Z)),
- swizzle(temp[0], X, X, X, X), 0);
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_Y,
- swizzle(temp[0], X, X, X, X),
- absolute(swizzle(temp[0], X, X, X, X)),
- negate(swizzle(temp[0], X, X, X, X)), 0);
-
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- swizzle(temp[0], Y, Y, Y, Y),
- swizzle(const_sin[0], W, W, W, W),
- swizzle(temp[0], X, X, X, X), flags);
-
- free_temp(fp, temp[0]);
- break;
- case OPCODE_DP3:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- emit_arith(fp, PFS_OP_DP3, dest, mask,
- src[0], src[1], undef, flags);
- break;
- case OPCODE_DP4:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- emit_arith(fp, PFS_OP_DP4, dest, mask,
- src[0], src[1], undef, flags);
- break;
- case OPCODE_DPH:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- /* src0.xyz1 -> temp
- * DP4 dest, temp, src1
- */
-#if 0
- temp[0] = get_temp_reg(fp);
- src[0].s_swz = SWIZZLE_ONE;
- emit_arith(fp, PFS_OP_MAD, temp[0], mask,
- src[0], pfs_one, pfs_zero, 0);
- emit_arith(fp, PFS_OP_DP4, dest, mask,
- temp[0], src[1], undef, flags);
- free_temp(fp, temp[0]);
-#else
- emit_arith(fp, PFS_OP_DP4, dest, mask,
- swizzle(src[0], X, Y, Z, ONE), src[1],
- undef, flags);
-#endif
- break;
- case OPCODE_DST:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- /* dest.y = src0.y * src1.y */
- if (mask & WRITEMASK_Y)
- emit_arith(fp, PFS_OP_MAD, dest, WRITEMASK_Y,
- keep(src[0]), keep(src[1]),
- pfs_zero, flags);
- /* dest.z = src0.z */
- if (mask & WRITEMASK_Z)
- emit_arith(fp, PFS_OP_MAD, dest, WRITEMASK_Z,
- src[0], pfs_one, pfs_zero, flags);
- /* result.x = 1.0
- * result.w = src1.w */
- if (mask & WRITEMASK_XW) {
- REG_SET_VSWZ(src[1], SWIZZLE_111); /*Cheat */
- emit_arith(fp, PFS_OP_MAD, dest,
- mask & WRITEMASK_XW,
- src[1], pfs_one, pfs_zero, flags);
- }
- break;
- case OPCODE_EX2:
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
- emit_arith(fp, PFS_OP_EX2, dest, mask,
- src[0], undef, undef, flags);
- break;
- case OPCODE_FLR:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- temp[0] = get_temp_reg(fp);
- /* FRC temp, src0
- * MAD dest, src0, 1.0, -temp
- */
- emit_arith(fp, PFS_OP_FRC, temp[0], mask,
- keep(src[0]), undef, undef, 0);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- src[0], pfs_one, negate(temp[0]), flags);
- free_temp(fp, temp[0]);
- break;
- case OPCODE_FRC:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- emit_arith(fp, PFS_OP_FRC, dest, mask,
- src[0], undef, undef, flags);
- break;
- case OPCODE_KIL:
- emit_tex(fp, fpi, R300_FPITX_OP_KIL);
- break;
- case OPCODE_LG2:
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
- emit_arith(fp, PFS_OP_LG2, dest, mask,
- src[0], undef, undef, flags);
- break;
- case OPCODE_LIT:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- emit_lit(fp, dest, mask, src[0], flags);
- break;
- case OPCODE_LRP:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- src[2] = t_src(fp, fpi->SrcReg[2]);
- /* result = tmp0tmp1 + (1 - tmp0)tmp2
- * = tmp0tmp1 + tmp2 + (-tmp0)tmp2
- * MAD temp, -tmp0, tmp2, tmp2
- * MAD result, tmp0, tmp1, temp
- */
- temp[0] = get_temp_reg(fp);
- emit_arith(fp, PFS_OP_MAD, temp[0], mask,
- negate(keep(src[0])), keep(src[2]), src[2],
- 0);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- src[0], src[1], temp[0], flags);
- free_temp(fp, temp[0]);
- break;
- case OPCODE_MAD:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- src[2] = t_src(fp, fpi->SrcReg[2]);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- src[0], src[1], src[2], flags);
- break;
- case OPCODE_MAX:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- emit_arith(fp, PFS_OP_MAX, dest, mask,
- src[0], src[1], undef, flags);
- break;
- case OPCODE_MIN:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- emit_arith(fp, PFS_OP_MIN, dest, mask,
- src[0], src[1], undef, flags);
- break;
- case OPCODE_MOV:
- case OPCODE_SWZ:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- src[0], pfs_one, pfs_zero, flags);
- break;
- case OPCODE_MUL:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- src[0], src[1], pfs_zero, flags);
- break;
- case OPCODE_POW:
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
- src[1] = t_scalar_src(fp, fpi->SrcReg[1]);
- temp[0] = get_temp_reg(fp);
- emit_arith(fp, PFS_OP_LG2, temp[0], WRITEMASK_W,
- src[0], undef, undef, 0);
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_W,
- temp[0], src[1], pfs_zero, 0);
- emit_arith(fp, PFS_OP_EX2, dest, fpi->DstReg.WriteMask,
- temp[0], undef, undef, 0);
- free_temp(fp, temp[0]);
- break;
- case OPCODE_RCP:
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
- emit_arith(fp, PFS_OP_RCP, dest, mask,
- src[0], undef, undef, flags);
- break;
- case OPCODE_RSQ:
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
- emit_arith(fp, PFS_OP_RSQ, dest, mask,
- absolute(src[0]), pfs_zero, pfs_zero, flags);
- break;
- case OPCODE_SCS:
- /*
- * scs using a parabola :
- * scs(x):
- * result.x = sin(-abs(x)+0.5*PI) (cos)
- * result.y = sin(x) (sin)
- *
- */
- temp[0] = get_temp_reg(fp);
- temp[1] = get_temp_reg(fp);
- const_sin[0] = emit_const4fv(fp, SinCosConsts[0]);
- const_sin[1] = emit_const4fv(fp, SinCosConsts[1]);
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
-
- /* x = -abs(x)+0.5*PI */
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_Z, swizzle(const_sin[0], Z, Z, Z, Z), //PI
- pfs_half,
- negate(abs
- (swizzle(keep(src[0]), X, X, X, X))),
- 0);
-
- /* C*x (sin) */
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_W,
- swizzle(const_sin[0], Y, Y, Y, Y),
- swizzle(keep(src[0]), X, X, X, X),
- pfs_zero, 0);
-
- /* B*x, C*x (cos) */
- emit_arith(fp, PFS_OP_MAD, temp[0],
- WRITEMASK_X | WRITEMASK_Y, swizzle(temp[0],
- Z, Z, Z,
- Z),
- const_sin[0], pfs_zero, 0);
-
- /* B*x (sin) */
- emit_arith(fp, PFS_OP_MAD, temp[1], WRITEMASK_W,
- swizzle(const_sin[0], X, X, X, X),
- keep(src[0]), pfs_zero, 0);
-
- /* y = B*x + C*x*abs(x) (sin) */
- emit_arith(fp, PFS_OP_MAD, temp[1], WRITEMASK_Z,
- absolute(src[0]),
- swizzle(temp[0], W, W, W, W),
- swizzle(temp[1], W, W, W, W), 0);
-
- /* y = B*x + C*x*abs(x) (cos) */
- emit_arith(fp, PFS_OP_MAD, temp[1], WRITEMASK_W,
- swizzle(temp[0], Y, Y, Y, Y),
- absolute(swizzle(temp[0], Z, Z, Z, Z)),
- swizzle(temp[0], X, X, X, X), 0);
-
- /* y*abs(y) - y (cos), y*abs(y) - y (sin) */
- emit_arith(fp, PFS_OP_MAD, temp[0],
- WRITEMASK_X | WRITEMASK_Y, swizzle(temp[1],
- W, Z, Y,
- X),
- absolute(swizzle(temp[1], W, Z, Y, X)),
- negate(swizzle(temp[1], W, Z, Y, X)), 0);
-
- /* dest.xy = mad(temp.xy, P, temp2.wz) */
- emit_arith(fp, PFS_OP_MAD, dest,
- mask & (WRITEMASK_X | WRITEMASK_Y), temp[0],
- swizzle(const_sin[0], W, W, W, W),
- swizzle(temp[1], W, Z, Y, X), flags);
-
- free_temp(fp, temp[0]);
- free_temp(fp, temp[1]);
- break;
- case OPCODE_SGE:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- temp[0] = get_temp_reg(fp);
- /* temp = src0 - src1
- * dest.c = (temp.c < 0.0) ? 0 : 1
- */
- emit_arith(fp, PFS_OP_MAD, temp[0], mask,
- src[0], pfs_one, negate(src[1]), 0);
- emit_arith(fp, PFS_OP_CMP, dest, mask,
- pfs_one, pfs_zero, temp[0], 0);
- free_temp(fp, temp[0]);
- break;
- case OPCODE_SIN:
- /*
- * using a parabola:
- * sin(x) = 4/pi * x + -4/(pi*pi) * x * abs(x)
- * extra precision is obtained by weighting against
- * itself squared.
- */
-
- temp[0] = get_temp_reg(fp);
- const_sin[0] = emit_const4fv(fp, SinCosConsts[0]);
- const_sin[1] = emit_const4fv(fp, SinCosConsts[1]);
- src[0] = t_scalar_src(fp, fpi->SrcReg[0]);
-
- /* do range reduction */
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_X,
- swizzle(keep(src[0]), X, X, X, X),
- swizzle(const_sin[1], Z, Z, Z, Z),
- pfs_half, 0);
-
- emit_arith(fp, PFS_OP_FRC, temp[0], WRITEMASK_X,
- swizzle(temp[0], X, X, X, X),
- undef, undef, 0);
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_Z, swizzle(temp[0], X, X, X, X), swizzle(const_sin[1], W, W, W, W), //2*PI
- negate(swizzle(const_sin[0], Z, Z, Z, Z)), //PI
- 0);
-
- /* SIN */
-
- emit_arith(fp, PFS_OP_MAD, temp[0],
- WRITEMASK_X | WRITEMASK_Y, swizzle(temp[0],
- Z, Z, Z,
- Z),
- const_sin[0], pfs_zero, 0);
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_X,
- swizzle(temp[0], Y, Y, Y, Y),
- absolute(swizzle(temp[0], Z, Z, Z, Z)),
- swizzle(temp[0], X, X, X, X), 0);
-
- emit_arith(fp, PFS_OP_MAD, temp[0], WRITEMASK_Y,
- swizzle(temp[0], X, X, X, X),
- absolute(swizzle(temp[0], X, X, X, X)),
- negate(swizzle(temp[0], X, X, X, X)), 0);
-
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- swizzle(temp[0], Y, Y, Y, Y),
- swizzle(const_sin[0], W, W, W, W),
- swizzle(temp[0], X, X, X, X), flags);
-
- free_temp(fp, temp[0]);
- break;
- case OPCODE_SLT:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- temp[0] = get_temp_reg(fp);
- /* temp = src0 - src1
- * dest.c = (temp.c < 0.0) ? 1 : 0
- */
- emit_arith(fp, PFS_OP_MAD, temp[0], mask,
- src[0], pfs_one, negate(src[1]), 0);
- emit_arith(fp, PFS_OP_CMP, dest, mask,
- pfs_zero, pfs_one, temp[0], 0);
- free_temp(fp, temp[0]);
- break;
- case OPCODE_SUB:
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- emit_arith(fp, PFS_OP_MAD, dest, mask,
- src[0], pfs_one, negate(src[1]), flags);
- break;
- case OPCODE_TEX:
- emit_tex(fp, fpi, R300_FPITX_OP_TEX);
- break;
- case OPCODE_TXB:
- emit_tex(fp, fpi, R300_FPITX_OP_TXB);
- break;
- case OPCODE_TXP:
- emit_tex(fp, fpi, R300_FPITX_OP_TXP);
- break;
- case OPCODE_XPD:{
- src[0] = t_src(fp, fpi->SrcReg[0]);
- src[1] = t_src(fp, fpi->SrcReg[1]);
- temp[0] = get_temp_reg(fp);
- /* temp = src0.zxy * src1.yzx */
- emit_arith(fp, PFS_OP_MAD, temp[0],
- WRITEMASK_XYZ, swizzle(keep(src[0]),
- Z, X, Y, W),
- swizzle(keep(src[1]), Y, Z, X, W),
- pfs_zero, 0);
- /* dest.xyz = src0.yzx * src1.zxy - temp
- * dest.w = undefined
- * */
- emit_arith(fp, PFS_OP_MAD, dest,
- mask & WRITEMASK_XYZ, swizzle(src[0],
- Y, Z,
- X, W),
- swizzle(src[1], Z, X, Y, W),
- negate(temp[0]), flags);
- /* cleanup */
- free_temp(fp, temp[0]);
+ case OPCODE_ABS:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ /* Variation on MOV */
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | MAKE_SWIZ_RGB_A(make_rgb_swizzle(fpi->SrcReg[0]))
+ | R500_ALU_RGB_MOD_A_ABS | R500_ALU_RGB_SEL_B_SRC0
+ | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[0]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MAX
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0
+ | MAKE_SWIZ_ALPHA_A(make_alpha_swizzle(fpi->SrcReg[0])) | R500_ALPHA_MOD_A_ABS
+ | R500_ALPHA_SEL_B_SRC0 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[0]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MAX
+ | R500_ALU_RGBA_ADDRD(dest);
+ break;
+ case OPCODE_ADD:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[1]);
+ /* Variation on MAD: 1*src0+src1 */
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0])
+ | R500_RGB_ADDR1(src[1]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0])
+ | R500_ALPHA_ADDR1(src[1]);
+ fp->inst[counter].inst3 = /* 1 */
+ MAKE_SWIZ_RGB_A(R500_SWIZ_RGB_ONE)
+ | R500_ALU_RGB_SEL_B_SRC0 | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[0]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MAD
+ | R500_ALPHA_ADDRD(dest)
+ | MAKE_SWIZ_ALPHA_A(R500_SWIZZLE_ONE)
+ | R500_ALPHA_SEL_B_SRC0 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[0]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MAD
+ | R500_ALU_RGBA_ADDRD(dest)
+ | R500_ALU_RGBA_SEL_C_SRC1
+ | MAKE_SWIZ_RGBA_C(make_rgb_swizzle(fpi->SrcReg[1]))
+ | R500_ALU_RGBA_ALPHA_SEL_C_SRC1
+ | MAKE_SWIZ_ALPHA_C(make_alpha_swizzle(fpi->SrcReg[1]));
+ break;
+ case OPCODE_DP3:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[1]);
+ src[2] = make_src(fp, fpi->SrcReg[2]);
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0])
+ | R500_RGB_ADDR1(src[1]) | R500_RGB_ADDR2(src[2]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0])
+ | R500_ALPHA_ADDR1(src[1]) | R500_ALPHA_ADDR2(src[2]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | MAKE_SWIZ_RGB_A(make_rgb_swizzle(fpi->SrcReg[0]))
+ | R500_ALU_RGB_SEL_B_SRC1 | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_DP
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | MAKE_SWIZ_ALPHA_A(make_alpha_swizzle(fpi->SrcReg[0]))
+ | R500_ALPHA_SEL_B_SRC1 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_DP3
+ | R500_ALU_RGBA_ADDRD(dest)
+ | R500_ALU_RGBA_SEL_C_SRC2
+ | MAKE_SWIZ_RGBA_C(make_rgb_swizzle(fpi->SrcReg[2]))
+ | R500_ALU_RGBA_ALPHA_SEL_C_SRC2
+ | MAKE_SWIZ_ALPHA_C(make_alpha_swizzle(fpi->SrcReg[2]));
+ break;
+ case OPCODE_DP4:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[1]);
+ src[2] = make_src(fp, fpi->SrcReg[2]);
+ /* Based on DP3 */
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0])
+ | R500_RGB_ADDR1(src[1]) | R500_RGB_ADDR2(src[2]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0])
+ | R500_ALPHA_ADDR1(src[1]) | R500_ALPHA_ADDR2(src[2]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | MAKE_SWIZ_RGB_A(make_rgb_swizzle(fpi->SrcReg[0]))
+ | R500_ALU_RGB_SEL_B_SRC1 | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_DP
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | MAKE_SWIZ_ALPHA_A(make_alpha_swizzle(fpi->SrcReg[0]))
+ | R500_ALPHA_SEL_B_SRC1 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_DP4
+ | R500_ALU_RGBA_ADDRD(dest)
+ | R500_ALU_RGBA_SEL_C_SRC2
+ | MAKE_SWIZ_RGBA_C(make_rgb_swizzle(fpi->SrcReg[2]))
+ | R500_ALU_RGBA_ALPHA_SEL_C_SRC2
+ | MAKE_SWIZ_ALPHA_C(make_alpha_swizzle(fpi->SrcReg[2]));
+ break;
+ case OPCODE_MAD:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[1]);
+ src[2] = make_src(fp, fpi->SrcReg[2]);
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0])
+ | R500_RGB_ADDR1(src[1]) | R500_RGB_ADDR2(src[2]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0])
+ | R500_ALPHA_ADDR1(src[1]) | R500_ALPHA_ADDR2(src[2]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | MAKE_SWIZ_RGB_A(make_rgb_swizzle(fpi->SrcReg[0]))
+ | R500_ALU_RGB_SEL_B_SRC1 | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MAD
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | MAKE_SWIZ_ALPHA_A(make_alpha_swizzle(fpi->SrcReg[0]))
+ | R500_ALPHA_SEL_B_SRC1 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MAD
+ | R500_ALU_RGBA_ADDRD(dest)
+ | R500_ALU_RGBA_SEL_C_SRC2
+ | MAKE_SWIZ_RGBA_C(make_rgb_swizzle(fpi->SrcReg[2]))
+ | R500_ALU_RGBA_ALPHA_SEL_C_SRC2
+ | MAKE_SWIZ_ALPHA_C(make_alpha_swizzle(fpi->SrcReg[2]));
+ break;
+ case OPCODE_MAX:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[0]);
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0]) | R500_RGB_ADDR1(src[1]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0]) | R500_ALPHA_ADDR1(src[1]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | MAKE_SWIZ_RGB_A(make_rgb_swizzle(fpi->SrcReg[0]))
+ | R500_ALU_RGB_SEL_B_SRC1
+ | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MAX
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | MAKE_SWIZ_ALPHA_A(make_alpha_swizzle(fpi->SrcReg[0]))
+ | R500_ALPHA_SEL_B_SRC1 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MAX
+ | R500_ALU_RGBA_ADDRD(dest);
+ break;
+ case OPCODE_MIN:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[0]);
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0]) | R500_RGB_ADDR1(src[1]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0]) | R500_ALPHA_ADDR1(src[1]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | MAKE_SWIZ_RGB_A(make_rgb_swizzle(fpi->SrcReg[0]))
+ | R500_ALU_RGB_SEL_B_SRC1
+ | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MIN
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | MAKE_SWIZ_ALPHA_A(make_alpha_swizzle(fpi->SrcReg[0]))
+ | R500_ALPHA_SEL_B_SRC1 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MIN
+ | R500_ALU_RGBA_ADDRD(dest);
+ break;
+ case OPCODE_MOV:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ /* We use MAX, but MIN, CND, and CMP also work.
+ * Just remember to disable the OMOD! */
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | R500_ALU_RGB_R_SWIZ_A_R | R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B
+ | R500_ALU_RGB_SEL_B_SRC0
+ | R500_ALU_RGB_R_SWIZ_B_R | R500_ALU_RGB_G_SWIZ_B_G | R500_ALU_RGB_B_SWIZ_B_B
+ | R500_ALU_RGB_OMOD_DISABLE;
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MAX
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | R500_ALPHA_SEL_B_SRC0
+ | R500_ALPHA_OMOD_DISABLE;
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MAX
+ | R500_ALU_RGBA_ADDRD(dest);
+ break;
+ case OPCODE_MUL:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[1]);
+ /* Variation on MAD: src0*src1+0 */
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR0(src[0])
+ | R500_RGB_ADDR1(src[1]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR0(src[0])
+ | R500_ALPHA_ADDR1(src[1]);
+ fp->inst[counter].inst3 = R500_ALU_RGB_SEL_A_SRC0
+ | MAKE_SWIZ_RGB_A(make_rgb_swizzle(fpi->SrcReg[0]))
+ | R500_ALU_RGB_SEL_B_SRC1 | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MAD
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | MAKE_SWIZ_ALPHA_A(make_alpha_swizzle(fpi->SrcReg[0]))
+ | R500_ALPHA_SEL_B_SRC1 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[1]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MAD
+ | R500_ALU_RGBA_ADDRD(dest)
+ // | R500_ALU_RGBA_SEL_C_SRC2
+ | MAKE_SWIZ_RGBA_C(R500_SWIZ_RGB_ZERO)
+ // | R500_ALU_RGBA_ALPHA_SEL_C_SRC2
+ | MAKE_SWIZ_ALPHA_C(R500_SWIZZLE_ZERO);
+ break;
+ case OPCODE_SUB:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ src[1] = make_src(fp, fpi->SrcReg[1]);
+ /* Variation on MAD: 1*src0-src1 */
+ fp->inst[counter].inst0 = R500_INST_TYPE_ALU
+ | mask;
+ fp->inst[counter].inst1 = R500_RGB_ADDR1(src[0])
+ | R500_RGB_ADDR2(src[1]);
+ fp->inst[counter].inst2 = R500_ALPHA_ADDR1(src[0])
+ | R500_ALPHA_ADDR2(src[1]);
+ fp->inst[counter].inst3 = /* 1 */
+ MAKE_SWIZ_RGB_A(R500_SWIZ_RGB_ONE)
+ | R500_ALU_RGB_SEL_B_SRC1 | MAKE_SWIZ_RGB_B(make_rgb_swizzle(fpi->SrcReg[0]));
+ fp->inst[counter].inst4 = R500_ALPHA_OP_MAD
+ | R500_ALPHA_ADDRD(dest)
+ | R500_ALPHA_SEL_A_SRC0 | MAKE_SWIZ_ALPHA_A(R500_SWIZZLE_ONE)
+ | R500_ALPHA_SEL_B_SRC1 | MAKE_SWIZ_ALPHA_B(make_alpha_swizzle(fpi->SrcReg[0]));
+ fp->inst[counter].inst5 = R500_ALU_RGBA_OP_MAD
+ | R500_ALU_RGBA_ADDRD(dest)
+ | R500_ALU_RGBA_SEL_C_SRC2
+ | MAKE_SWIZ_RGBA_C(make_rgb_swizzle(fpi->SrcReg[1]))
+ | R500_ALU_RGBA_MOD_C_NEG
+ | R500_ALU_RGBA_ALPHA_SEL_C_SRC2
+ | MAKE_SWIZ_ALPHA_C(make_alpha_swizzle(fpi->SrcReg[1]))
+ | R500_ALU_RGBA_ALPHA_MOD_C_NEG;
+ break;
+ case OPCODE_TEX:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ fp->inst[counter].inst0 = R500_INST_TYPE_TEX | mask
+ | R500_INST_TEX_SEM_WAIT;
+ fp->inst[counter].inst1 = fpi->TexSrcUnit
+ | R500_TEX_INST_LD | R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED;
+ fp->inst[counter].inst2 = R500_TEX_SRC_ADDR(src[0])
+ /* | MAKE_SWIZ_TEX_STRQ(make_strq_swizzle(fpi->SrcReg[0])) */
+ | R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G
+ | R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A
+ | R500_TEX_DST_ADDR(dest)
+ | R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G
+ | R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A;
+ fp->inst[counter].inst3 = 0x0;
+ fp->inst[counter].inst4 = 0x0;
+ fp->inst[counter].inst5 = 0x0;
+ break;
+ case OPCODE_TXP:
+ src[0] = make_src(fp, fpi->SrcReg[0]);
+ fp->inst[counter].inst0 = R500_INST_TYPE_TEX | mask;
+ fp->inst[counter].inst1 = fpi->TexSrcUnit
+ | R500_TEX_INST_PROJ | R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED;
+ fp->inst[counter].inst2 = R500_TEX_SRC_ADDR(src[0])
+ /* | MAKE_SWIZ_TEX_STRQ(make_strq_swizzle(fpi->SrcReg[0])) */
+ | R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G
+ | R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A
+ | R500_TEX_DST_ADDR(dest)
+ | R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G
+ | R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A;
+ fp->inst[counter].inst3 = 0x0;
+ fp->inst[counter].inst4 = 0x0;
+ fp->inst[counter].inst5 = 0x0;
+ break;
+ default:
+ ERROR("unknown fpi->Opcode %d\n", fpi->Opcode);
break;
- }
- default:
- ERROR("unknown fpi->Opcode %d\n", fpi->Opcode);
- break;
}
+ /* Finishing touches */
+ if (fpi->SaturateMode == SATURATE_ZERO_ONE) {
+ fp->inst[counter].inst0 |= R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP;
+ }
+ if (fpi->DstReg.File == PROGRAM_OUTPUT) {
+ fp->inst[counter].inst0 |= R500_INST_TYPE_OUT
+ | R500_INST_RGB_OMASK_R | R500_INST_RGB_OMASK_G
+ | R500_INST_RGB_OMASK_B | R500_INST_ALPHA_OMASK;
+ }
+
+ counter++;
+
if (fp->error)
return GL_FALSE;
}
- return GL_TRUE;
-}
-
-static void insert_wpos(struct gl_program *prog)
-{
- static gl_state_index tokens[STATE_LENGTH] = {
- STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0
- };
- struct prog_instruction *fpi;
- GLuint window_index;
- int i = 0;
- GLuint tempregi = prog->NumTemporaries;
- /* should do something else if no temps left... */
- prog->NumTemporaries++;
-
- fpi = _mesa_alloc_instructions(prog->NumInstructions + 3);
- _mesa_init_instructions(fpi, prog->NumInstructions + 3);
-
- /* perspective divide */
- fpi[i].Opcode = OPCODE_RCP;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_W;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_INPUT;
- fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
- fpi[i].SrcReg[0].Swizzle = SWIZZLE_WWWW;
- i++;
-
- fpi[i].Opcode = OPCODE_MUL;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_INPUT;
- fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
- fpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
-
- fpi[i].SrcReg[1].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[1].Index = tempregi;
- fpi[i].SrcReg[1].Swizzle = SWIZZLE_WWWW;
- i++;
-
- /* viewport transformation */
- window_index = _mesa_add_state_reference(prog->Parameters, tokens);
-
- fpi[i].Opcode = OPCODE_MAD;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[0].Index = tempregi;
- fpi[i].SrcReg[0].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
-
- fpi[i].SrcReg[1].File = PROGRAM_STATE_VAR;
- fpi[i].SrcReg[1].Index = window_index;
- fpi[i].SrcReg[1].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
-
- fpi[i].SrcReg[2].File = PROGRAM_STATE_VAR;
- fpi[i].SrcReg[2].Index = window_index;
- fpi[i].SrcReg[2].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
- i++;
+ fp->cs->nrslots = counter;
- _mesa_copy_instructions(&fpi[i], prog->Instructions,
- prog->NumInstructions);
-
- free(prog->Instructions);
-
- prog->Instructions = fpi;
-
- prog->NumInstructions += i;
- fpi = &prog->Instructions[prog->NumInstructions - 1];
-
- assert(fpi->Opcode == OPCODE_END);
-
- for (fpi = &prog->Instructions[3]; fpi->Opcode != OPCODE_END; fpi++) {
- for (i = 0; i < 3; i++)
- if (fpi->SrcReg[i].File == PROGRAM_INPUT &&
- fpi->SrcReg[i].Index == FRAG_ATTRIB_WPOS) {
- fpi->SrcReg[i].File = PROGRAM_TEMPORARY;
- fpi->SrcReg[i].Index = tempregi;
- }
+ /* Finish him! (If it's an output instruction...)
+ * Yes, I know it's ugly... */
+ if ((fp->inst[counter].inst0 & 0x3) ^ 0x2) {
+ fp->inst[counter].inst0 |= R500_INST_TYPE_OUT
+ | R500_INST_TEX_SEM_WAIT | R500_INST_LAST;
}
+
+ return GL_TRUE;
}
-/* - Init structures
- * - Determine what hwregs each input corresponds to
- */
-static void init_program(r300ContextPtr r300, struct r300_fragment_program *fp)
+static void init_program(r300ContextPtr r300, struct r500_fragment_program *fp)
{
struct r300_pfs_compile_state *cs = NULL;
struct gl_fragment_program *mp = &fp->mesa_program;
fp->translated = GL_FALSE;
fp->error = GL_FALSE;
fp->cs = cs = &(R300_CONTEXT(fp->ctx)->state.pfs_compile);
- fp->tex.length = 0;
fp->cur_node = 0;
fp->first_node_has_tex = 0;
fp->const_nr = 0;
* starting from register 0.
*/
+#if 0
/* Texcoords come first */
for (i = 0; i < fp->ctx->Const.MaxTextureUnits; i++) {
if (InputsRead & (FRAG_BIT_TEX0 << i)) {
if (InputsRead & (1 << i))
cs->inputs[i].reg = 0;
}
+#endif
/* Pre-parse the mesa program, grabbing refcounts on input/temp regs.
* That way, we can free up the reg when it's no longer needed
cs->temp_in_use = temps_used;
}
-static void update_params(struct r300_fragment_program *fp)
+static void update_params(struct r500_fragment_program *fp)
{
struct gl_fragment_program *mp = &fp->mesa_program;
}
void r500TranslateFragmentShader(r300ContextPtr r300,
- struct r300_fragment_program *fp)
+ struct r500_fragment_program *fp)
{
+
struct r300_pfs_compile_state *cs = NULL;
if (!fp->translated) {
+ /* I need to see what I'm working with! */
+ fprintf(stderr, "Mesa program:\n");
+ fprintf(stderr, "-------------\n");
+ _mesa_print_program(&fp->mesa_program.Base);
+ fflush(stdout);
+
init_program(r300, fp);
cs = fp->cs;
if (parse_program(fp) == GL_FALSE) {
- dump_program(fp);
+ ERROR("Huh. Couldn't parse program. There should be additional errors explaining why.\nUsing dumb shader...\n");
+ dumb_shader(fp);
return;
}
fp->node[fp->cur_node].tex_end = 0;
fp->alu_offset = 0;
fp->alu_end = cs->nrslots - 1;
- fp->tex_offset = 0;
- fp->tex_end = fp->tex.length ? fp->tex.length - 1 : 0;
- assert(fp->node[fp->cur_node].alu_end >= 0);
- assert(fp->alu_end >= 0);
+ //assert(fp->node[fp->cur_node].alu_end >= 0);
+ //assert(fp->alu_end >= 0);
fp->translated = GL_TRUE;
- if (RADEON_DEBUG & DEBUG_PIXEL)
- dump_program(fp);
r300UpdateStateParameters(fp->ctx, _NEW_PROGRAM);
}
update_params(fp);
}
-
-/* just some random things... */
-static void dump_program(struct r300_fragment_program *fp)
-{
- int n, i, j;
- static int pc = 0;
-
- fprintf(stderr, "pc=%d*************************************\n", pc++);
-
- fprintf(stderr, "Mesa program:\n");
- fprintf(stderr, "-------------\n");
- _mesa_print_program(&fp->mesa_program.Base);
- fflush(stdout);
-
- fprintf(stderr, "Hardware program\n");
- fprintf(stderr, "----------------\n");
-
- for (n = 0; n < (fp->cur_node + 1); n++) {
- fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, "
- "alu_end: %d, tex_end: %d\n", n,
- fp->node[n].alu_offset,
- fp->node[n].tex_offset,
- fp->node[n].alu_end, fp->node[n].tex_end);
-
- if (fp->tex.length) {
- fprintf(stderr, " TEX:\n");
- for (i = fp->node[n].tex_offset;
- i <= fp->node[n].tex_offset + fp->node[n].tex_end;
- ++i) {
- const char *instr;
-
- switch ((fp->tex.
- inst[i] >> R300_FPITX_OPCODE_SHIFT) &
- 15) {
- case R300_FPITX_OP_TEX:
- instr = "TEX";
- break;
- case R300_FPITX_OP_KIL:
- instr = "KIL";
- break;
- case R300_FPITX_OP_TXP:
- instr = "TXP";
- break;
- case R300_FPITX_OP_TXB:
- instr = "TXB";
- break;
- default:
- instr = "UNKNOWN";
- }
-
- fprintf(stderr,
- " %s t%i, %c%i, texture[%i] (%08x)\n",
- instr,
- (fp->tex.
- inst[i] >> R300_FPITX_DST_SHIFT) & 31,
- (fp->tex.
- inst[i] & R300_FPITX_SRC_CONST) ? 'c' :
- 't',
- (fp->tex.
- inst[i] >> R300_FPITX_SRC_SHIFT) & 31,
- (fp->tex.
- inst[i] & R300_FPITX_IMAGE_MASK) >>
- R300_FPITX_IMAGE_SHIFT,
- fp->tex.inst[i]);
- }
- }
-
- for (i = fp->node[n].alu_offset;
- i <= fp->node[n].alu_offset + fp->node[n].alu_end; ++i) {
- char srcc[3][10], dstc[20];
- char srca[3][10], dsta[20];
- char argc[3][20];
- char arga[3][20];
- char flags[5], tmp[10];
-
- for (j = 0; j < 3; ++j) {
- int regc = fp->alu.inst[i].inst1 >> (j * 6);
- int rega = fp->alu.inst[i].inst3 >> (j * 6);
-
- sprintf(srcc[j], "%c%i",
- (regc & 32) ? 'c' : 't', regc & 31);
- sprintf(srca[j], "%c%i",
- (rega & 32) ? 'c' : 't', rega & 31);
- }
-
- dstc[0] = 0;
- sprintf(flags, "%s%s%s",
- (fp->alu.inst[i].
- inst1 & R300_FPI1_DSTC_REG_X) ? "x" : "",
- (fp->alu.inst[i].
- inst1 & R300_FPI1_DSTC_REG_Y) ? "y" : "",
- (fp->alu.inst[i].
- inst1 & R300_FPI1_DSTC_REG_Z) ? "z" : "");
- if (flags[0] != 0) {
- sprintf(dstc, "t%i.%s ",
- (fp->alu.inst[i].
- inst1 >> R300_FPI1_DSTC_SHIFT) & 31,
- flags);
- }
- sprintf(flags, "%s%s%s",
- (fp->alu.inst[i].
- inst1 & R300_FPI1_DSTC_OUTPUT_X) ? "x" : "",
- (fp->alu.inst[i].
- inst1 & R300_FPI1_DSTC_OUTPUT_Y) ? "y" : "",
- (fp->alu.inst[i].
- inst1 & R300_FPI1_DSTC_OUTPUT_Z) ? "z" : "");
- if (flags[0] != 0) {
- sprintf(tmp, "o%i.%s",
- (fp->alu.inst[i].
- inst1 >> R300_FPI1_DSTC_SHIFT) & 31,
- flags);
- strcat(dstc, tmp);
- }
-
- dsta[0] = 0;
- if (fp->alu.inst[i].inst3 & R300_FPI3_DSTA_REG) {
- sprintf(dsta, "t%i.w ",
- (fp->alu.inst[i].
- inst3 >> R300_FPI3_DSTA_SHIFT) & 31);
- }
- if (fp->alu.inst[i].inst3 & R300_FPI3_DSTA_OUTPUT) {
- sprintf(tmp, "o%i.w ",
- (fp->alu.inst[i].
- inst3 >> R300_FPI3_DSTA_SHIFT) & 31);
- strcat(dsta, tmp);
- }
- if (fp->alu.inst[i].inst3 & R300_FPI3_DSTA_DEPTH) {
- strcat(dsta, "Z");
- }
-
- fprintf(stderr,
- "%3i: xyz: %3s %3s %3s -> %-20s (%08x)\n"
- " w: %3s %3s %3s -> %-20s (%08x)\n", i,
- srcc[0], srcc[1], srcc[2], dstc,
- fp->alu.inst[i].inst1, srca[0], srca[1],
- srca[2], dsta, fp->alu.inst[i].inst3);
-
- for (j = 0; j < 3; ++j) {
- int regc = fp->alu.inst[i].inst0 >> (j * 7);
- int rega = fp->alu.inst[i].inst2 >> (j * 7);
- int d;
- char buf[20];
-
- d = regc & 31;
- if (d < 12) {
- switch (d % 4) {
- case R300_FPI0_ARGC_SRC0C_XYZ:
- sprintf(buf, "%s.xyz",
- srcc[d / 4]);
- break;
- case R300_FPI0_ARGC_SRC0C_XXX:
- sprintf(buf, "%s.xxx",
- srcc[d / 4]);
- break;
- case R300_FPI0_ARGC_SRC0C_YYY:
- sprintf(buf, "%s.yyy",
- srcc[d / 4]);
- break;
- case R300_FPI0_ARGC_SRC0C_ZZZ:
- sprintf(buf, "%s.zzz",
- srcc[d / 4]);
- break;
- }
- } else if (d < 15) {
- sprintf(buf, "%s.www", srca[d - 12]);
- } else if (d == 20) {
- sprintf(buf, "0.0");
- } else if (d == 21) {
- sprintf(buf, "1.0");
- } else if (d == 22) {
- sprintf(buf, "0.5");
- } else if (d >= 23 && d < 32) {
- d -= 23;
- switch (d / 3) {
- case 0:
- sprintf(buf, "%s.yzx",
- srcc[d % 3]);
- break;
- case 1:
- sprintf(buf, "%s.zxy",
- srcc[d % 3]);
- break;
- case 2:
- sprintf(buf, "%s.Wzy",
- srcc[d % 3]);
- break;
- }
- } else {
- sprintf(buf, "%i", d);
- }
-
- sprintf(argc[j], "%s%s%s%s",
- (regc & 32) ? "-" : "",
- (regc & 64) ? "|" : "",
- buf, (regc & 64) ? "|" : "");
-
- d = rega & 31;
- if (d < 9) {
- sprintf(buf, "%s.%c", srcc[d / 3],
- 'x' + (char)(d % 3));
- } else if (d < 12) {
- sprintf(buf, "%s.w", srca[d - 9]);
- } else if (d == 16) {
- sprintf(buf, "0.0");
- } else if (d == 17) {
- sprintf(buf, "1.0");
- } else if (d == 18) {
- sprintf(buf, "0.5");
- } else {
- sprintf(buf, "%i", d);
- }
-
- sprintf(arga[j], "%s%s%s%s",
- (rega & 32) ? "-" : "",
- (rega & 64) ? "|" : "",
- buf, (rega & 64) ? "|" : "");
- }
-
- fprintf(stderr, " xyz: %8s %8s %8s op: %08x\n"
- " w: %8s %8s %8s op: %08x\n",
- argc[0], argc[1], argc[2],
- fp->alu.inst[i].inst0, arga[0], arga[1],
- arga[2], fp->alu.inst[i].inst2);
- }
- }
-}
#define DRI_CONF_FP_OPTIMIZATION_SPEED 0
#define DRI_CONF_FP_OPTIMIZATION_QUALITY 1
-struct r300_fragment_program;
+struct r500_fragment_program;
+
+extern void r500TranslateFragmentShader(r300ContextPtr r300,
+ struct r500_fragment_program *fp);
extern void r300TranslateFragmentShader(r300ContextPtr r300,
struct r300_fragment_program *fp);
#define PCI_CHIP_RV410_5E4D 0x5E4D
#define PCI_CHIP_RV410_5E4F 0x5E4F
+<<<<<<< HEAD:src/mesa/drivers/dri/radeon/radeon_chipset.h
+#define PCI_CHIP_RV530_71C4 0x71C4
+#define PCI_CHIP_RV530_71D5 0x71D5
+=======
#define PCI_CHIP_RV530_71C4 0x71C4
+>>>>>>> eff6f1203222a776c5990b5d104b57a7f69b9aab:src/mesa/drivers/dri/radeon/radeon_chipset.h
#define PCI_CHIP_RS350_7834 0x7834
#define PCI_CHIP_RS350_7835 0x7835
DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
- DRI_CONF_ALLOW_LARGE_TEXTURES(1)
+ DRI_CONF_ALLOW_LARGE_TEXTURES(2)
DRI_CONF_SECTION_END
DRI_CONF_SECTION_DEBUG
DRI_CONF_NO_RAST(false)
DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
- DRI_CONF_ALLOW_LARGE_TEXTURES(1)
+ DRI_CONF_ALLOW_LARGE_TEXTURES(2)
DRI_CONF_TEXTURE_BLEND_QUALITY(1.0,"0.0:1.0")
DRI_CONF_SECTION_END
DRI_CONF_SECTION_DEBUG
fprintf(stderr, "Warning, R520 detected, 3D HAHAHAHAHA!!.\n");
break;
+<<<<<<< HEAD:src/mesa/drivers/dri/radeon/radeon_screen.c
+ case PCI_CHIP_RV530_71D5:
+ screen->chip_family = CHIP_FAMILY_R520;
+ fprintf(stderr, "Warning, RV530 detected, all your base belong to us\n");
+ break;
+
+=======
+>>>>>>> eff6f1203222a776c5990b5d104b57a7f69b9aab:src/mesa/drivers/dri/radeon/radeon_screen.c
default:
fprintf(stderr, "unknown chip id 0x%x, can't guess.\n",
dri_priv->deviceID);
#ifdef XFree86Server
+# include "xorg-server.h"
# include "resource.h"
# include "windowstr.h"
+++ /dev/null
-# Note: only listing sources needed for X server renderer
-MESA_DRIVER_X11_SOURCES = \
-xm_api.c \
-xm_buffer.c \
-xm_dd.c \
-xm_line.c \
-xm_span.c \
-xm_tri.c
/**********************************************************************/
+#ifdef IN_DRI_DRIVER
+#define need_GL_VERSION_1_3
+#define need_GL_VERSION_1_4
+#define need_GL_VERSION_1_5
+#define need_GL_VERSION_2_0
+
+/* sw extensions for imaging */
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_convolution
+#define need_GL_EXT_histogram
+#define need_GL_SGI_color_table
+
+/* sw extensions not associated with some GL version */
+#define need_GL_ARB_shader_objects
+#define need_GL_ARB_vertex_program
+#define need_GL_APPLE_vertex_array_object
+#define need_GL_ATI_fragment_shader
+#define need_GL_EXT_depth_bounds_test
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_framebuffer_blit
+#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_paletted_texture
+#define need_GL_IBM_multimode_draw_arrays
+#define need_GL_MESA_resize_buffers
+#define need_GL_NV_vertex_program
+#define need_GL_NV_fragment_program
+
+#include "extension_helper.h"
+#include "utils.h"
+
+const struct dri_extension card_extensions[] =
+{
+ { "GL_VERSION_1_3", GL_VERSION_1_3_functions },
+ { "GL_VERSION_1_4", GL_VERSION_1_4_functions },
+ { "GL_VERSION_1_5", GL_VERSION_1_5_functions },
+ { "GL_VERSION_2_0", GL_VERSION_2_0_functions },
+
+ { "GL_EXT_blend_color", GL_EXT_blend_color_functions },
+ { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
+ { "GL_EXT_convolution", GL_EXT_convolution_functions },
+ { "GL_EXT_histogram", GL_EXT_histogram_functions },
+ { "GL_SGI_color_table", GL_SGI_color_table_functions },
+
+ { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+ { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
+ { "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions },
+ { "GL_EXT_depth_bounds_test", GL_EXT_depth_bounds_test_functions },
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
+ { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
+ { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
+ { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
+ { "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions },
+ { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
+ { "GL_NV_fragment_program", GL_NV_fragment_program_functions },
+ { NULL, NULL }
+};
+#endif
+
/*
* Create a new X/Mesa visual.
* Input: display - X11 display
XMesaVisual v;
GLint red_bits, green_bits, blue_bits, alpha_bits;
+#ifdef IN_DRI_DRIVER
+ /* driInitExtensions() should be called once per screen to setup extension
+ * indices. There is no need to call it when the context is created since
+ * XMesa enables mesa sw extensions on its own.
+ */
+ driInitExtensions( NULL, card_extensions, GL_FALSE );
+#endif
+
#ifndef XFree86Server
/* For debugging only */
if (_mesa_getenv("MESA_XSYNC")) {
_mesa_enable_2_0_extensions(mesaCtx);
_mesa_enable_2_1_extensions(mesaCtx);
#if ENABLE_EXT_texure_compression_s3tc
- if (c->Mesa_DXTn) {
+ if (mesaCtx->Mesa_DXTn) {
_mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc");
_mesa_enable_extension(mesaCtx, "GL_S3_s3tc");
}
--- /dev/null
+glxheader.h
+xmesaP.h
+xm_*
--- /dev/null
+# src/mesa/drivers/xorg/Makefile
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = libGLcore.so
+
+SYMLINKS = \
+ glxheader.h \
+ xmesaP.h \
+ xm_api.c \
+ xm_buffer.c \
+ xm_dd.c \
+ xm_image.c \
+ xm_image.h \
+ xm_line.c \
+ xm_span.c \
+ xm_tri.c
+
+C_SOURCES = \
+ xm_api.c \
+ xm_buffer.c \
+ xm_dd.c \
+ xm_image.c \
+ xm_line.c \
+ xm_span.c \
+ xm_tri.c \
+ glcore.c
+
+########################################
+
+MESA_MODULES = $(TOP)/src/mesa/libmesa.a
+
+C_SOURCES += ../common/driverfuncs.c
+ifeq ("${DRIVER_DIRS}", "dri")
+C_SOURCES += ../dri/common/utils.c
+endif
+
+OBJECTS = $(C_SOURCES:.c=.o)
+
+### Include directories
+INCLUDES = \
+ -I. \
+ -I.. \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ `pkg-config --cflags xorg-server`
+
+ifeq ("${DRIVER_DIRS}", "dri")
+INCLUDES += \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ `pkg-config --cflags libdrm`
+endif
+
+# undef 'USE_XSHM' to make it explicit that 'XFree86Server' takes precedence
+DRIVER_DEFINES = -UUSE_XSHM -DXFree86Server
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: depend symlinks $(LIBNAME)
+
+
+$(LIBNAME): $(OBJECTS) $(MESA_MODULES) Makefile
+ $(TOP)/bin/mklib -noprefix -o $@ \
+ $(OBJECTS) $(MESA_MODULES) $(GLCORE_LIB_DEPS)
+
+
+depend: $(C_SOURCES) $(SYMLINKS)
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
+ > /dev/null
+
+
+clean:
+ -rm -f *.o *.so $(SYMLINKS)
+ -rm -f depend depend.bak
+
+install: $(LIBNAME)
+ $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+ $(INSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+
+$(SYMLINKS):
+ @[ -e $@ ] || ln -sf ../x11/$@ ./
+
+symlinks: $(SYMLINKS)
+
+include depend
--- /dev/null
+
+#define _NEED_GL_CORE_IF
+#include <GL/xmesa.h>
+#include <GL/internal/glcore.h>
+#include "xmesaP.h"
+
+PUBLIC
+__GLcoreModule GL_Core = {
+ XMesaCreateVisual,
+ XMesaDestroyVisual,
+
+ XMesaCreateWindowBuffer,
+ XMesaCreatePixmapBuffer,
+ XMesaDestroyBuffer,
+ XMesaSwapBuffers,
+ XMesaResizeBuffers,
+
+ XMesaCreateContext,
+ XMesaDestroyContext,
+ XMesaCopyContext,
+ XMesaMakeCurrent2,
+ XMesaForceCurrent,
+ XMesaLoseCurrent
+};
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
#include "glheader.h"
#include "glapi.h"
#include "glapioffsets.h"
*/
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
#include "glheader.h"
#include "glthread.h"
+++ /dev/null
-MESA_GLAPI_SOURCES = \
-glapi.c \
-glthread.c
-
-MESA_GLAPI_HEADERS = \
-dispatch.h \
-glapi.h \
-glapioffsets.h \
-glapitable.h \
-glapitemp.h \
-glprocs.h \
-glthread.h
#include "version.h"
#include "vtxfmt.h"
#include "glapi/glthread.h"
-#include "glapi/glapioffsets.h"
#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
#include "shader/program.h"
#endif
/*
- * Translate the nth element of list from type to GLuint.
+ * Translate the nth element of list from <type> to GLint.
*/
-static GLuint
+static GLint
translate_id(GLsizei n, GLenum type, const GLvoid * list)
{
GLbyte *bptr;
switch (type) {
case GL_BYTE:
bptr = (GLbyte *) list;
- return (GLuint) *(bptr + n);
+ return (GLint) bptr[n];
case GL_UNSIGNED_BYTE:
ubptr = (GLubyte *) list;
- return (GLuint) *(ubptr + n);
+ return (GLint) ubptr[n];
case GL_SHORT:
sptr = (GLshort *) list;
- return (GLuint) *(sptr + n);
+ return (GLint) sptr[n];
case GL_UNSIGNED_SHORT:
usptr = (GLushort *) list;
- return (GLuint) *(usptr + n);
+ return (GLint) usptr[n];
case GL_INT:
iptr = (GLint *) list;
- return (GLuint) *(iptr + n);
+ return iptr[n];
case GL_UNSIGNED_INT:
uiptr = (GLuint *) list;
- return (GLuint) *(uiptr + n);
+ return (GLint) uiptr[n];
case GL_FLOAT:
fptr = (GLfloat *) list;
- return (GLuint) *(fptr + n);
+ return (GLint) FLOORF(fptr[n]);
case GL_2_BYTES:
ubptr = ((GLubyte *) list) + 2 * n;
- return (GLuint) *ubptr * 256 + (GLuint) * (ubptr + 1);
+ return (GLint) ubptr[0] * 256
+ + (GLint) ubptr[1];
case GL_3_BYTES:
ubptr = ((GLubyte *) list) + 3 * n;
- return (GLuint) * ubptr * 65536
- + (GLuint) *(ubptr + 1) * 256 + (GLuint) * (ubptr + 2);
+ return (GLint) ubptr[0] * 65536
+ + (GLint) ubptr[1] * 256
+ + (GLint) ubptr[2];
case GL_4_BYTES:
ubptr = ((GLubyte *) list) + 4 * n;
- return (GLuint) *ubptr * 16777216
- + (GLuint) *(ubptr + 1) * 65536
- + (GLuint) *(ubptr + 2) * 256 + (GLuint) * (ubptr + 3);
+ return (GLint) ubptr[0] * 16777216
+ + (GLint) ubptr[1] * 65536
+ + (GLint) ubptr[2] * 256
+ + (GLint) ubptr[3];
default:
return 0;
}
}
for (i = 0; i < n; i++) {
- GLuint list = translate_id(i, type, lists);
+ GLint list = translate_id(i, type, lists);
Node *n = ALLOC_INSTRUCTION(ctx, OPCODE_CALL_LIST_OFFSET, 2);
if (n) {
- n[1].ui = list;
+ n[1].i = list;
n[2].b = typeErrorFlag;
}
}
_mesa_error(ctx, GL_INVALID_ENUM, "glCallLists(type)");
}
else if (ctx->ListState.CallDepth < MAX_LIST_NESTING) {
- execute_list(ctx, ctx->List.ListBase + n[1].ui);
+ GLuint list = (GLuint) (ctx->List.ListBase + n[1].i);
+ execute_list(ctx, list);
}
break;
case OPCODE_CLEAR:
_mesa_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
{
GET_CURRENT_CONTEXT(ctx);
- GLuint list;
GLint i;
GLboolean save_compile_flag;
ctx->CompileFlag = GL_FALSE;
for (i = 0; i < n; i++) {
- list = translate_id(i, type, lists);
- execute_list(ctx, ctx->List.ListBase + list);
+ GLuint list = (GLuint) (ctx->List.ListBase + translate_id(i, type, lists));
+ execute_list(ctx, list);
}
ctx->CompileFlag = save_compile_flag;
if (ctx->RenderMode == GL_RENDER) {
/* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
- GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
- GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig);
+ const GLfloat epsilon = 0.0001;
+ GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
+ GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
if (ctx->Unpack.BufferObj->Name) {
/* unpack from PBO */
#ifndef GLHEADER_H
#define GLHEADER_H
-/* This allows Mesa to be integrated into XFree86 */
-#ifdef HAVE_DIX_CONFIG_H
-#include "dix-config.h"
-#endif
-
#include <assert.h>
#include <ctype.h>
#if defined(__alpha__) && defined(CCPML)
+++ /dev/null
-# List of source files in this directory used for X.org xserver build
-MESA_MAIN_SOURCES = \
-accum.c \
-api_arrayelt.c \
-api_loopback.c \
-api_noop.c \
-api_validate.c \
-arrayobj.c \
-attrib.c \
-blend.c \
-bufferobj.c \
-buffers.c \
-clip.c \
-colortab.c \
-context.c \
-convolve.c \
-debug.c \
-depth.c \
-depthstencil.c \
-dlist.c \
-drawpix.c \
-enable.c \
-enums.c \
-eval.c \
-execmem.c \
-extensions.c \
-fbobject.c \
-feedback.c \
-fog.c \
-framebuffer.c \
-get.c \
-getstring.c \
-hash.c \
-hint.c \
-histogram.c \
-image.c \
-imports.c \
-light.c \
-lines.c \
-matrix.c \
-mipmap.c \
-mm.c \
-occlude.c \
-pixel.c \
-points.c \
-polygon.c \
-rastpos.c \
-rbadaptors.c \
-renderbuffer.c \
-state.c \
-stencil.c \
-texcompress.c \
-texcompress_fxt1.c \
-texcompress_s3tc.c \
-texenvprogram.c \
-texformat.c \
-teximage.c \
-texobj.c \
-texrender.c \
-texstate.c \
-texstore.c \
-varray.c \
-$(VSNPRINTF_SOURCES) \
-vtxfmt.c
-
-MESA_VSNPRINTF_SOURCES = \
-vsnprintf.c
-
-MESA_MAIN_HEADERS = \
-accum.h \
-api_arrayelt.h \
-api_eval.h \
-api_loopback.h \
-api_noop.h \
-api_validate.h \
-arrayobj.h \
-attrib.h \
-bitset.h \
-blend.h \
-bufferobj.h \
-buffers.h \
-clip.h \
-colormac.h \
-colortab.h \
-config.h \
-context.h \
-convolve.h \
-dd.h \
-debug.h \
-depth.h \
-depthstencil.h \
-dlist.h \
-drawpix.h \
-enable.h \
-enums.h \
-eval.h \
-extensions.h \
-fbobject.h \
-feedback.h \
-fog.h \
-framebuffer.h \
-get.h \
-glheader.h \
-hash.h \
-hint.h \
-histogram.h \
-image.h \
-imports.h \
-light.h \
-lines.h \
-macros.h \
-matrix.h \
-mipmap.h \
-mm.h \
-mtypes.h \
-occlude.h \
-pixel.h \
-points.h \
-polygon.h \
-rastpos.h \
-rbadaptors.h \
-renderbuffer.h \
-simple_list.h \
-state.h \
-stencil.h \
-texcompress.h \
-texenvprogram.h \
-texformat.h \
-texformat_tmp.h \
-teximage.h \
-texobj.h \
-texrender.h \
-texstate.h \
-texstore.h \
-varray.h \
-version.h \
-vtxfmt.h \
-vtxfmt_tmp.h
return;
}
+ if (mode == GL_REPLACE_EXT)
+ mode = GL_REPLACE;
+
switch (mode) {
case GL_REPLACE:
case GL_MODULATE:
switch (pname) {
case GL_TEXTURE_ENV_MODE:
{
- const GLenum mode = (GLenum) (GLint) *param;
+ GLenum mode = (GLenum) (GLint) *param;
+ if (mode == GL_REPLACE_EXT)
+ mode = GL_REPLACE;
if (texUnit->EnvMode == mode)
return;
if (mode == GL_MODULATE ||
+++ /dev/null
-MESA_MATH_SOURCES = \
-m_debug_clip.c \
-m_debug_norm.c \
-m_debug_xform.c \
-m_eval.c \
-m_matrix.c \
-m_translate.c \
-m_vector.c \
-m_xform.c
-
-MESA_MATH_HEADERS = \
-m_clip_tmp.h \
-m_copy_tmp.h \
-m_debug.h \
-m_debug_util.h \
-m_dotprod_tmp.h \
-m_eval.h \
-m_matrix.h \
-m_norm_tmp.h \
-m_trans_tmp.h \
-m_translate.h \
-m_vector.h \
-m_xform.h \
-m_xform_tmp.h \
-mathmod.h
+++ /dev/null
-MESA_SHADER_GRAMMAR_SOURCES = \
-grammar_mesa.c
-
-MESA_SHADER_GRAMMAR_HEADERS = \
-grammar.c \
-grammar.h \
-grammar_mesa.h \
-grammar_syn.h
case OPCODE_END:
return GL_TRUE;
default:
- _mesa_problem(ctx, "Bad opcode %d in _mesa_exec_fragment_program",
+ _mesa_problem(ctx, "Bad opcode %d in _mesa_execute_program",
inst->Opcode);
+ assert(0);
return GL_TRUE; /* return value doesn't matter */
}
struct gl_program_parameter_list *
_mesa_new_parameter_list(void)
{
- return (struct gl_program_parameter_list *)
- _mesa_calloc(sizeof(struct gl_program_parameter_list));
+ return CALLOC_STRUCT(gl_program_parameter_list);
}
{
(void) ctx;
if (prog) {
- _mesa_bzero(prog, sizeof(*prog));
prog->Id = id;
prog->Target = target;
prog->Resident = GL_TRUE;
_mesa_free(shProg->Shaders);
shProg->Shaders = NULL;
}
+
+ if (shProg->InfoLog) {
+ _mesa_free(shProg->InfoLog);
+ shProg->InfoLog = NULL;
+ }
}
_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
{
_mesa_free_shader_program_data(ctx, shProg);
- if (shProg->Shaders) {
- _mesa_free(shProg->Shaders);
- shProg->Shaders = NULL;
- }
+
_mesa_free(shProg);
}
+++ /dev/null
-MESA_SHADER_SLANG_SOURCES = \
-slang_analyse.c \
-slang_assemble_assignment.c \
-slang_assemble.c \
-slang_assemble_conditional.c \
-slang_assemble_constructor.c \
-slang_assemble_typeinfo.c \
-slang_compile.c \
-slang_compile_function.c \
-slang_compile_operation.c \
-slang_compile_struct.c \
-slang_compile_variable.c \
-slang_execute.c \
-slang_execute_x86.c \
-slang_export.c \
-slang_library_texsample.c \
-slang_library_noise.c \
-slang_link.c \
-slang_preprocess.c \
-slang_storage.c \
-slang_utility.c
-
-MESA_SHADER_SLANG_HEADERS = \
-slang_analyse.h \
-slang_assemble.h \
-slang_assemble_assignment.h \
-slang_assemble_conditional.h \
-slang_assemble_constructor.h \
-slang_assemble_typeinfo.h \
-slang_compile.h \
-slang_compile_function.h \
-slang_compile_operation.h \
-slang_compile_struct.h \
-slang_compile_variable.h \
-slang_execute.h \
-slang_export.h \
-slang_library_noise.h \
-slang_library_texsample.h \
-slang_link.h \
-slang_mesa.h \
-slang_preprocess.h \
-slang_storage.h \
-slang_utility.h \
-traverse_wrap.h
+++ /dev/null
-# List of source files in this directory used for X.org xserver build
-MESA_SHADER_SOURCES = \
-arbprogparse.c \
-arbprogram.c \
-atifragshader.c \
-nvfragparse.c \
-nvprogram.c \
-nvvertexec.c \
-nvvertparse.c \
-program.c \
-programopt.c \
-shaderobjects.c \
-shaderobjects_3dlabs.c
-
-MESA_SHADER_HEADERS = \
-arbprogparse.h \
-arbprogram.h \
-arbprogram_syn.h \
-atifragshader.h \
-nvfragparse.h \
-nvprogram.h \
-nvvertexec.h \
-nvvertparse.h \
-programopt.h \
-program.h \
-program_instruction.h \
-shaderobjects.h \
-shaderobjects_3dlabs.h
+++ /dev/null
-# List of source files in this directory used for X.org xserver build
-MESA_SWRAST_SOURCES = \
-s_aaline.c \
-s_aatriangle.c \
-s_accum.c \
-s_alpha.c \
-s_arbshader.c \
-s_atifragshader.c \
-s_bitmap.c \
-s_blend.c \
-s_blit.c \
-s_buffers.c \
-s_context.c \
-s_copypix.c \
-s_depth.c \
-s_drawpix.c \
-s_feedback.c \
-s_fog.c \
-s_imaging.c \
-s_lines.c \
-s_logic.c \
-s_masking.c \
-s_nvfragprog.c \
-s_points.c \
-s_readpix.c \
-s_span.c \
-s_stencil.c \
-s_texcombine.c \
-s_texfilter.c \
-s_texstore.c \
-s_triangle.c \
-s_zoom.c
-
-MESA_SWRAST_HEADERS = \
-s_aaline.h \
-s_aalinetemp.h \
-s_aatriangle.h \
-s_aatritemp.h \
-s_accum.h \
-s_alpha.h \
-s_arbshader.h \
-s_atifragshader.h \
-s_blend.h \
-s_context.h \
-s_depth.h \
-s_drawpix.h \
-s_feedback.h \
-s_fog.h \
-s_lines.h \
-s_linetemp.h \
-s_logic.h \
-s_masking.h \
-s_nvfragprog.h \
-s_points.h \
-s_pointtemp.h \
-s_span.h \
-s_spantemp.h \
-s_stencil.h \
-s_texcombine.h \
-s_texfilter.h \
-s_triangle.h \
-s_trispan.h \
-s_tritemp.h \
-s_zoom.h \
-swrast.h
+++ /dev/null
-MESA_SWRAST_SETUP_SOURCES = \
-ss_context.c \
-ss_triangle.c
-
-MESA_SWRAST_SETUP_HEADERS = \
-ss_context.h \
-ss_triangle.h \
-ss_tritmp.h \
-ss_vb.h \
-swrast_setup.h
+++ /dev/null
-# List of source files in this directory used for X.org xserver build
-MESA_TNL_SOURCES = \
-t_context.c \
-t_pipeline.c \
-t_vb_arbprogram.c \
-t_vb_arbprogram_sse.c \
-t_vb_arbshader.c \
-t_vb_cull.c \
-t_vb_fog.c \
-t_vb_light.c \
-t_vb_normals.c \
-t_vb_points.c \
-t_vb_program.c \
-t_vb_render.c \
-t_vb_texgen.c \
-t_vb_texmat.c \
-t_vb_vertex.c \
-t_vertex.c \
-t_vertex_generic.c \
-t_vertex_sse.c \
-t_vp_build.c
-
-MESA_TNL_HEADERS = \
-t_array_api.h \
-t_array_import.h \
-t_context.h \
-t_pipeline.h \
-t_vb_arbprogram.h \
-t_vb_cliptmp.h \
-t_vb_lighttmp.h \
-t_vb_rendertmp.h \
-t_vertex.h \
-t_vp_build.h \
-tnl.h
#include "main/state.h"
#include "main/api_validate.h"
#include "main/api_noop.h"
-#include "glapi/dispatch.h"
#include "vbo_context.h"