diff options
667 files changed, 25041 insertions, 31920 deletions
@@ -180,7 +180,7 @@ ultrix-gcc: # Rules for making release tarballs -VERSION=7.8-rc1 +VERSION=7.9-devel DIRECTORY = Mesa-$(VERSION) LIB_NAME = MesaLib-$(VERSION) DEMO_NAME = MesaDemos-$(VERSION) @@ -215,7 +215,6 @@ MAIN_FILES = \ $(DIRECTORY)/include/GL/glx_mangle.h \ $(DIRECTORY)/include/GL/glfbdev.h \ $(DIRECTORY)/include/GL/mesa_wgl.h \ - $(DIRECTORY)/include/GL/mglmesa.h \ $(DIRECTORY)/include/GL/osmesa.h \ $(DIRECTORY)/include/GL/vms_x_fix.h \ $(DIRECTORY)/include/GL/wglext.h \ diff --git a/SConstruct b/SConstruct index e1c4a1898ce..6ed44ddd067 100644 --- a/SConstruct +++ b/SConstruct @@ -110,9 +110,11 @@ Export([ ####################################################################### # Environment setup -# Always build trace driver +# Always build trace and identity drivers if 'trace' not in env['drivers']: env['drivers'].append('trace') +if 'identity' not in env['drivers']: + env['drivers'].append('identity') # Includes env.Append(CPPPATH = [ @@ -120,6 +122,7 @@ env.Append(CPPPATH = [ '#/src/gallium/include', '#/src/gallium/auxiliary', '#/src/gallium/drivers', + '#/src/gallium/winsys', ]) if env['msvc']: diff --git a/bin/mklib b/bin/mklib index 08ef99ec105..c2760e5d892 100755 --- a/bin/mklib +++ b/bin/mklib @@ -494,13 +494,16 @@ case $ARCH in OPTS="${OPTS} -Wl,-Mmapfile.scope" fi - # Check if objects are SPARC v9 + # Check if objects are 64-bit # file says: ELF 64-bit MSB relocatable SPARCV9 Version 1 set ${OBJECTS} if [ ${LINK} = "cc" -o ${LINK} = "CC" ] ; then - SPARCV9=`file $1 | grep SPARCV9` - if [ "${SPARCV9}" ] ; then - OPTS="${OPTS} -xarch=v9" + ABI64=`file $1 | grep "ELF 64-bit"` + if [ "${ABI64}" ] ; then + case `uname -p` in + sparc) OPTS="${OPTS} -xarch=v9" ;; + i386) OPTS="${OPTS} -xarch=amd64" ;; + esac fi fi if [ "${ALTOPTS}" ] ; then diff --git a/configs/autoconf.in b/configs/autoconf.in index 30637877f3b..f50fb7dd093 100644 --- a/configs/autoconf.in +++ b/configs/autoconf.in @@ -24,6 +24,8 @@ RADEON_CFLAGS = @RADEON_CFLAGS@ RADEON_LDFLAGS = @RADEON_LDFLAGS@ INTEL_LIBS = @INTEL_LIBS@ INTEL_CFLAGS = @INTEL_CFLAGS@ +X_LIBS = @X_LIBS@ +X_CFLAGS = @X_CFLAGS@ # Assembler MESA_ASM_SOURCES = @MESA_ASM_SOURCES@ @@ -73,6 +75,7 @@ EGL_DRIVERS_DIRS = @EGL_DRIVERS_DIRS@ GALLIUM_DIRS = @GALLIUM_DIRS@ GALLIUM_DRIVERS_DIRS = @GALLIUM_DRIVERS_DIRS@ GALLIUM_WINSYS_DIRS = @GALLIUM_WINSYS_DIRS@ +GALLIUM_TARGET_DIRS = @GALLIUM_TARGET_DIRS@ GALLIUM_WINSYS_DRM_DIRS = @GALLIUM_WINSYS_DRM_DIRS@ GALLIUM_STATE_TRACKERS_DIRS = @GALLIUM_STATE_TRACKERS_DIRS@ GALLIUM_AUXILIARIES = $(TOP)/src/gallium/auxiliary/libgallium.a @@ -83,7 +86,6 @@ PROGRAM_DIRS = @PROGRAM_DIRS@ # Driver specific build vars DRI_DIRS = @DRI_DIRS@ -WINDOW_SYSTEM = @WINDOW_SYSTEM@ EGL_DISPLAYS = @EGL_DISPLAYS@ # Dependencies diff --git a/configs/default b/configs/default index ad6d93c92ff..8fbf8dd219a 100644 --- a/configs/default +++ b/configs/default @@ -9,7 +9,7 @@ CONFIG_NAME = default # Version info MESA_MAJOR=7 -MESA_MINOR=8 +MESA_MINOR=9 MESA_TINY=0 MESA_VERSION = $(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY) @@ -86,7 +86,7 @@ MOTIF_CFLAGS = -I/usr/include/Motif1.2 # Directories to build LIB_DIR = lib -SRC_DIRS = glsl mesa gallium egl gallium/winsys glu glut/glx glew glw +SRC_DIRS = glsl mesa gallium egl gallium/winsys gallium/targets glu glut/glx glew glw GLU_DIRS = sgi DRIVER_DIRS = x11 osmesa # Which subdirs under $(TOP)/progs/ to enter: @@ -100,7 +100,8 @@ GALLIUM_DIRS = auxiliary drivers state_trackers GALLIUM_AUXILIARIES = $(TOP)/src/gallium/auxiliary/libgallium.a GALLIUM_DRIVERS_DIRS = softpipe failover svga i915 i965 r300 trace identity GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVERS_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a) -GALLIUM_WINSYS_DIRS = drm xlib +GALLIUM_WINSYS_DIRS = null xlib drm +GALLIUM_TARGET_DIRS = libgl-xlib GALLIUM_WINSYS_DRM_DIRS = swrast GALLIUM_STATE_TRACKERS_DIRS = glx vega diff --git a/configs/freebsd-dri b/configs/freebsd-dri index 0b91cfc37e9..2c697e1c6e4 100644 --- a/configs/freebsd-dri +++ b/configs/freebsd-dri @@ -44,7 +44,6 @@ GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -L/usr/local/lib -lGL -lXt -lX11 SRC_DIRS = glx gallium mesa glu glut/glx glew glw DRIVER_DIRS = dri PROGRAM_DIRS = -WINDOW_SYSTEM=dri DRM_SOURCE_PATH=$(TOP)/../drm diff --git a/configs/linux-cell b/configs/linux-cell index e89a08cd934..0908dba9e05 100644 --- a/configs/linux-cell +++ b/configs/linux-cell @@ -6,7 +6,7 @@ CONFIG_NAME = linux-cell # Omiting other gallium drivers: -GALLIUM_DRIVERS_DIRS = cell softpipe trace +GALLIUM_DRIVERS_DIRS = cell softpipe trace identity # Compiler and flags @@ -37,7 +37,7 @@ CXXFLAGS = $(COMMON_C_CPP_FLAGS) # Omitting glw here: -SRC_DIRS = glsl mesa gallium gallium/winsys glu glut/glx glew +SRC_DIRS = glsl mesa gallium gallium/winsys gallium/targets glu glut/glx glew # Build no traditional Mesa drivers: DRIVER_DIRS = diff --git a/configs/linux-dri b/configs/linux-dri index e8e8ccfcf94..d362fd8b377 100644 --- a/configs/linux-dri +++ b/configs/linux-dri @@ -58,8 +58,8 @@ PROGRAM_DIRS := egl $(PROGRAM_DIRS) EGL_DRIVERS_DIRS = glx DRIVER_DIRS = dri -WINDOW_SYSTEM = dri -GALLIUM_WINSYS_DIRS = drm +GALLIUM_WINSYS_DIRS = null xlib drm +GALLIUM_TARGET_DIRS = GALLIUM_WINSYS_DRM_DIRS = vmware intel i965 GALLIUM_STATE_TRACKERS_DIRS = egl diff --git a/configs/linux-dri-xcb b/configs/linux-dri-xcb index c5ed89c4b34..1ed980aa36e 100644 --- a/configs/linux-dri-xcb +++ b/configs/linux-dri-xcb @@ -51,7 +51,5 @@ SRC_DIRS = glx gallium mesa glu glut/glx glew glw PROGRAM_DIRS = xdemos DRIVER_DIRS = dri -WINDOW_SYSTEM=dri - DRI_DIRS = i810 i915 mach64 mga r128 r200 r300 radeon \ savage sis tdfx unichrome diff --git a/configs/linux-egl b/configs/linux-egl index 2c2834b81d7..28165ed5b5a 100644 --- a/configs/linux-egl +++ b/configs/linux-egl @@ -47,11 +47,11 @@ GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \ # Directories -SRC_DIRS = gallium mesa gallium/winsys glu egl +SRC_DIRS = gallium mesa gallium/winsys gallium/targets glu egl PROGRAM_DIRS = egl DRIVER_DIRS = dri -WINDOW_SYSTEM = dri GALLIUM_WINSYS_DIRS = egl_drm +GALLIUM_TARGET_DIRS = DRI_DIRS = intel diff --git a/configs/linux-i965 b/configs/linux-i965 index e66abc347bb..7656a2adc5e 100644 --- a/configs/linux-i965 +++ b/configs/linux-i965 @@ -6,3 +6,4 @@ CONFIG_NAME = linux-i965 GALLIUM_DRIVER_DIRS = i965 GALLIUM_WINSYS_DIRS = drm/i965/xlib +GALLIUM_TARGET_DIRS = diff --git a/configs/linux-indirect b/configs/linux-indirect index 0914fba19bc..1c7dd857db6 100644 --- a/configs/linux-indirect +++ b/configs/linux-indirect @@ -50,4 +50,3 @@ GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl SRC_DIRS = glx glu glut/glx glew glw DRIVER_DIRS = PROGRAM_DIRS = -WINDOW_SYSTEM=dri diff --git a/configs/linux-opengl-es b/configs/linux-opengl-es index 259c26a931b..76054aad14e 100644 --- a/configs/linux-opengl-es +++ b/configs/linux-opengl-es @@ -6,7 +6,7 @@ CONFIG_NAME = linux-opengl-es # Directories to build LIB_DIR = lib -SRC_DIRS = egl glsl mesa/es gallium gallium/winsys +SRC_DIRS = egl glsl mesa/es gallium gallium/winsys gallium/targets PROGRAM_DIRS = es1/screen es1/xegl es2/xegl # egl st needs this diff --git a/configure.ac b/configure.ac index 61487c3905e..0f51097ef62 100644 --- a/configure.ac +++ b/configure.ac @@ -459,8 +459,8 @@ CORE_DIRS="glsl mesa" SRC_DIRS="glew" GLU_DIRS="sgi" -WINDOW_SYSTEM="" GALLIUM_DIRS="auxiliary drivers state_trackers" +GALLIUM_TARGET_DIRS="" GALLIUM_WINSYS_DIRS="" GALLIUM_WINSYS_DRM_DIRS="" GALLIUM_DRIVERS_DIRS="softpipe failover trace identity" @@ -470,12 +470,12 @@ case "$mesa_driver" in xlib) DRIVER_DIRS="x11" GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS xlib" + GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS libgl-xlib" ;; dri) SRC_DIRS="$SRC_DIRS glx" DRIVER_DIRS="dri" - WINDOW_SYSTEM="dri" - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS drm" + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS xlib drm" ;; osmesa) DRIVER_DIRS="osmesa" @@ -484,8 +484,8 @@ esac AC_SUBST([SRC_DIRS]) AC_SUBST([GLU_DIRS]) AC_SUBST([DRIVER_DIRS]) -AC_SUBST([WINDOW_SYSTEM]) AC_SUBST([GALLIUM_DIRS]) +AC_SUBST([GALLIUM_TARGET_DIRS]) AC_SUBST([GALLIUM_WINSYS_DIRS]) AC_SUBST([GALLIUM_WINSYS_DRM_DIRS]) AC_SUBST([GALLIUM_DRIVERS_DIRS]) @@ -547,7 +547,9 @@ else x11_pkgconfig=no fi dnl Use the autoconf macro if no pkg-config files -if test "$x11_pkgconfig" = no; then +if test "$x11_pkgconfig" = yes; then + PKG_CHECK_MODULES([X], [x11]) +else AC_PATH_XTRA fi @@ -1358,7 +1360,7 @@ AC_ARG_ENABLE([gallium-nouveau], [enable_gallium_nouveau=no]) if test "x$enable_gallium_nouveau" = xyes; then GALLIUM_WINSYS_DRM_DIRS="$GALLIUM_WINSYS_DRM_DIRS nouveau" - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nv30 nv40 nv50" + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50" fi dnl @@ -1426,6 +1428,7 @@ echo "" if echo "$SRC_DIRS" | grep 'gallium' >/dev/null 2>&1; then echo " Gallium: yes" echo " Gallium dirs: $GALLIUM_DIRS" + echo " Target dirs: $GALLIUM_TARGET_DIRS" echo " Winsys dirs: $GALLIUM_WINSYS_DIRS" echo " Winsys drm dirs:$GALLIUM_WINSYS_DRM_DIRS" echo " Driver dirs: $GALLIUM_DRIVERS_DIRS" diff --git a/docs/install.html b/docs/install.html index 5aea92e0b51..3962ea5c91e 100644 --- a/docs/install.html +++ b/docs/install.html @@ -361,7 +361,7 @@ To build Mesa with SCons for Windows on Linux using the MinGW crosscompiler tool This will create: </p> <ul> -<li>build/windows-x86-debug/gallium/winsys/gdi/opengl32.dll — Mesa + Gallium + softpipe, binary compatible with Windows's opengl32.dll +<li>build/windows-x86-debug/gallium/targets/libgl-gdi/opengl32.dll — Mesa + Gallium + softpipe, binary compatible with Windows's opengl32.dll <li>build/windows-x86-debug/glut/glx/glut32.dll <li>progs/build/windows-x86-debug/wgl/wglinfo.exe <li>progs/build/windows-x86-debug/trivial/tri.exe diff --git a/docs/relnotes-7.9.html b/docs/relnotes-7.9.html new file mode 100644 index 00000000000..f7d5016dc69 --- /dev/null +++ b/docs/relnotes-7.9.html @@ -0,0 +1,50 @@ +<HTML> + +<TITLE>Mesa Release Notes</TITLE> + +<head><link rel="stylesheet" type="text/css" href="mesa.css"></head> + +<BODY> + +<body bgcolor="#eeeeee"> + +<H1>Mesa 7.9 Release Notes / date TBD</H1> + +<p> +Mesa 7.9 is a new development release. +People who are concerned with stability and reliability should stick +with a previous release or wait for Mesa 7.9.1. +</p> +<p> +Mesa 7.9 implements the OpenGL 2.1 API, but the version reported by +glGetString(GL_VERSION) depends on the particular driver being used. +Some drivers don't support all the features required in OpenGL 2.1. +</p> +<p> +See the <a href="install.html">Compiling/Installing page</a> for prerequisites +for DRI hardware acceleration. +</p> + + +<h2>MD5 checksums</h2> +<pre> +tbd +</pre> + + +<h2>New features</h2> +<ul> +</ul> + + +<h2>Bug fixes</h2> +<ul> +</ul> + + +<h2>Changes</h2> +<ul> +</ul> + +</body> +</html> diff --git a/include/GL/gl_mangle.h b/include/GL/gl_mangle.h index b292840f917..43d2e896b0b 100644 --- a/include/GL/gl_mangle.h +++ b/include/GL/gl_mangle.h @@ -393,6 +393,8 @@ #define glEdgeFlagPointerListIBM MANGLE(EdgeFlagPointerListIBM) #define glEdgeFlagPointer MANGLE(EdgeFlagPointer) #define glEdgeFlagv MANGLE(EdgeFlagv) +#define glEGLImageTargetRenderbufferStorageOES MANGLE(EGLImageTargetRenderbufferStorageOES) +#define glEGLImageTargetTexture2DOES MANGLE(EGLImageTargetTexture2DOES) #define glElementPointerAPPLE MANGLE(ElementPointerAPPLE) #define glElementPointerATI MANGLE(ElementPointerATI) #define glEnableClientStateIndexedEXT MANGLE(EnableClientStateIndexedEXT) diff --git a/include/GL/glut_h.dja b/include/GL/glut_h.dja deleted file mode 100644 index e76dcb985e3..00000000000 --- a/include/GL/glut_h.dja +++ /dev/null @@ -1,340 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.1 - * Copyright (C) 1995-1998 Brian Paul - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -/* - * This header file is based on the REAL glut.h by Mark J. Kilgard. - * - * The DJGPP/ALLEGRO (DJA) GLUT implementation was written by - * Bernhard Tschirren ([email protected]) for the sole purpose - * of compiling all the sample programs (which use GLUT). Therefore, - * is NOT AT ALL a complete version of GLUT! - */ - - -#ifndef __AGLUT_H__ -#define __AGLUT_H__ - -#include <GL/gl.h> -#include <GL/glu.h> - -#define GLUTCALLBACK -#define APIENTRY -#define GLUTAPI extern - -#define GLUT_RGB 0 -#define GLUT_RGBA GLUT_RGB -#define GLUT_INDEX 1 -#define GLUT_SINGLE 0 -#define GLUT_DOUBLE 2 -#define GLUT_ACCUM 4 -#define GLUT_ALPHA 8 -#define GLUT_DEPTH 16 -#define GLUT_STENCIL 32 - -/* Mouse buttons. */ -#define GLUT_LEFT_BUTTON 0 -#define GLUT_MIDDLE_BUTTON 1 -#define GLUT_RIGHT_BUTTON 2 - -/* Mouse button state. */ -#define GLUT_DOWN 0 -#define GLUT_UP 1 - -/* function keys */ -#define GLUT_KEY_F1 1 -#define GLUT_KEY_F2 2 -#define GLUT_KEY_F3 3 -#define GLUT_KEY_F4 4 -#define GLUT_KEY_F5 5 -#define GLUT_KEY_F6 6 -#define GLUT_KEY_F7 7 -#define GLUT_KEY_F8 8 -#define GLUT_KEY_F9 9 -#define GLUT_KEY_F10 10 -#define GLUT_KEY_F11 11 -#define GLUT_KEY_F12 12 - -/* directional keys */ -#define GLUT_KEY_LEFT 100 -#define GLUT_KEY_UP 101 -#define GLUT_KEY_RIGHT 102 -#define GLUT_KEY_DOWN 103 -#define GLUT_KEY_PAGE_UP 104 -#define GLUT_KEY_PAGE_DOWN 105 -#define GLUT_KEY_HOME 106 -#define GLUT_KEY_END 107 -#define GLUT_KEY_INSERT 108 - -/* Entry/exit state. */ -#define GLUT_LEFT 0 -#define GLUT_ENTERED 1 - -/* Visibility state. */ -#define GLUT_NOT_VISIBLE 0 -#define GLUT_VISIBLE 1 - -/* Color index component selection values. */ -#define GLUT_RED 0 -#define GLUT_GREEN 1 -#define GLUT_BLUE 2 - -/* Layers for use. */ -#define GLUT_NORMAL 0 -#define GLUT_OVERLAY 1 - -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN ((void*)0) -#define GLUT_STROKE_MONO_ROMAN ((void*)1) - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 ((void*)2) -#define GLUT_BITMAP_8_BY_13 ((void*)3) -#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) -#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) -#define GLUT_BITMAP_HELVETICA_10 ((void*)6) -#define GLUT_BITMAP_HELVETICA_12 ((void*)7) -#define GLUT_BITMAP_HELVETICA_18 ((void*)8) - -/* glutGet parameters. */ -#define GLUT_WINDOW_X 100 -#define GLUT_WINDOW_Y 101 -#define GLUT_WINDOW_WIDTH 102 -#define GLUT_WINDOW_HEIGHT 103 -#define GLUT_WINDOW_BUFFER_SIZE 104 -#define GLUT_WINDOW_STENCIL_SIZE 105 -#define GLUT_WINDOW_DEPTH_SIZE 106 -#define GLUT_WINDOW_RED_SIZE 107 -#define GLUT_WINDOW_GREEN_SIZE 108 -#define GLUT_WINDOW_BLUE_SIZE 109 -#define GLUT_WINDOW_ALPHA_SIZE 110 -#define GLUT_WINDOW_ACCUM_RED_SIZE 111 -#define GLUT_WINDOW_ACCUM_GREEN_SIZE 112 -#define GLUT_WINDOW_ACCUM_BLUE_SIZE 113 -#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 114 -#define GLUT_WINDOW_DOUBLEBUFFER 115 -#define GLUT_WINDOW_RGBA 116 -#define GLUT_WINDOW_PARENT 117 -#define GLUT_WINDOW_NUM_CHILDREN 118 -#define GLUT_WINDOW_COLORMAP_SIZE 119 -#define GLUT_WINDOW_NUM_SAMPLES 120 -#define GLUT_WINDOW_STEREO 121 -#define GLUT_WINDOW_CURSOR 122 -#define GLUT_SCREEN_WIDTH 200 -#define GLUT_SCREEN_HEIGHT 201 -#define GLUT_SCREEN_WIDTH_MM 202 -#define GLUT_SCREEN_HEIGHT_MM 203 -#define GLUT_MENU_NUM_ITEMS 300 -#define GLUT_DISPLAY_MODE_POSSIBLE 400 -#define GLUT_INIT_WINDOW_X 500 -#define GLUT_INIT_WINDOW_Y 501 -#define GLUT_INIT_WINDOW_WIDTH 502 -#define GLUT_INIT_WINDOW_HEIGHT 503 -#define GLUT_INIT_DISPLAY_MODE 504 -#define GLUT_ELAPSED_TIME 700 -#define GLUT_WINDOW_FORMAT_ID 123 - -/* glutDeviceGet parameters. */ -#define GLUT_HAS_KEYBOARD 600 -#define GLUT_HAS_MOUSE 601 -#define GLUT_HAS_SPACEBALL 602 -#define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 -#define GLUT_HAS_TABLET 604 -#define GLUT_NUM_MOUSE_BUTTONS 605 -#define GLUT_NUM_SPACEBALL_BUTTONS 606 -#define GLUT_NUM_BUTTON_BOX_BUTTONS 607 -#define GLUT_NUM_DIALS 608 -#define GLUT_NUM_TABLET_BUTTONS 609 -#define GLUT_DEVICE_IGNORE_KEY_REPEAT 610 -#define GLUT_DEVICE_KEY_REPEAT 611 -#define GLUT_HAS_JOYSTICK 612 -#define GLUT_OWNS_JOYSTICK 613 -#define GLUT_JOYSTICK_BUTTONS 614 -#define GLUT_JOYSTICK_AXES 615 -#define GLUT_JOYSTICK_POLL_RATE 616 - -/* glutLayerGet parameters. */ -#define GLUT_OVERLAY_POSSIBLE 800 -#define GLUT_LAYER_IN_USE 801 -#define GLUT_HAS_OVERLAY 802 -#define GLUT_TRANSPARENT_INDEX 803 -#define GLUT_NORMAL_DAMAGED 804 -#define GLUT_OVERLAY_DAMAGED 805 - -/* glutVideoResizeGet parameters. */ -#define GLUT_VIDEO_RESIZE_POSSIBLE 900 -#define GLUT_VIDEO_RESIZE_IN_USE 901 -#define GLUT_VIDEO_RESIZE_X_DELTA 902 -#define GLUT_VIDEO_RESIZE_Y_DELTA 903 -#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 -#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 -#define GLUT_VIDEO_RESIZE_X 906 -#define GLUT_VIDEO_RESIZE_Y 907 -#define GLUT_VIDEO_RESIZE_WIDTH 908 -#define GLUT_VIDEO_RESIZE_HEIGHT 909 - -/* glutUseLayer parameters. */ -#define GLUT_NORMAL 0 -#define GLUT_OVERLAY 1 - -/* glutGetModifiers return mask. */ -#define GLUT_ACTIVE_SHIFT 1 -#define GLUT_ACTIVE_CTRL 2 -#define GLUT_ACTIVE_ALT 4 - -/* glutSetCursor parameters. */ -/* Basic arrows. */ -#define GLUT_CURSOR_RIGHT_ARROW 0 -#define GLUT_CURSOR_LEFT_ARROW 1 -/* Symbolic cursor shapes. */ -#define GLUT_CURSOR_INFO 2 -#define GLUT_CURSOR_DESTROY 3 -#define GLUT_CURSOR_HELP 4 -#define GLUT_CURSOR_CYCLE 5 -#define GLUT_CURSOR_SPRAY 6 -#define GLUT_CURSOR_WAIT 7 -#define GLUT_CURSOR_TEXT 8 -#define GLUT_CURSOR_CROSSHAIR 9 -/* Directional cursors. */ -#define GLUT_CURSOR_UP_DOWN 10 -#define GLUT_CURSOR_LEFT_RIGHT 11 -/* Sizing cursors. */ -#define GLUT_CURSOR_TOP_SIDE 12 -#define GLUT_CURSOR_BOTTOM_SIDE 13 -#define GLUT_CURSOR_LEFT_SIDE 14 -#define GLUT_CURSOR_RIGHT_SIDE 15 -#define GLUT_CURSOR_TOP_LEFT_CORNER 16 -#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 -#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 -#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 -/* Inherit from parent window. */ -#define GLUT_CURSOR_INHERIT 100 -/* Blank cursor. */ -#define GLUT_CURSOR_NONE 101 -/* Fullscreen crosshair (if available). */ -#define GLUT_CURSOR_FULL_CROSSHAIR 102 - -/* GLUT initialization sub-API. */ -GLUTAPI void APIENTRY glutInit(int *argcp, char **argv); -GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode); -GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y); -GLUTAPI void APIENTRY glutInitWindowSize(int width, int height); -GLUTAPI void APIENTRY glutMainLoop(void); - -/* GLUT window sub-API. */ -GLUTAPI int APIENTRY glutCreateWindow(const char *title); -GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); -GLUTAPI void APIENTRY glutDestroyWindow(int win); -GLUTAPI void APIENTRY glutPostRedisplay(void); -GLUTAPI void APIENTRY glutSwapBuffers(void); -GLUTAPI int APIENTRY glutGetWindow(void); -GLUTAPI void APIENTRY glutSetWindow(int win); -GLUTAPI void APIENTRY glutSetWindowTitle(const char *title); -GLUTAPI void APIENTRY glutSetIconTitle(const char *title); -GLUTAPI void APIENTRY glutPositionWindow(int x, int y); -GLUTAPI void APIENTRY glutReshapeWindow(int width, int height); -GLUTAPI void APIENTRY glutPopWindow(void); -GLUTAPI void APIENTRY glutPushWindow(void); -GLUTAPI void APIENTRY glutIconifyWindow(void); -GLUTAPI void APIENTRY glutShowWindow(void); -GLUTAPI void APIENTRY glutHideWindow(void); - -/* GLUT overlay sub-API. */ -GLUTAPI void APIENTRY glutEstablishOverlay(void); -GLUTAPI void APIENTRY glutRemoveOverlay(void); -GLUTAPI void APIENTRY glutUseLayer(GLenum layer); -GLUTAPI void APIENTRY glutPostOverlayRedisplay(void); -GLUTAPI void APIENTRY glutShowOverlay(void); -GLUTAPI void APIENTRY glutHideOverlay(void); - -/* GLUT menu sub-API. */ -GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *)(int)); -GLUTAPI void APIENTRY glutDestroyMenu(int menu); -GLUTAPI int APIENTRY glutGetMenu(void); -GLUTAPI void APIENTRY glutSetMenu(int menu); -GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value); -GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu); -GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); -GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); -GLUTAPI void APIENTRY glutRemoveMenuItem(int item); -GLUTAPI void APIENTRY glutAttachMenu(int button); -GLUTAPI void APIENTRY glutDetachMenu(int button); - -/* GLUT window callback sub-API. */ -GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK * func)(void)); -GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK * func)(int width, int height)); -GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK * func)(unsigned char key, int x, int y)); -GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK * func)(int button, int state, int x, int y)); -GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK * func)(int x, int y)); -GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK * func)(int x, int y)); -GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK * func)(int state)); -GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK * func)(int state)); -GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK * func)(void)); -GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK * func)(int value), int value); -GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK * func)(int state)); -GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK * func)(int key, int x, int y)); -GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK * func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK * func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK * func)(int button, int state)); -GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK * func)(int button, int state)); -GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK * func)(int dial, int value)); -GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK * func)(int x, int y)); -GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK * func)(int button, int state, int x, int y)); -GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK * func)(int status, int x, int y)); -GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK * func)(void)); -GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK * func)(int state)); - -/* GLUT color index sub-API. */ -GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); -GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component); -GLUTAPI void APIENTRY glutCopyColormap(int win); - -/* GLUT state retrieval sub-API. */ -GLUTAPI int APIENTRY glutGet(GLenum type); -GLUTAPI int APIENTRY glutDeviceGet(GLenum type); - -/* GLUT font sub-API */ -GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character); -GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character); -GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character); -GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character); - -/* GLUT pre-built models sub-API */ -GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCube(GLdouble size); -GLUTAPI void APIENTRY glutSolidCube(GLdouble size); -GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutWireDodecahedron(void); -GLUTAPI void APIENTRY glutSolidDodecahedron(void); -GLUTAPI void APIENTRY glutWireTeapot(GLdouble size); -GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size); -GLUTAPI void APIENTRY glutWireOctahedron(void); -GLUTAPI void APIENTRY glutSolidOctahedron(void); -GLUTAPI void APIENTRY glutWireTetrahedron(void); -GLUTAPI void APIENTRY glutSolidTetrahedron(void); -GLUTAPI void APIENTRY glutWireIcosahedron(void); -GLUTAPI void APIENTRY glutSolidIcosahedron(void); - -#endif /* __AGLUT_H__ */ diff --git a/include/GL/mglmesa.h b/include/GL/mglmesa.h deleted file mode 100644 index 0f9f7895714..00000000000 --- a/include/GL/mglmesa.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -* -* Mesa bindings for SciTech MGL -* -* Copyright (C) 1996 SciTech Software. -* All rights reserved. -* -* Filename: mglmesa.h -* Version: Revision: 1.1.1.1 -* -* Language: ANSI C -* Environment: Any -* -* Description: Header file for the Mesa/OpenGL interface bindings for the -* SciTech MGL graphics library. Uses the MGL internal -* device context structures to get direct access to the -* high performance MGL rasterization functions for maximum -* performance. Utilizes the VESA VBE/AF Accelerator Functions -* via the MGL's accelerated device driver functions, as well -* as basic DirectDraw accelerated functions provided by the -* MGL. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Library General Public -* License as published by the Free Software Foundation; either -* version 2 of the License, or (at your option) any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Library General Public License for more details. -* -* You should have received a copy of the GNU Library General Public -* License along with this library; if not, write to the Free -* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* -****************************************************************************/ - -#ifndef __MGLMESA_H -#define __MGLMESA_H - -#include "mgraph.h" - -/*------------------------- Function Prototypes ---------------------------*/ - -#ifdef __cplusplus -extern "C" { /* Use "C" linkage when in C++ mode */ -#endif - -#ifndef __WINDOWS__ -#define GLAPIENTRY -#endif - -#ifdef __WINDOWS__ -bool GLAPIENTRY MGLMesaInitDLL(MGLCallbacks *cb,char *version); -#endif -void GLAPIENTRY MGLMesaChooseVisual(MGLDC *dc,MGLVisual *visual); -bool GLAPIENTRY MGLMesaSetVisual(MGLDC *dc,MGLVisual *visual); -bool GLAPIENTRY MGLMesaCreateContext(MGLDC *dc,bool forceMemDC); -void GLAPIENTRY MGLMesaDestroyContext(MGLDC *dc); -void GLAPIENTRY MGLMesaMakeCurrent(MGLDC *dc); -void GLAPIENTRY MGLMesaSwapBuffers(MGLDC *dc,bool waitVRT); - -/* Palette manipulation support. The reason we provide palette manipulation - * routines is so that when rendering in double buffered modes with a - * software backbuffer, the palette for the backbuffer is kept consistent - * with the hardware front buffer. - */ - -void GLAPIENTRY MGLMesaSetPaletteEntry(MGLDC *dc,int entry,uchar red,uchar green,uchar blue); -void GLAPIENTRY MGLMesaSetPalette(MGLDC *dc,palette_t *pal,int numColors,int startIndex); -void GLAPIENTRY MGLMesaRealizePalette(MGLDC *dc,int numColors,int startIndex,int waitVRT); - -#ifdef __cplusplus -} /* End of "C" linkage for C++ */ -#endif /* __cplusplus */ - -#endif /* __MGLMESA_H */ diff --git a/progs/demos/stex3d.c b/progs/demos/stex3d.c index c0bbea0960f..de18480c25e 100644 --- a/progs/demos/stex3d.c +++ b/progs/demos/stex3d.c @@ -36,6 +36,7 @@ static int tex_width=64, tex_height=64, tex_depth=64; static float angx=0, angy=0, angz=0; static int texgen = 2, animate = 1, smooth = 1, wireframe = 0; static int CurTexture = NOISE_TEXTURE, CurObject = TORUS; +static GLenum Filter = GL_LINEAR; static void @@ -298,8 +299,6 @@ create3Dtexture(void) printf("setting up 3d texture...\n"); glBindTexture(GL_TEXTURE_3D, NOISE_TEXTURE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); @@ -406,6 +405,9 @@ drawScene(void) glDisable(GL_TEXTURE_GEN_R); } + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, Filter); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, Filter); + glCallList(CurObject); glPopMatrix(); @@ -505,6 +507,12 @@ KeyHandler(unsigned char key, int x, int y) else CurObject = TORUS; break; + case 'f': + if (Filter == GL_LINEAR) + Filter = GL_NEAREST; + else + Filter = GL_LINEAR; + break; case 'i': if (CurTexture == NOISE_TEXTURE) CurTexture = GRADIENT_TEXTURE; @@ -513,6 +521,7 @@ KeyHandler(unsigned char key, int x, int y) glBindTexture(GL_TEXTURE_3D, CurTexture); break; case 'a': + case ' ': animate = !animate; if (animate) glutIdleFunc(Idle); @@ -559,8 +568,6 @@ create3Dgradient(void) glBindTexture(GL_TEXTURE_3D, GRADIENT_TEXTURE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); diff --git a/progs/egl/Makefile b/progs/egl/Makefile index 25de6e1f703..5f51104fed6 100644 --- a/progs/egl/Makefile +++ b/progs/egl/Makefile @@ -57,13 +57,13 @@ peglgears: peglgears.o $(HEADERS) $(LIB_DEP) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(LIBDRM_LIB) -lm xeglgears: xeglgears.o $(HEADERS) $(LIB_DEP) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) -lm -L$(libdir) -lX11 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) -lm $(X_LIBS) xeglthreads: xeglthreads.o $(HEADERS) $(LIB_DEP) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) -lm -L$(libdir) -lX11 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) -lm $(X_LIBS) xegl_tri: xegl_tri.o $(HEADERS) $(LIB_DEP) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) -lm -L$(libdir) -lX11 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) -lm $(X_LIBS) clean: -rm -f *.o *~ diff --git a/progs/fpglsl/dowhile.glsl b/progs/fpglsl/dowhile.glsl new file mode 100644 index 00000000000..ed9d7296753 --- /dev/null +++ b/progs/fpglsl/dowhile.glsl @@ -0,0 +1,8 @@ +void main() { + float sum = 0.0; + do { + sum += 0.1; + break; + } while (true); + gl_FragColor = vec4(sum); +} diff --git a/progs/fpglsl/dowhile2.glsl b/progs/fpglsl/dowhile2.glsl new file mode 100644 index 00000000000..f3e00b8e865 --- /dev/null +++ b/progs/fpglsl/dowhile2.glsl @@ -0,0 +1,10 @@ +void main() { + float sum = 0.0; + do { + sum += 0.1; + if (sum < 0.499999) + continue; + break; + } while (true); + gl_FragColor = vec4(sum); +} diff --git a/progs/fpglsl/for.glsl b/progs/fpglsl/for.glsl new file mode 100644 index 00000000000..862ca8bd6cc --- /dev/null +++ b/progs/fpglsl/for.glsl @@ -0,0 +1,11 @@ +uniform int KernelSizeInt; + +void main() { + int i; + vec4 sum = vec4(0.0); + for (i = 0; i < KernelSizeInt; ++i) { + sum.g += 0.25; + } + sum.a = 1.0; + gl_FragColor = sum; +} diff --git a/progs/fpglsl/forbreak.glsl b/progs/fpglsl/forbreak.glsl new file mode 100644 index 00000000000..0b8d957cb04 --- /dev/null +++ b/progs/fpglsl/forbreak.glsl @@ -0,0 +1,13 @@ +uniform int KernelSizeInt; + +void main() { + int i; + vec4 sum = vec4(0.0); + for (i = 0; i < KernelSizeInt; ++i) { + sum.g += 0.25; + if (i > 0) + break; + } + sum.a = 1.0; + gl_FragColor = sum; +} diff --git a/progs/fpglsl/fp-tri.c b/progs/fpglsl/fp-tri.c index c9b08fbbad7..8af09845dd8 100644 --- a/progs/fpglsl/fp-tri.c +++ b/progs/fpglsl/fp-tri.c @@ -129,6 +129,11 @@ static void setup_uniforms() } { + GLint loci = glGetUniformLocationARB(program, "KernelSizeInt"); + if (loci >= 0) + glUniform1i(loci, 4); + } + { GLint loc1f = glGetUniformLocationARB(program, "KernelValue1f"); GLint loc2f = glGetUniformLocationARB(program, "KernelValue2f"); GLint loc4f = glGetUniformLocationARB(program, "KernelValue4f"); diff --git a/progs/fpglsl/simpleif.glsl b/progs/fpglsl/simpleif.glsl new file mode 100644 index 00000000000..922421b4108 --- /dev/null +++ b/progs/fpglsl/simpleif.glsl @@ -0,0 +1,6 @@ +void main() { + // this should always be true + if (gl_FragCoord.x >= 0.0) { + gl_FragColor = vec4(0.5, 0.0, 0.5, 1.0); + } +} diff --git a/progs/fpglsl/while.glsl b/progs/fpglsl/while.glsl new file mode 100644 index 00000000000..05fb860ddcf --- /dev/null +++ b/progs/fpglsl/while.glsl @@ -0,0 +1,7 @@ +void main() { + float sum = 0.0; + while (sum < 0.499999) { + sum += 0.1; + } + gl_FragColor = vec4(sum); +} diff --git a/progs/fpglsl/while2.glsl b/progs/fpglsl/while2.glsl new file mode 100644 index 00000000000..19c8904e283 --- /dev/null +++ b/progs/fpglsl/while2.glsl @@ -0,0 +1,9 @@ +void main() { + float sum = 0.0; + while (true) { + sum += 0.1; + if (sum > 0.8) + break; + } + gl_FragColor = vec4(sum); +} diff --git a/progs/gallium/python/retrace/interpreter.py b/progs/gallium/python/retrace/interpreter.py index b30469dfaee..1a961812553 100755 --- a/progs/gallium/python/retrace/interpreter.py +++ b/progs/gallium/python/retrace/interpreter.py @@ -551,7 +551,6 @@ class Context(Object): data = vbuf.buffer.read() values = unpack_from(format, data, offset) sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n') - assert len(values) == velem.nr_components sys.stdout.write('\t},\n') sys.stdout.flush() diff --git a/progs/gallium/unit/u_format_test.c b/progs/gallium/unit/u_format_test.c index 2dfba5538bf..5274311e035 100644 --- a/progs/gallium/unit/u_format_test.c +++ b/progs/gallium/unit/u_format_test.c @@ -30,546 +30,10 @@ #include <stdio.h> #include "util/u_format.h" +#include "util/u_format_tests.h" #include "util/u_format_pack.h" -#define MAX_PACKED_BYTES 16 - - -/** - * A (packed, unpacked) color pair. - */ -struct util_format_test_case -{ - enum pipe_format format; - - /** - * Mask of the bits that actually meaningful data. Used to mask out the - * "X" channels. - */ - uint8_t mask[MAX_PACKED_BYTES]; - - uint8_t packed[MAX_PACKED_BYTES]; - - /** - * RGBA. - */ - double unpacked[4]; -}; - - -/* - * Helper macros to create the packed bytes for longer words. - */ - -#define PACKED_1x8(x) {x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_2x8(x, y) {x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_3x8(x, y, z) {x, y, z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_4x8(x, y, z, w) {x, y, z, w, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -#define PACKED_1x16(x) {(x) & 0xff, (x) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_2x16(x, y) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_3x16(x, y, z) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_4x16(x, y, z, w) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, (w) & 0xff, (w) >> 8, 0, 0, 0, 0, 0, 0, 0, 0} - -#define PACKED_1x32(x) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_2x32(x, y) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, 0, 0, 0, 0, 0, 0, 0, 0} -#define PACKED_3x32(x, y, z) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, 0, 0, 0, 0} -#define PACKED_4x32(x, y, z, w) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, (w) & 0xff, ((w) >> 8) & 0xff, ((w) >> 16) & 0xff, (w) >> 24} - - -/** - * Test cases. - * - * These were manually entered. We could generate these - * - * To keep this to a we cover only the corner cases, which should produce - * good enough coverage since that pixel format transformations are afine for - * non SRGB formats. - */ -static const struct util_format_test_case -test_cases[] = -{ - - /* - * 32-bit rendertarget formats - */ - - {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xff000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000003ff), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000ffc00), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x3ff00000), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - /* - * 16-bit rendertarget formats - */ - - {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7c00), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00f0), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0f00), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x07e0), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf800), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, - - /* - * Luminance/intensity/alpha formats - */ - - {PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {0.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00ff), {1.0, 1.0, 1.0, 0.0}}, - {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xff00), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, - - /* - * TODO: SRGB formats - */ - - /* - * Mixed-signed formats - */ - - {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000007f), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000081), {-1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00007f00), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00008100), { 0.0, -1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), { 0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xff000000), { 0.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0011), {-1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x01e0), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0220), { 0.0, -1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0xfc00), { 0.0, 0.0, 1.0, 1.0}}, - - /* - * TODO: Depth-stencil formats - */ - - /* - * TODO: YUV formats - */ - - /* - * TODO: Compressed formats - */ - - /* - * Standard 8-bit integer formats - */ - - {PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {1.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), {1.0, 1.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0xff), {255.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), {255.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), { 0.0, 255.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), {255.0, 255.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), {255.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), { 0.0, 255.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), { 0.0, 0.0, 255.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), {255.0, 255.0, 255.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), {255.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), { 0.0, 255.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), { 0.0, 0.0, 255.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), { 0.0, 0.0, 0.0, 255.0}}, - {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), {255.0, 255.0, 255.0, 255.0}}, - - {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x7f), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x81), {-1.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x81, 0x00), {-1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x81), { 0.0, -1.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x81, 0x00, 0x00), {-1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x81, 0x00), { 0.0, -1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), { 0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x81), { 0.0, 0.0, -1.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), { 1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x81, 0x00, 0x00, 0x00), {-1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), { 0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x81, 0x00, 0x00), { 0.0, -1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), { 0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x81, 0x00), { 0.0, 0.0, -1.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x81), { 0.0, 0.0, 0.0, -1.0}}, - - {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x7f), { 127.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x80), {-128.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), { 127.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x80, 0x00), {-128.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), { 0.0, 127.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x80), { 0.0, -128.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), { 127.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x80, 0x00, 0x00), {-128.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), { 0.0, 127.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x80, 0x00), { 0.0, -128.0, 0.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), { 0.0, 0.0, 127.0, 1.0}}, - {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x80), { 0.0, 0.0, -128.0, 1.0}}, - - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), { 127.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x00, 0x00, 0x00), {-128.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), { 0.0, 127.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x80, 0x00, 0x00), { 0.0, -128.0, 0.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), { 0.0, 0.0, 127.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x80, 0x00), { 0.0, 0.0, -128.0, 0.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), { 0.0, 0.0, 0.0, 127.0}}, - {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x80), { 0.0, 0.0, 0.0, -128.0}}, - - /* - * Standard 16-bit integer formats - */ - - {PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), {1.0, 1.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {65535.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), {65535.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), { 0.0, 65535.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), {65535.0, 65535.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), {65535.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), { 0.0, 65535.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), { 0.0, 0.0, 65535.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), {65535.0, 65535.0, 65535.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), {65535.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), { 0.0, 65535.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), { 0.0, 0.0, 65535.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), { 0.0, 0.0, 0.0, 65535.0}}, - {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), {65535.0, 65535.0, 65535.0, 65535.0}}, - - {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8001), { -1.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8001, 0x0000), { -1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8001), { 0.0, -1.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8001, 0x0000, 0x0000), { -1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8001, 0x0000), { 0.0, -1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8001), { 0.0, 0.0, -1.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), { 1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8001, 0x0000, 0x0000, 0x0000), { -1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), { 0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8001, 0x0000, 0x0000), { 0.0, -1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), { 0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8001, 0x0000), { 0.0, 0.0, -1.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8001), { 0.0, 0.0, 0.0, -1.0}}, - - {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), { 32767.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x8000), {-32768.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), { 32767.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8000, 0x0000), {-32768.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), { 0.0, 32767.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8000), { 0.0, -32768.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), { 32767.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8000, 0x0000, 0x0000), {-32768.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), { 0.0, 32767.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8000, 0x0000), { 0.0, -32768.0, 0.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 32767.0, 1.0}}, - {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8000), { 0.0, 0.0, -32768.0, 1.0}}, - - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), { 32767.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8000, 0x0000, 0x0000, 0x0000), {-32768.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), { 0.0, 32767.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8000, 0x0000, 0x0000), { 0.0, -32768.0, 0.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), { 0.0, 0.0, 32767.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8000, 0x0000), { 0.0, 0.0, -32768.0, 0.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 0.0, 32767.0}}, - {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8000), { 0.0, 0.0, 0.0, -32768.0}}, - - /* - * Standard 32-bit integer formats - * - * NOTE: We can't accurately represent integers larger than +/-0x1000000 - * with single precision floats, so that's as far as we test. - */ - - {PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0x00000000), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xffffffff), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0xffffffff), {1.0, 1.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0x00000000, 0x00000000), {1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xffffffff, 0x00000000), {0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xffffffff), {0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), {0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0x00000000, 0x00000000, 0x00000000), {1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xffffffff, 0x00000000, 0x00000000), {0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xffffffff, 0x00000000), {0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xffffffff), {0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), {1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), {16777216.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), {16777216.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), { 0.0, 16777216.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x01000000), {16777216.0, 16777216.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), {16777216.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), { 0.0, 16777216.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 16777216.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x01000000, 0x01000000), {16777216.0, 16777216.0, 16777216.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), {16777216.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), { 0.0, 16777216.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), { 0.0, 0.0, 16777216.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 0.0, 16777216.0}}, - {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x01000000, 0x01000000, 0x01000000), {16777216.0, 16777216.0, 16777216.0, 16777216.0}}, - - {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x7fffffff), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x80000001), { -1.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x7fffffff, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x80000001, 0x00000000), { -1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x7fffffff), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x80000001), { 0.0, -1.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x7fffffff, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x80000001, 0x00000000, 0x00000000), { -1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x7fffffff, 0x00000000), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x80000001, 0x00000000), { 0.0, -1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x7fffffff), { 0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x80000001), { 0.0, 0.0, -1.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x7fffffff, 0x00000000, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x80000001, 0x00000000, 0x00000000, 0x00000000), { -1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x7fffffff, 0x00000000, 0x00000000), { 0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x80000001, 0x00000000, 0x00000000), { 0.0, -1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x7fffffff, 0x00000000), { 0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x80000001, 0x00000000), { 0.0, 0.0, -1.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x7fffffff), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x80000001), { 0.0, 0.0, 0.0, -1.0}}, - - {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), { 16777216.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {-16777216.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), { 16777216.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xff000000, 0x00000000), {-16777216.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), { 0.0, 16777216.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xff000000), { 0.0, -16777216.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), { 16777216.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xff000000, 0x00000000, 0x00000000), {-16777216.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), { 0.0, 16777216.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xff000000, 0x00000000), { 0.0, -16777216.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 16777216.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xff000000), { 0.0, 0.0, -16777216.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), { 16777216.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xff000000, 0x00000000, 0x00000000, 0x00000000), {-16777216.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), { 0.0, 16777216.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xff000000, 0x00000000, 0x00000000), { 0.0, -16777216.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), { 0.0, 0.0, 16777216.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xff000000, 0x00000000), { 0.0, 0.0, -16777216.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 0.0, 16777216.0}}, - {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xff000000), { 0.0, 0.0, 0.0, -16777216.0}}, - - /* - * Standard 32-bit float formats - */ - - {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x3f800000), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0xbf800000), { -1.0, 0.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xbf800000, 0x00000000), {-1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x3f800000), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xbf800000), { 0.0, -1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x3f800000), { 1.0, 1.0, 0.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xbf800000, 0x00000000, 0x00000000), {-1.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x3f800000, 0x00000000), { 0.0, 1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xbf800000, 0x00000000), { 0.0, -1.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x3f800000), { 0.0, 0.0, 1.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xbf800000), { 0.0, 0.0, -1.0, 1.0}}, - {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x3f800000, 0x3f800000), { 1.0, 1.0, 1.0, 1.0}}, - - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x00000000, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xbf800000, 0x00000000, 0x00000000, 0x00000000), {-1.0, 0.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x3f800000, 0x00000000, 0x00000000), { 0.0, 1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xbf800000, 0x00000000, 0x00000000), { 0.0, -1.0, 0.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x3f800000, 0x00000000), { 0.0, 0.0, 1.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xbf800000, 0x00000000), { 0.0, 0.0, -1.0, 0.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x3f800000), { 0.0, 0.0, 0.0, 1.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xbf800000), { 0.0, 0.0, 0.0, -1.0}}, - {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000), { 1.0, 1.0, 1.0, 1.0}}, -}; - - static boolean test_format_unpack_4f(const struct util_format_test_case *test) { @@ -596,7 +60,7 @@ test_format_unpack_4f(const struct util_format_test_case *test) static boolean test_format_pack_4f(const struct util_format_test_case *test) { - uint8_t packed[MAX_PACKED_BYTES]; + uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; unsigned i; boolean success; @@ -605,7 +69,7 @@ test_format_pack_4f(const struct util_format_test_case *test) util_format_pack_4f(test->format, packed, test->unpacked[0], test->unpacked[1], test->unpacked[2], test->unpacked[3]); success = TRUE; - for (i = 0; i < MAX_PACKED_BYTES; ++i) + for (i = 0; i < UTIL_FORMAT_MAX_PACKED_BYTES; ++i) if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i])) success = FALSE; @@ -627,13 +91,27 @@ test_format_pack_4f(const struct util_format_test_case *test) } -static void +static boolean convert_4f_to_4ub(uint8_t *dst, const double *src) { unsigned i; + boolean accurate = TRUE; - for (i = 0; i < 4; ++i) - dst[i] = CLAMP(src[i], 0.0, 1.0) * 255.0; + for (i = 0; i < 4; ++i) { + if (src[i] < 0.0) { + accurate = FALSE; + dst[i] = 0; + } + else if (src[i] > 1.0) { + accurate = FALSE; + dst[i] = 255; + } + else { + dst[i] = src[i] * 255.0; + } + } + + return accurate; } @@ -667,18 +145,23 @@ static boolean test_format_pack_4ub(const struct util_format_test_case *test) { uint8_t unpacked[4]; - uint8_t packed[MAX_PACKED_BYTES]; + uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; unsigned i; boolean success; - convert_4f_to_4ub(unpacked, test->unpacked); + if (!convert_4f_to_4ub(unpacked, test->unpacked)) { + /* + * Skip test cases which cannot be represented by four unorm bytes. + */ + return TRUE; + } memset(packed, 0, sizeof packed); util_format_pack_4ub(test->format, packed, unpacked[0], unpacked[1], unpacked[2], unpacked[3]); success = TRUE; - for (i = 0; i < MAX_PACKED_BYTES; ++i) + for (i = 0; i < UTIL_FORMAT_MAX_PACKED_BYTES; ++i) if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i])) success = FALSE; @@ -711,15 +194,16 @@ test_one(test_func_t func, const char *suffix) unsigned i; bool success = TRUE; - for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) { - if (test_cases[i].format != last_format) { + for (i = 0; i < util_format_nr_test_cases; ++i) { + const struct util_format_test_case *test = &util_format_test_cases[i]; + if (test->format != last_format) { const struct util_format_description *format_desc; - format_desc = util_format_description(test_cases[i].format); - printf("Testing %s.%s ...\n", format_desc->name, suffix); - last_format = test_cases[i].format; + format_desc = util_format_description(test->format); + printf("Testing util_format_%s_%s ...\n", format_desc->short_name, suffix); + last_format = test->format; } - if (!func(&test_cases[i])) + if (!func(&util_format_test_cases[i])) success = FALSE; } diff --git a/progs/objviewer/skybox.c b/progs/objviewer/skybox.c index 4e30742e208..93331b9c168 100644 --- a/progs/objviewer/skybox.c +++ b/progs/objviewer/skybox.c @@ -88,9 +88,9 @@ LoadSkyBoxCubeTexture(const char *filePosX, return 0; if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE)) return 0; - if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, 1+GL_FALSE, GL_TRUE)) + if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, GL_TRUE, GL_TRUE)) return 0; - if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, 1+GL_FALSE, GL_TRUE)) + if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, GL_TRUE, GL_TRUE)) return 0; if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE)) return 0; diff --git a/progs/samples/loadppm.c b/progs/samples/loadppm.c index be056d62940..adae9b491e4 100644 --- a/progs/samples/loadppm.c +++ b/progs/samples/loadppm.c @@ -9,7 +9,7 @@ static PPMImage *LoadPPM(const char *filename) char buff[16]; PPMImage *result; FILE *fp; - int maxval; + int maxval, w, h; fp = fopen(filename, "rb"); if (!fp) @@ -37,11 +37,13 @@ static PPMImage *LoadPPM(const char *filename) exit(1); } - if (fscanf(fp, "%lu %lu", &result->sizeX, &result->sizeY) != 2) + if (fscanf(fp, "%d %d", &w, &h) != 2) { fprintf(stderr, "Error loading image `%s'\n", filename); exit(1); } + result->sizeX = w; + result->sizeY = h; if (fscanf(fp, "%d", &maxval) != 1) { diff --git a/progs/tests/fbotest1.c b/progs/tests/fbotest1.c index 0cd7f95c355..a95fdff74c3 100644 --- a/progs/tests/fbotest1.c +++ b/progs/tests/fbotest1.c @@ -36,8 +36,8 @@ Display( void ) /* draw to user framebuffer */ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -161,7 +161,7 @@ Init( void ) assert(i == MyFB); CheckError(__LINE__); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, MyRB); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); diff --git a/progs/tests/fbotest2.c b/progs/tests/fbotest2.c index f9c506193f6..faf0dd87484 100644 --- a/progs/tests/fbotest2.c +++ b/progs/tests/fbotest2.c @@ -33,15 +33,16 @@ CheckError(int line) static void Display( void ) { - GLubyte *buffer = malloc(Width * Height * 4); + GLboolean copyPix = GL_FALSE; + GLboolean blitPix = GL_FALSE; GLenum status; CheckError(__LINE__); /* draw to user framebuffer */ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -63,16 +64,43 @@ Display( void ) glutSolidTeapot(2.0); glPopMatrix(); - /* read from user framebuffer */ - glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + if (copyPix) { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, MyFB); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glDrawBuffer(GL_BACK); - /* draw to window */ - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDisable(GL_DEPTH_TEST); /* in case window has depth buffer */ - glWindowPos2iARB(0, 0); - glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + glDisable(GL_DEPTH_TEST); /* in case window has depth buffer */ + + glWindowPos2iARB(0, 0); + glCopyPixels(0, 0, Width, Height, GL_COLOR); + } + else if (blitPix) { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, MyFB); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glDrawBuffer(GL_BACK); + + glDisable(GL_DEPTH_TEST); /* in case window has depth buffer */ + + glBlitFramebufferEXT(0, 0, Width, Height, + 0, 0, Width, Height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else { + GLubyte *buffer = malloc(Width * Height * 4); + /* read from user framebuffer */ + glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + /* draw to window */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDisable(GL_DEPTH_TEST); /* in case window has depth buffer */ + glWindowPos2iARB(0, 0); + glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + free(buffer); + } - free(buffer); glutSwapBuffers(); CheckError(__LINE__); } @@ -163,7 +191,7 @@ Init( void ) glGenRenderbuffersEXT(1, &ColorRb); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb); assert(glIsRenderbufferEXT(ColorRb)); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, ColorRb); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); diff --git a/progs/tests/fbotest3.c b/progs/tests/fbotest3.c index 8e288b38b83..c176f82d2ba 100644 --- a/progs/tests/fbotest3.c +++ b/progs/tests/fbotest3.c @@ -50,8 +50,8 @@ Display( void ) /* draw to user framebuffer */ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -189,7 +189,7 @@ Init( void ) glGenRenderbuffersEXT(1, &ColorRb); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb); assert(glIsRenderbufferEXT(ColorRb)); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, ColorRb); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); diff --git a/progs/trivial/Makefile b/progs/trivial/Makefile index b4a903cb68f..a10748f9487 100644 --- a/progs/trivial/Makefile +++ b/progs/trivial/Makefile @@ -11,6 +11,7 @@ include $(TOP)/configs/current LIBS = -L$(TOP)/$(LIB_DIR) -l $(GLEW_LIB) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) $(APP_LIB_DEPS) SOURCES = \ + clear-fbo-scissor.c \ clear-fbo-tex.c \ clear-fbo.c \ clear-scissor.c \ diff --git a/progs/trivial/SConscript b/progs/trivial/SConscript index f480da047eb..24b4f91fb0a 100644 --- a/progs/trivial/SConscript +++ b/progs/trivial/SConscript @@ -1,7 +1,8 @@ Import('*') progs = [ - 'clear-fbo-tex', + 'clear-fbo-scissor', + 'clear-fbo-tex', 'clear-fbo', 'clear-scissor', 'clear-undefined', diff --git a/progs/trivial/clear-fbo-scissor.c b/progs/trivial/clear-fbo-scissor.c new file mode 100644 index 00000000000..6a605e16a8b --- /dev/null +++ b/progs/trivial/clear-fbo-scissor.c @@ -0,0 +1,234 @@ +/* + * Use scissor to clear the four quadrants of the FBO to different + * colors. Then draw a grey triangle in the middle. + */ + + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <GL/glew.h> +#include <GL/glut.h> +#include <GL/glu.h> + + +static int Width = 512, Height = 512; +static GLuint MyFB, MyRB; +static GLboolean UseTex = GL_FALSE; +static GLboolean UseCopyPix = GL_FALSE; + + +#define CheckError() \ + do { \ + GLenum err = glGetError(); \ + if (err != GL_NO_ERROR) \ + printf("Error: %s\n", gluErrorString(err)); \ + assert(err == GL_NO_ERROR); \ + } while (0) + + +static void +Init(void) +{ + GLenum status; + + fprintf(stderr, "GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + fprintf(stderr, "GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); + fprintf(stderr, "GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); + fflush(stderr); + + if (!glutExtensionSupported("GL_EXT_framebuffer_object")) { + printf("GL_EXT_framebuffer_object not found!\n"); + exit(0); + } + + glGenFramebuffersEXT(1, &MyFB); + glGenRenderbuffersEXT(1, &MyRB); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); + + if (UseTex) { + GLuint tex; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, tex, 0); + } + else { + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, MyRB); + + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_RENDERBUFFER_EXT, MyRB); + + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); + } + + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + fprintf(stderr, "Framebuffer object is incomplete (0x%x)!\n", status); + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + + +static void +Reshape(int width, int height) +{ + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + + Width = width; + Height = height; + if (!UseTex) { + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); + } +} + + +static void +Key(unsigned char key, int x, int y) +{ + if (key == 27) { + exit(0); + } + glutPostRedisplay(); +} + + +static void +Draw(void) +{ + GLboolean scissor = GL_TRUE; + + /* draw to user framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + + glViewport(0, 0, Width, Height); + CheckError(); + + if (scissor) { + glEnable(GL_SCISSOR_TEST); + + /* lower-left = red */ + glClearColor(1, 0, 0, 0); + glScissor(0, 0, Width / 2, Height / 2); + glClear(GL_COLOR_BUFFER_BIT); + + /* lower-right = green */ + glClearColor(0, 1, 0, 0); + glScissor(Width / 2, 0, Width - Width / 2, Height / 2); + glClear(GL_COLOR_BUFFER_BIT); + + /* upper-left = blue */ + glClearColor(0, 0, 1, 0); + glScissor(0, Height / 2, Width / 2, Height - Height / 2); + glClear(GL_COLOR_BUFFER_BIT); + + /* upper-right = white */ + glClearColor(1, 1, 1, 0); + glScissor(Width / 2, Height / 2, Width - Width / 2, Height - Height / 2); + glClear(GL_COLOR_BUFFER_BIT); + + glDisable(GL_SCISSOR_TEST); + } + else { + glClearColor(0, 1, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + } + + CheckError(); + + /* gray triangle in middle, pointing up */ + glColor3f(0.5, 0.5, 0.5); + glBegin(GL_TRIANGLES); + glVertex2f(Width/4, Height/4); + glVertex2f(Width*3/4, Height/4); + glVertex2f(Width/2, Height*3/4); + glVertex2f(-0.5, -0.5); + glVertex2f(+0.5, -0.5); + glVertex2f( 0.0, 0.7); + glEnd(); + + CheckError(); + + /* copy fbo to window */ + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, MyFB); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glDrawBuffer(GL_BACK); + + if (UseCopyPix) { + glWindowPos2i(0, 0); + glCopyPixels(0, 0, Width, Height, GL_COLOR); + } + else { + GLubyte *buffer = malloc(Width * Height * 4); + + /* read from user framebuffer */ + glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + /* draw to window */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glWindowPos2iARB(0, 0); + glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + free(buffer); + } + + /* Bind normal framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + glutSwapBuffers(); + + CheckError(); +} + + +int +main(int argc, char *argv[]) +{ + int i; + + glutInit(&argc, argv); + glutInitWindowPosition(100, 0); + glutInitWindowSize(Width, Height); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-t") == 0) + UseTex = GL_TRUE; + else if (strcmp(argv[i], "-c") == 0) + UseCopyPix = GL_TRUE; + } + + if (UseTex) + printf("Using render to texture\n"); + else + printf("Using user-created render buffer\n"); + + if (!glutCreateWindow(argv[0])) { + exit(1); + } + + glewInit(); + Init(); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Draw); + glutMainLoop(); + return 0; +} diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile index e87d55d011e..f81aafe00f6 100644 --- a/progs/xdemos/Makefile +++ b/progs/xdemos/Makefile @@ -9,9 +9,9 @@ INCDIR = $(TOP)/include LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) # Add X11 and pthread libs to satisfy GNU gold. -APP_LIB_DEPS += -lX11 -lpthread +APP_LIB_DEPS += $(X_LIBS) -lpthread -LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -L$(libdir) $(APP_LIB_DEPS) +LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) $(APP_LIB_DEPS) PROGS = \ corender \ diff --git a/progs/xdemos/omlsync.c b/progs/xdemos/omlsync.c index a2baf4ad720..061d6c68613 100644 --- a/progs/xdemos/omlsync.c +++ b/progs/xdemos/omlsync.c @@ -249,11 +249,13 @@ int main(int argc, char *argv[]) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glRectf(0, 0, width, height); - glXSwapBuffersMscOML(disp, winGL, 0, divisor, remainder); - - if (wait_interval) { + if (!wait_interval) + glXSwapBuffersMscOML(disp, winGL, 0, divisor, + remainder); + else { glXWaitForMscOML(disp, winGL, msc + wait_interval, - 0, 0, &ust, &msc, &sbc); + divisor, remainder, &ust, &msc, &sbc); + glXSwapBuffersMscOML(disp, winGL, 0, 0, 0); } } diff --git a/scons/llvm.py b/scons/llvm.py index 37c503ec986..01eae2403a7 100644 --- a/scons/llvm.py +++ b/scons/llvm.py @@ -29,7 +29,9 @@ Tool-specific initialization for LLVM import os import os.path +import re import sys +import distutils.version import SCons.Errors import SCons.Util @@ -60,71 +62,98 @@ def generate(env): if env['platform'] == 'windows': # XXX: There is no llvm-config on Windows, so assume a standard layout - if llvm_dir is not None: - env.Prepend(CPPPATH = [os.path.join(llvm_dir, 'include')]) - env.AppendUnique(CPPDEFINES = [ - '__STDC_LIMIT_MACROS', - '__STDC_CONSTANT_MACROS', - 'HAVE_STDINT_H', + if llvm_dir is None: + return + + # Try to determine the LLVM version from llvm/Config/config.h + llvm_config = os.path.join(llvm_dir, 'include/llvm/Config/config.h') + if not os.path.exists(llvm_config): + print 'scons: could not find %s' % llvm_config + return + llvm_version_re = re.compile(r'^#define PACKAGE_VERSION "([^"]*)"') + llvm_version = None + for line in open(llvm_config, 'rt'): + mo = llvm_version_re.match(line) + if mo: + llvm_version = mo.group(1) + llvm_version = distutils.version.LooseVersion(llvm_version) + break + if llvm_version is None: + print 'scons: could not determine the LLVM version from %s' % llvm_config + return + + env.Prepend(CPPPATH = [os.path.join(llvm_dir, 'include')]) + env.AppendUnique(CPPDEFINES = [ + '__STDC_LIMIT_MACROS', + '__STDC_CONSTANT_MACROS', + 'HAVE_STDINT_H', + ]) + env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')]) + if llvm_version >= distutils.version.LooseVersion('2.7'): + # 2.7 + env.Prepend(LIBS = [ + 'LLVMLinker', 'LLVMipo', 'LLVMInterpreter', + 'LLVMInstrumentation', 'LLVMJIT', 'LLVMExecutionEngine', + 'LLVMBitWriter', 'LLVMX86Disassembler', 'LLVMX86AsmParser', + 'LLVMMCParser', 'LLVMX86AsmPrinter', 'LLVMX86CodeGen', + 'LLVMSelectionDAG', 'LLVMX86Info', 'LLVMAsmPrinter', + 'LLVMCodeGen', 'LLVMScalarOpts', 'LLVMInstCombine', + 'LLVMTransformUtils', 'LLVMipa', 'LLVMAsmParser', + 'LLVMArchive', 'LLVMBitReader', 'LLVMAnalysis', 'LLVMTarget', + 'LLVMMC', 'LLVMCore', 'LLVMSupport', 'LLVMSystem', ]) - env.Prepend(LIBPATH = [os.path.join(llvm_dir, 'lib')]) + else: + # 2.6 env.Prepend(LIBS = [ - 'LLVMX86AsmParser', - 'LLVMX86AsmPrinter', - 'LLVMX86CodeGen', - 'LLVMX86Info', - 'LLVMLinker', - 'LLVMipo', - 'LLVMInterpreter', - 'LLVMInstrumentation', - 'LLVMJIT', - 'LLVMExecutionEngine', - 'LLVMDebugger', - 'LLVMBitWriter', - 'LLVMAsmParser', - 'LLVMArchive', - 'LLVMBitReader', - 'LLVMSelectionDAG', - 'LLVMAsmPrinter', - 'LLVMCodeGen', - 'LLVMScalarOpts', - 'LLVMTransformUtils', - 'LLVMipa', - 'LLVMAnalysis', - 'LLVMTarget', - 'LLVMMC', - 'LLVMCore', - 'LLVMSupport', + 'LLVMX86AsmParser', 'LLVMX86AsmPrinter', 'LLVMX86CodeGen', + 'LLVMX86Info', 'LLVMLinker', 'LLVMipo', 'LLVMInterpreter', + 'LLVMInstrumentation', 'LLVMJIT', 'LLVMExecutionEngine', + 'LLVMDebugger', 'LLVMBitWriter', 'LLVMAsmParser', + 'LLVMArchive', 'LLVMBitReader', 'LLVMSelectionDAG', + 'LLVMAsmPrinter', 'LLVMCodeGen', 'LLVMScalarOpts', + 'LLVMTransformUtils', 'LLVMipa', 'LLVMAnalysis', + 'LLVMTarget', 'LLVMMC', 'LLVMCore', 'LLVMSupport', 'LLVMSystem', - 'imagehlp', - 'psapi', ]) - if env['msvc']: - # Some of the LLVM C headers use the inline keyword without - # defining it. - env.Append(CPPDEFINES = [('inline', '__inline')]) - if env['debug']: - # LLVM libraries are static, build with /MT, and they - # automatically link agains LIBCMT. When we're doing a - # debug build we'll be linking against LIBCMTD, so disable - # that. - env.Append(LINKFLAGS = ['/nodefaultlib:LIBCMT']) - env['LLVM_VERSION'] = '2.6' - return + env.Append(LIBS = [ + 'imagehlp', + 'psapi', + ]) + if env['msvc']: + # Some of the LLVM C headers use the inline keyword without + # defining it. + env.Append(CPPDEFINES = [('inline', '__inline')]) + if env['debug']: + # LLVM libraries are static, build with /MT, and they + # automatically link agains LIBCMT. When we're doing a + # debug build we'll be linking against LIBCMTD, so disable + # that. + env.Append(LINKFLAGS = ['/nodefaultlib:LIBCMT']) elif env.Detect('llvm-config'): - version = env.backtick('llvm-config --version').rstrip() + llvm_version = env.backtick('llvm-config --version').rstrip() + llvm_version = distutils.version.LooseVersion(llvm_version) try: env.ParseConfig('llvm-config --cppflags') env.ParseConfig('llvm-config --libs jit interpreter nativecodegen bitwriter') env.ParseConfig('llvm-config --ldflags') except OSError: - print 'llvm-config version %s failed' % version + print 'llvm-config version %s failed' % llvm_version else: - if env['platform'] == 'windows': - env.Append(LIBS = ['imagehlp', 'psapi']) env['LINK'] = env['CXX'] - env['LLVM_VERSION'] = version + else: + return + + assert llvm_version is not None + + print 'scons: Found LLVM version %s' % llvm_version + env['LLVM_VERSION'] = llvm_version + + # Define HAVE_LLVM macro with the major/minor version number (e.g., 0x0206 for 2.6) + llvm_version_major = int(llvm_version.version[0]) + llvm_version_minor = int(llvm_version.version[1]) + llvm_version_hex = '0x%02x%02x' % (llvm_version_major, llvm_version_minor) + env.Prepend(CPPDEFINES = [('HAVE_LLVM', llvm_version_hex)]) def exists(env): return True diff --git a/src/SConscript b/src/SConscript index cd4896ada40..cf6db730da2 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,13 +1,12 @@ Import('*') SConscript('glsl/SConscript') -SConscript('gallium/SConscript') if 'mesa' in env['statetrackers']: - SConscript('mesa/SConscript') + SConscript('mesa/SConscript') -SConscript('gallium/winsys/SConscript') +SConscript('gallium/SConscript') if platform != 'embedded': - SConscript('glut/glx/SConscript') - SConscript('glew/SConscript') + SConscript('glut/glx/SConscript') + SConscript('glew/SConscript') diff --git a/src/gallium/SConscript b/src/gallium/SConscript index d56c5c84617..c833d83e65b 100644 --- a/src/gallium/SConscript +++ b/src/gallium/SConscript @@ -7,6 +7,9 @@ SConscript('auxiliary/SConscript') for driver in env['drivers']: SConscript(os.path.join('drivers', driver, 'SConscript')) +# Needed by some state trackers +SConscript('winsys/null/SConscript') + SConscript('state_trackers/python/SConscript') if platform != 'embedded': SConscript('state_trackers/glx/xlib/SConscript') @@ -15,3 +18,7 @@ if platform != 'embedded': if platform == 'windows': SConscript('state_trackers/wgl/SConscript') + +SConscript('winsys/SConscript') + +SConscript('targets/SConscript') diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 1d0930e024b..e1c3bc43a24 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -107,6 +107,7 @@ C_SOURCES = \ util/u_draw_quad.c \ util/u_format_access.c \ util/u_format_table.c \ + util/u_format_tests.c \ util/u_gen_mipmap.c \ util/u_handle_table.c \ util/u_hash_table.c \ @@ -118,6 +119,7 @@ C_SOURCES = \ util/u_mm.c \ util/u_rect.c \ util/u_ringbuffer.c \ + util/u_sampler.c \ util/u_simple_shaders.c \ util/u_snprintf.c \ util/u_surface.c \ @@ -126,11 +128,14 @@ C_SOURCES = \ util/u_timed_winsys.c \ util/u_upload_mgr.c \ util/u_simple_screen.c \ - vl/vl_bitstream_parser.c \ - vl/vl_mpeg12_mc_renderer.c \ - vl/vl_compositor.c \ - vl/vl_csc.c \ - vl/vl_shader_build.c + target-helpers/wrap_screen.c + + # Disabling until pipe-video branch gets merged in + #vl/vl_bitstream_parser.c \ + #vl/vl_mpeg12_mc_renderer.c \ + #vl/vl_compositor.c \ + #vl/vl_csc.c \ + #vl/vl_shader_build.c \ GALLIVM_SOURCES = \ gallivm/lp_bld_alpha.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index f365c4bbdd6..65e1dc8a58d 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -7,6 +7,8 @@ env.Append(CPPPATH = [ 'util', ]) +env.Tool('udis86') + env.CodeGenerate( target = 'indices/u_indices_gen.c', script = 'indices/u_indices_gen.py', @@ -149,6 +151,7 @@ source = [ 'util/u_draw_quad.c', 'util/u_format_access.c', 'util/u_format_table.c', + 'util/u_format_tests.c', 'util/u_gen_mipmap.c', 'util/u_handle_table.c', 'util/u_hash.c', @@ -159,6 +162,7 @@ source = [ 'util/u_mm.c', 'util/u_rect.c', 'util/u_ringbuffer.c', + 'util/u_sampler.c', 'util/u_simple_shaders.c', 'util/u_snprintf.c', 'util/u_surface.c', @@ -167,11 +171,13 @@ source = [ 'util/u_timed_winsys.c', 'util/u_upload_mgr.c', 'util/u_simple_screen.c', - 'vl/vl_bitstream_parser.c', - 'vl/vl_mpeg12_mc_renderer.c', - 'vl/vl_compositor.c', - 'vl/vl_csc.c', - 'vl/vl_shader_build.c', + # Disabling until pipe-video branch gets merged in + #'vl/vl_bitstream_parser.c', + #'vl/vl_mpeg12_mc_renderer.c', + #'vl/vl_compositor.c', + #'vl/vl_csc.c', + #'vl/vl_shader_build.c', + 'target-helpers/wrap_screen.c', ] if drawllvm: diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.c b/src/gallium/auxiliary/cso_cache/cso_cache.c index a6a07e72c2f..900c64df4b9 100644 --- a/src/gallium/auxiliary/cso_cache/cso_cache.c +++ b/src/gallium/auxiliary/cso_cache/cso_cache.c @@ -43,6 +43,7 @@ struct cso_cache { struct cso_hash *vs_hash; struct cso_hash *rasterizer_hash; struct cso_hash *sampler_hash; + struct cso_hash *velements_hash; int max_size; cso_sanitize_callback sanitize_cb; @@ -108,6 +109,9 @@ static struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_ case CSO_VERTEX_SHADER: hash = sc->vs_hash; break; + case CSO_VELEMENTS: + hash = sc->velements_hash; + break; } return hash; @@ -161,6 +165,13 @@ static void delete_vs_state(void *state, void *data) FREE(state); } +static void delete_velements(void *state, void *data) +{ + struct cso_velements *cso = (struct cso_velements *)state; + if (cso->delete_state) + cso->delete_state(cso->context, cso->data); + FREE(state); +} static INLINE void delete_cso(void *state, enum cso_cache_type type) { @@ -183,6 +194,9 @@ static INLINE void delete_cso(void *state, enum cso_cache_type type) case CSO_VERTEX_SHADER: delete_vs_state(state, 0); break; + case CSO_VELEMENTS: + delete_velements(state, 0); + break; default: assert(0); FREE(state); @@ -294,6 +308,7 @@ struct cso_cache *cso_cache_create(void) sc->rasterizer_hash = cso_hash_create(); sc->fs_hash = cso_hash_create(); sc->vs_hash = cso_hash_create(); + sc->velements_hash = cso_hash_create(); sc->sanitize_cb = sanitize_cb; sc->sanitize_data = 0; @@ -325,6 +340,9 @@ void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type, case CSO_VERTEX_SHADER: hash = sc->vs_hash; break; + case CSO_VELEMENTS: + hash = sc->velements_hash; + break; } iter = cso_hash_first_node(hash); @@ -351,6 +369,7 @@ void cso_cache_delete(struct cso_cache *sc) cso_for_each_state(sc, CSO_VERTEX_SHADER, delete_vs_state, 0); cso_for_each_state(sc, CSO_RASTERIZER, delete_rasterizer_state, 0); cso_for_each_state(sc, CSO_SAMPLER, delete_sampler_state, 0); + cso_for_each_state(sc, CSO_VELEMENTS, delete_velements, 0); cso_hash_delete(sc->blend_hash); cso_hash_delete(sc->sampler_hash); @@ -358,6 +377,7 @@ void cso_cache_delete(struct cso_cache *sc) cso_hash_delete(sc->rasterizer_hash); cso_hash_delete(sc->fs_hash); cso_hash_delete(sc->vs_hash); + cso_hash_delete(sc->velements_hash); FREE(sc); } @@ -372,6 +392,7 @@ void cso_set_maximum_cache_size(struct cso_cache *sc, int number) sanitize_hash(sc, sc->vs_hash, CSO_VERTEX_SHADER, sc->max_size); sanitize_hash(sc, sc->rasterizer_hash, CSO_RASTERIZER, sc->max_size); sanitize_hash(sc, sc->sampler_hash, CSO_SAMPLER, sc->max_size); + sanitize_hash(sc, sc->velements_hash, CSO_VELEMENTS, sc->max_size); } int cso_maximum_cache_size(const struct cso_cache *sc) diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.h b/src/gallium/auxiliary/cso_cache/cso_cache.h index eea60b940bb..fb09b83c623 100644 --- a/src/gallium/auxiliary/cso_cache/cso_cache.h +++ b/src/gallium/auxiliary/cso_cache/cso_cache.h @@ -53,6 +53,7 @@ * - rasterizer (old setup) * - sampler * - vertex shader + * - vertex elements * * Things that are not constant state objects include: * - blend_color @@ -90,7 +91,8 @@ enum cso_cache_type { CSO_DEPTH_STENCIL_ALPHA, CSO_RASTERIZER, CSO_FRAGMENT_SHADER, - CSO_VERTEX_SHADER + CSO_VERTEX_SHADER, + CSO_VELEMENTS }; typedef void (*cso_state_callback)(void *ctx, void *obj); @@ -144,6 +146,18 @@ struct cso_sampler { struct pipe_context *context; }; +struct cso_velems_state { + unsigned count; + struct pipe_vertex_element velems[PIPE_MAX_ATTRIBS]; +}; + +struct cso_velements { + struct cso_velems_state state; + void *data; + cso_state_callback delete_state; + struct pipe_context *context; +}; + unsigned cso_construct_key(void *item, int item_size); struct cso_cache *cso_cache_create(void); diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index a7335c340ca..4ed9e09c529 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -37,7 +37,9 @@ #include "pipe/p_state.h" #include "util/u_inlines.h" +#include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "tgsi/tgsi_parse.h" #include "cso_cache/cso_context.h" @@ -69,17 +71,17 @@ struct cso_context { unsigned nr_vertex_samplers_saved; void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS]; - struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; - uint nr_textures; + uint nr_fragment_sampler_views; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; - struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; - uint nr_vertex_textures; + uint nr_vertex_sampler_views; + struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; - uint nr_textures_saved; - struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS]; + uint nr_fragment_sampler_views_saved; + struct pipe_sampler_view *fragment_sampler_views_saved[PIPE_MAX_SAMPLERS]; - uint nr_vertex_textures_saved; - struct pipe_texture *vertex_textures_saved[PIPE_MAX_SAMPLERS]; + uint nr_vertex_sampler_views_saved; + struct pipe_sampler_view *vertex_sampler_views_saved[PIPE_MAX_VERTEX_SAMPLERS]; /** Current and saved state. * The saved state is used as a 1-deep stack. @@ -89,6 +91,7 @@ struct cso_context { void *rasterizer, *rasterizer_saved; void *fragment_shader, *fragment_shader_saved, *geometry_shader; void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved; + void *velements, *velements_saved; struct pipe_clip_state clip; struct pipe_clip_state clip_saved; @@ -174,6 +177,20 @@ static boolean delete_vs_state(struct cso_context *ctx, void *state) return FALSE; } +static boolean delete_vertex_elements(struct cso_context *ctx, + void *state) +{ + struct cso_velements *cso = (struct cso_velements *)state; + + if (ctx->velements == cso->data) + return FALSE; + + if (cso->delete_state) + cso->delete_state(cso->context, cso->data); + FREE(state); + return TRUE; +} + static INLINE boolean delete_cso(struct cso_context *ctx, void *state, enum cso_cache_type type) @@ -197,6 +214,9 @@ static INLINE boolean delete_cso(struct cso_context *ctx, case CSO_VERTEX_SHADER: return delete_vs_state(ctx, state); break; + case CSO_VELEMENTS: + return delete_vertex_elements(ctx, state); + break; default: assert(0); FREE(state); @@ -271,16 +291,17 @@ void cso_release_all( struct cso_context *ctx ) ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL ); ctx->pipe->bind_fs_state( ctx->pipe, NULL ); ctx->pipe->bind_vs_state( ctx->pipe, NULL ); + ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL ); } for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - pipe_texture_reference(&ctx->textures[i], NULL); - pipe_texture_reference(&ctx->textures_saved[i], NULL); + pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); + pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], NULL); } for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - pipe_texture_reference(&ctx->vertex_textures[i], NULL); - pipe_texture_reference(&ctx->vertex_textures_saved[i], NULL); + pipe_sampler_view_reference(&ctx->vertex_sampler_views[i], NULL); + pipe_sampler_view_reference(&ctx->vertex_sampler_views_saved[i], NULL); } free_framebuffer_state(&ctx->fb); @@ -603,108 +624,68 @@ enum pipe_error cso_set_sampler_textures( struct cso_context *ctx, { uint i; - ctx->nr_textures = count; + ctx->nr_fragment_sampler_views = count; - for (i = 0; i < count; i++) - pipe_texture_reference(&ctx->textures[i], textures[i]); - for ( ; i < PIPE_MAX_SAMPLERS; i++) - pipe_texture_reference(&ctx->textures[i], NULL); + for (i = 0; i < count; i++) { + struct pipe_sampler_view templ, *view; - ctx->pipe->set_fragment_sampler_textures(ctx->pipe, count, textures); + u_sampler_view_default_template(&templ, + textures[i], + textures[i]->format); - return PIPE_OK; -} - -void cso_save_sampler_textures( struct cso_context *ctx ) -{ - uint i; + view = ctx->pipe->create_sampler_view(ctx->pipe, + textures[i], + &templ); - ctx->nr_textures_saved = ctx->nr_textures; - for (i = 0; i < ctx->nr_textures; i++) { - assert(!ctx->textures_saved[i]); - pipe_texture_reference(&ctx->textures_saved[i], ctx->textures[i]); + pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], view); } -} - -void cso_restore_sampler_textures( struct cso_context *ctx ) -{ - uint i; - - ctx->nr_textures = ctx->nr_textures_saved; - - for (i = 0; i < ctx->nr_textures; i++) { - pipe_texture_reference(&ctx->textures[i], NULL); - ctx->textures[i] = ctx->textures_saved[i]; - ctx->textures_saved[i] = NULL; + for ( ; i < PIPE_MAX_SAMPLERS; i++) { + pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); } - for ( ; i < PIPE_MAX_SAMPLERS; i++) - pipe_texture_reference(&ctx->textures[i], NULL); - - ctx->pipe->set_fragment_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures); - - ctx->nr_textures_saved = 0; -} - - -enum pipe_error -cso_set_vertex_sampler_textures(struct cso_context *ctx, - uint count, - struct pipe_texture **textures) -{ - uint i; - - ctx->nr_vertex_textures = count; - - for (i = 0; i < count; i++) { - pipe_texture_reference(&ctx->vertex_textures[i], textures[i]); - } - for ( ; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - pipe_texture_reference(&ctx->vertex_textures[i], NULL); - } - - ctx->pipe->set_vertex_sampler_textures(ctx->pipe, count, textures); + ctx->pipe->set_fragment_sampler_views(ctx->pipe, + count, + ctx->fragment_sampler_views); return PIPE_OK; } -void -cso_save_vertex_sampler_textures(struct cso_context *ctx) +void cso_save_sampler_textures( struct cso_context *ctx ) { uint i; - ctx->nr_vertex_textures_saved = ctx->nr_vertex_textures; - for (i = 0; i < ctx->nr_vertex_textures; i++) { - assert(!ctx->vertex_textures_saved[i]); - pipe_texture_reference(&ctx->vertex_textures_saved[i], ctx->vertex_textures[i]); + ctx->nr_fragment_sampler_views_saved = ctx->nr_fragment_sampler_views; + for (i = 0; i < ctx->nr_fragment_sampler_views; i++) { + assert(!ctx->fragment_sampler_views_saved[i]); + + pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], + ctx->fragment_sampler_views[i]); } } -void -cso_restore_vertex_sampler_textures(struct cso_context *ctx) +void cso_restore_sampler_textures( struct cso_context *ctx ) { uint i; - ctx->nr_vertex_textures = ctx->nr_vertex_textures_saved; + ctx->nr_fragment_sampler_views = ctx->nr_fragment_sampler_views_saved; - for (i = 0; i < ctx->nr_vertex_textures; i++) { - pipe_texture_reference(&ctx->vertex_textures[i], NULL); - ctx->vertex_textures[i] = ctx->vertex_textures_saved[i]; - ctx->vertex_textures_saved[i] = NULL; + for (i = 0; i < ctx->nr_fragment_sampler_views; i++) { + pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); + ctx->fragment_sampler_views[i] = ctx->fragment_sampler_views_saved[i]; + ctx->fragment_sampler_views_saved[i] = NULL; } - for ( ; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - pipe_texture_reference(&ctx->vertex_textures[i], NULL); + for ( ; i < PIPE_MAX_SAMPLERS; i++) { + pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); } - ctx->pipe->set_vertex_sampler_textures(ctx->pipe, - ctx->nr_vertex_textures, - ctx->vertex_textures); + ctx->pipe->set_fragment_sampler_views(ctx->pipe, + ctx->nr_fragment_sampler_views, + ctx->fragment_sampler_views); - ctx->nr_vertex_textures_saved = 0; + ctx->nr_fragment_sampler_views_saved = 0; } - enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, const struct pipe_depth_stencil_alpha_state *templ) { @@ -1130,7 +1111,6 @@ void cso_restore_geometry_shader(struct cso_context *ctx) ctx->geometry_shader_saved = NULL; } - /* clip state */ static INLINE void @@ -1180,3 +1160,185 @@ cso_restore_clip(struct cso_context *ctx) ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip_saved); } } + +enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, + unsigned count, + const struct pipe_vertex_element *states) +{ + unsigned key_size, hash_key; + struct cso_hash_iter iter; + void *handle; + struct cso_velems_state velems_state; + + /* need to include the count into the stored state data too. + Otherwise first few count pipe_vertex_elements could be identical even if count + is different, and there's no guarantee the hash would be different in that + case neither */ + key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned); + velems_state.count = count; + memcpy(velems_state.velems, states, sizeof(struct pipe_vertex_element) * count); + hash_key = cso_construct_key((void*)&velems_state, key_size); + iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS, (void*)&velems_state, key_size); + + if (cso_hash_iter_is_null(iter)) { + struct cso_velements *cso = MALLOC(sizeof(struct cso_velements)); + if (!cso) + return PIPE_ERROR_OUT_OF_MEMORY; + + memcpy(&cso->state, &velems_state, key_size); + cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count, &cso->state.velems[0]); + cso->delete_state = (cso_state_callback)ctx->pipe->delete_vertex_elements_state; + cso->context = ctx->pipe; + + iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso); + if (cso_hash_iter_is_null(iter)) { + FREE(cso); + return PIPE_ERROR_OUT_OF_MEMORY; + } + + handle = cso->data; + } + else { + handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data; + } + + if (ctx->velements != handle) { + ctx->velements = handle; + ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle); + } + return PIPE_OK; +} + +void cso_save_vertex_elements(struct cso_context *ctx) +{ + assert(!ctx->velements_saved); + ctx->velements_saved = ctx->velements; +} + +void cso_restore_vertex_elements(struct cso_context *ctx) +{ + if (ctx->velements != ctx->velements_saved) { + ctx->velements = ctx->velements_saved; + ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved); + } + ctx->velements_saved = NULL; +} + +/* fragment sampler view state */ + +void +cso_set_fragment_sampler_views(struct cso_context *cso, + uint count, + struct pipe_sampler_view **views) +{ + uint i; + + for (i = 0; i < count; i++) { + pipe_sampler_view_reference(&cso->fragment_sampler_views[i], views[i]); + } + for (; i < cso->nr_fragment_sampler_views; i++) { + pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); + } + + cso->pipe->set_fragment_sampler_views(cso->pipe, + MAX2(count, cso->nr_fragment_sampler_views), + cso->fragment_sampler_views); + + cso->nr_fragment_sampler_views = count; +} + +void +cso_save_fragment_sampler_views(struct cso_context *cso) +{ + uint i; + + cso->nr_fragment_sampler_views_saved = cso->nr_fragment_sampler_views; + + for (i = 0; i < cso->nr_fragment_sampler_views; i++) { + assert(!cso->fragment_sampler_views_saved[i]); + + pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], + cso->fragment_sampler_views[i]); + } +} + +void +cso_restore_fragment_sampler_views(struct cso_context *cso) +{ + uint i; + + for (i = 0; i < cso->nr_fragment_sampler_views_saved; i++) { + pipe_sampler_view_reference(&cso->fragment_sampler_views[i], cso->fragment_sampler_views_saved[i]); + pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], NULL); + } + for (; i < cso->nr_fragment_sampler_views; i++) { + pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); + } + + cso->pipe->set_fragment_sampler_views(cso->pipe, + MAX2(cso->nr_fragment_sampler_views, cso->nr_fragment_sampler_views_saved), + cso->fragment_sampler_views); + + cso->nr_fragment_sampler_views = cso->nr_fragment_sampler_views_saved; + cso->nr_fragment_sampler_views_saved = 0; +} + + +/* vertex sampler view state */ + +void +cso_set_vertex_sampler_views(struct cso_context *cso, + uint count, + struct pipe_sampler_view **views) +{ + uint i; + + for (i = 0; i < count; i++) { + pipe_sampler_view_reference(&cso->vertex_sampler_views[i], views[i]); + } + for (; i < cso->nr_vertex_sampler_views; i++) { + pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); + } + + cso->pipe->set_vertex_sampler_views(cso->pipe, + MAX2(count, cso->nr_vertex_sampler_views), + cso->vertex_sampler_views); + + cso->nr_vertex_sampler_views = count; +} + +void +cso_save_vertex_sampler_views(struct cso_context *cso) +{ + uint i; + + cso->nr_vertex_sampler_views_saved = cso->nr_vertex_sampler_views; + + for (i = 0; i < cso->nr_vertex_sampler_views; i++) { + assert(!cso->vertex_sampler_views_saved[i]); + + pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], + cso->vertex_sampler_views[i]); + } +} + +void +cso_restore_vertex_sampler_views(struct cso_context *cso) +{ + uint i; + + for (i = 0; i < cso->nr_vertex_sampler_views_saved; i++) { + pipe_sampler_view_reference(&cso->vertex_sampler_views[i], cso->vertex_sampler_views_saved[i]); + pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], NULL); + } + for (; i < cso->nr_vertex_sampler_views; i++) { + pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); + } + + cso->pipe->set_vertex_sampler_views(cso->pipe, + MAX2(cso->nr_vertex_sampler_views, cso->nr_vertex_sampler_views_saved), + cso->vertex_sampler_views); + + cso->nr_vertex_sampler_views = cso->nr_vertex_sampler_views_saved; + cso->nr_vertex_sampler_views_saved = 0; +} diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 251a9a644f8..a24077e009c 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -111,16 +111,11 @@ void cso_save_sampler_textures( struct cso_context *cso ); void cso_restore_sampler_textures( struct cso_context *cso ); - -enum pipe_error -cso_set_vertex_sampler_textures(struct cso_context *cso, - uint count, - struct pipe_texture **textures); -void -cso_save_vertex_sampler_textures(struct cso_context *cso); -void -cso_restore_vertex_sampler_textures(struct cso_context *cso); - +enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, + unsigned count, + const struct pipe_vertex_element *states); +void cso_save_vertex_elements(struct cso_context *ctx); +void cso_restore_vertex_elements(struct cso_context *ctx); /* These aren't really sensible -- most of the time the api provides @@ -157,7 +152,6 @@ void cso_save_geometry_shader(struct cso_context *cso); void cso_restore_geometry_shader(struct cso_context *cso); - enum pipe_error cso_set_framebuffer(struct cso_context *cso, const struct pipe_framebuffer_state *fb); void cso_save_framebuffer(struct cso_context *cso); @@ -193,6 +187,34 @@ void cso_restore_clip(struct cso_context *cso); +/* fragment sampler view state */ + +void +cso_set_fragment_sampler_views(struct cso_context *cso, + uint count, + struct pipe_sampler_view **views); + +void +cso_save_fragment_sampler_views(struct cso_context *cso); + +void +cso_restore_fragment_sampler_views(struct cso_context *cso); + + +/* vertex sampler view state */ + +void +cso_set_vertex_sampler_views(struct cso_context *cso, + uint count, + struct pipe_sampler_view **views); + +void +cso_save_vertex_sampler_views(struct cso_context *cso); + +void +cso_restore_vertex_sampler_views(struct cso_context *cso); + + #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c index 8f6ca15dfa2..f4615064e65 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c @@ -40,6 +40,7 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "tgsi/tgsi_transform.h" #include "tgsi/tgsi_dump.h" @@ -88,8 +89,9 @@ struct aaline_stage void *sampler_cso; struct pipe_texture *texture; + struct pipe_sampler_view *sampler_view; uint num_samplers; - uint num_textures; + uint num_sampler_views; /* @@ -98,7 +100,7 @@ struct aaline_stage struct aaline_fragment_shader *fs; struct { void *sampler[PIPE_MAX_SAMPLERS]; - struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; } state; /* @@ -111,8 +113,9 @@ struct aaline_stage void (*driver_bind_sampler_states)(struct pipe_context *, unsigned, void **); - void (*driver_set_sampler_textures)(struct pipe_context *, unsigned, - struct pipe_texture **); + void (*driver_set_sampler_views)(struct pipe_context *, + unsigned, + struct pipe_sampler_view **); struct pipe_context *pipe; }; @@ -394,6 +397,7 @@ aaline_create_texture(struct aaline_stage *aaline) struct pipe_context *pipe = aaline->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_texture texTemp; + struct pipe_sampler_view viewTempl; uint level; memset(&texTemp, 0, sizeof(texTemp)); @@ -408,6 +412,16 @@ aaline_create_texture(struct aaline_stage *aaline) if (!aaline->texture) return FALSE; + u_sampler_view_default_template(&viewTempl, + aaline->texture, + aaline->texture->format); + aaline->sampler_view = pipe->create_sampler_view(pipe, + aaline->texture, + &viewTempl); + if (!aaline->sampler_view) { + return FALSE; + } + /* Fill in mipmap images. * Basically each level is solid opaque, except for the outermost * texels which are zero. Special case the 1x1 and 2x2 levels. @@ -422,9 +436,9 @@ aaline_create_texture(struct aaline_stage *aaline) /* This texture is new, no need to flush. */ - transfer = screen->get_tex_transfer(screen, aaline->texture, 0, level, 0, + transfer = pipe->get_tex_transfer(pipe, aaline->texture, 0, level, 0, PIPE_TRANSFER_WRITE, 0, 0, size, size); - data = screen->transfer_map(screen, transfer); + data = pipe->transfer_map(pipe, transfer); if (data == NULL) return FALSE; @@ -448,8 +462,8 @@ aaline_create_texture(struct aaline_stage *aaline) } /* unmap */ - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->tex_transfer_destroy(pipe, transfer); } return TRUE; } @@ -669,16 +683,16 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header) /* how many samplers? */ /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ - num_samplers = MAX2(aaline->num_textures, aaline->num_samplers); + num_samplers = MAX2(aaline->num_sampler_views, aaline->num_samplers); num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1); aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso; - pipe_texture_reference(&aaline->state.texture[aaline->fs->sampler_unit], - aaline->texture); + pipe_sampler_view_reference(&aaline->state.sampler_views[aaline->fs->sampler_unit], + aaline->sampler_view); draw->suspend_flushing = TRUE; aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler); - aaline->driver_set_sampler_textures(pipe, num_samplers, aaline->state.texture); + aaline->driver_set_sampler_views(pipe, num_samplers, aaline->state.sampler_views); draw->suspend_flushing = FALSE; /* now really draw first line */ @@ -702,8 +716,9 @@ aaline_flush(struct draw_stage *stage, unsigned flags) aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs); aaline->driver_bind_sampler_states(pipe, aaline->num_samplers, aaline->state.sampler); - aaline->driver_set_sampler_textures(pipe, aaline->num_textures, - aaline->state.texture); + aaline->driver_set_sampler_views(pipe, + aaline->num_sampler_views, + aaline->state.sampler_views); draw->suspend_flushing = FALSE; draw->extra_shader_outputs.slot = 0; @@ -724,7 +739,7 @@ aaline_destroy(struct draw_stage *stage) uint i; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - pipe_texture_reference(&aaline->state.texture[i], NULL); + pipe_sampler_view_reference(&aaline->state.sampler_views[i], NULL); } if (aaline->sampler_cso) @@ -733,6 +748,10 @@ aaline_destroy(struct draw_stage *stage) if (aaline->texture) pipe_texture_reference(&aaline->texture, NULL); + if (aaline->sampler_view) { + pipe_sampler_view_reference(&aaline->sampler_view, NULL); + } + draw_free_temp_verts( stage ); FREE( stage ); @@ -844,23 +863,24 @@ aaline_bind_sampler_states(struct pipe_context *pipe, static void -aaline_set_sampler_textures(struct pipe_context *pipe, - unsigned num, struct pipe_texture **texture) +aaline_set_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); uint i; /* save current */ for (i = 0; i < num; i++) { - pipe_texture_reference(&aaline->state.texture[i], texture[i]); + pipe_sampler_view_reference(&aaline->state.sampler_views[i], views[i]); } for ( ; i < PIPE_MAX_SAMPLERS; i++) { - pipe_texture_reference(&aaline->state.texture[i], NULL); + pipe_sampler_view_reference(&aaline->state.sampler_views[i], NULL); } - aaline->num_textures = num; + aaline->num_sampler_views = num; /* pass-through */ - aaline->driver_set_sampler_textures(aaline->pipe, num, texture); + aaline->driver_set_sampler_views(aaline->pipe, num, views); } @@ -898,7 +918,7 @@ draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe) aaline->driver_delete_fs_state = pipe->delete_fs_state; aaline->driver_bind_sampler_states = pipe->bind_fragment_sampler_states; - aaline->driver_set_sampler_textures = pipe->set_fragment_sampler_textures; + aaline->driver_set_sampler_views = pipe->set_fragment_sampler_views; /* override the driver's functions */ pipe->create_fs_state = aaline_create_fs_state; @@ -906,7 +926,7 @@ draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe) pipe->delete_fs_state = aaline_delete_fs_state; pipe->bind_fragment_sampler_states = aaline_bind_sampler_states; - pipe->set_fragment_sampler_textures = aaline_set_sampler_textures; + pipe->set_fragment_sampler_views = aaline_set_sampler_views; /* Install once everything is known to be OK: */ diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c index d0d99aa331a..794fd81d70f 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c +++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c @@ -42,6 +42,7 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "tgsi/tgsi_transform.h" #include "tgsi/tgsi_dump.h" @@ -75,8 +76,9 @@ struct pstip_stage void *sampler_cso; struct pipe_texture *texture; + struct pipe_sampler_view *sampler_view; uint num_samplers; - uint num_textures; + uint num_sampler_views; /* * Currently bound state @@ -84,7 +86,7 @@ struct pstip_stage struct pstip_fragment_shader *fs; struct { void *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; const struct pipe_poly_stipple *stipple; } state; @@ -98,8 +100,9 @@ struct pstip_stage void (*driver_bind_sampler_states)(struct pipe_context *, unsigned, void **); - void (*driver_set_sampler_textures)(struct pipe_context *, unsigned, - struct pipe_texture **); + void (*driver_set_sampler_views)(struct pipe_context *, + unsigned, + struct pipe_sampler_view **); void (*driver_set_polygon_stipple)(struct pipe_context *, const struct pipe_poly_stipple *); @@ -374,19 +377,21 @@ pstip_update_texture(struct pstip_stage *pstip) { static const uint bit31 = 1 << 31; struct pipe_context *pipe = pstip->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *transfer; const uint *stipple = pstip->state.stipple->stipple; uint i, j; ubyte *data; /* XXX: want to avoid flushing just because we use stipple: + * + * Flush should no longer be necessary if driver is properly + * interleaving drawing and transfers on a given context: */ pipe->flush( pipe, PIPE_FLUSH_TEXTURE_CACHE, NULL ); - transfer = screen->get_tex_transfer(screen, pstip->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, 0, 0, 32, 32); - data = screen->transfer_map(screen, transfer); + transfer = pipe->get_tex_transfer(pipe, pstip->texture, 0, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, 32, 32); + data = pipe->transfer_map(pipe, transfer); /* * Load alpha texture. @@ -408,8 +413,8 @@ pstip_update_texture(struct pstip_stage *pstip) } /* unmap */ - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->tex_transfer_destroy(pipe, transfer); } @@ -422,6 +427,7 @@ pstip_create_texture(struct pstip_stage *pstip) struct pipe_context *pipe = pstip->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_texture texTemp; + struct pipe_sampler_view viewTempl; memset(&texTemp, 0, sizeof(texTemp)); texTemp.target = PIPE_TEXTURE_2D; @@ -435,6 +441,16 @@ pstip_create_texture(struct pstip_stage *pstip) if (pstip->texture == NULL) return FALSE; + u_sampler_view_default_template(&viewTempl, + pstip->texture, + pstip->texture->format); + pstip->sampler_view = pipe->create_sampler_view(pipe, + pstip->texture, + &viewTempl); + if (!pstip->sampler_view) { + return FALSE; + } + return TRUE; } @@ -513,19 +529,19 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header) /* how many samplers? */ /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ - num_samplers = MAX2(pstip->num_textures, pstip->num_samplers); + num_samplers = MAX2(pstip->num_sampler_views, pstip->num_samplers); num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1); /* plug in our sampler, texture */ pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso; - pipe_texture_reference(&pstip->state.textures[pstip->fs->sampler_unit], - pstip->texture); + pipe_sampler_view_reference(&pstip->state.sampler_views[pstip->fs->sampler_unit], + pstip->sampler_view); assert(num_samplers <= PIPE_MAX_SAMPLERS); draw->suspend_flushing = TRUE; pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers); - pstip->driver_set_sampler_textures(pipe, num_samplers, pstip->state.textures); + pstip->driver_set_sampler_views(pipe, num_samplers, pstip->state.sampler_views); draw->suspend_flushing = FALSE; /* now really draw first triangle */ @@ -549,8 +565,9 @@ pstip_flush(struct draw_stage *stage, unsigned flags) pstip->driver_bind_fs_state(pipe, pstip->fs->driver_fs); pstip->driver_bind_sampler_states(pipe, pstip->num_samplers, pstip->state.samplers); - pstip->driver_set_sampler_textures(pipe, pstip->num_textures, - pstip->state.textures); + pstip->driver_set_sampler_views(pipe, + pstip->num_sampler_views, + pstip->state.sampler_views); draw->suspend_flushing = FALSE; } @@ -569,13 +586,17 @@ pstip_destroy(struct draw_stage *stage) uint i; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - pipe_texture_reference(&pstip->state.textures[i], NULL); + pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL); } pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso); pipe_texture_reference(&pstip->texture, NULL); + if (pstip->sampler_view) { + pipe_sampler_view_reference(&pstip->sampler_view, NULL); + } + draw_free_temp_verts( stage ); FREE( stage ); } @@ -680,24 +701,25 @@ pstip_bind_sampler_states(struct pipe_context *pipe, static void -pstip_set_sampler_textures(struct pipe_context *pipe, - unsigned num, struct pipe_texture **texture) +pstip_set_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); uint i; /* save current */ for (i = 0; i < num; i++) { - pipe_texture_reference(&pstip->state.textures[i], texture[i]); + pipe_sampler_view_reference(&pstip->state.sampler_views[i], views[i]); } for (; i < PIPE_MAX_SAMPLERS; i++) { - pipe_texture_reference(&pstip->state.textures[i], NULL); + pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL); } - pstip->num_textures = num; + pstip->num_sampler_views = num; /* pass-through */ - pstip->driver_set_sampler_textures(pstip->pipe, num, texture); + pstip->driver_set_sampler_views(pstip->pipe, num, views); } @@ -754,7 +776,7 @@ draw_install_pstipple_stage(struct draw_context *draw, pstip->driver_delete_fs_state = pipe->delete_fs_state; pstip->driver_bind_sampler_states = pipe->bind_fragment_sampler_states; - pstip->driver_set_sampler_textures = pipe->set_fragment_sampler_textures; + pstip->driver_set_sampler_views = pipe->set_fragment_sampler_views; pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple; /* override the driver's functions */ @@ -763,7 +785,7 @@ draw_install_pstipple_stage(struct draw_context *draw, pipe->delete_fs_state = pstip_delete_fs_state; pipe->bind_fragment_sampler_states = pstip_bind_sampler_states; - pipe->set_fragment_sampler_textures = pstip_set_sampler_textures; + pipe->set_fragment_sampler_views = pstip_set_sampler_views; pipe->set_polygon_stipple = pstip_set_polygon_stipple; return TRUE; diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 6d90a6c42fd..a8cdc57ad96 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -307,9 +307,8 @@ draw_arrays_instanced(struct draw_context *draw, tgsi_dump(draw->vs.vertex_shader->state.tokens, 0); debug_printf("Elements:\n"); for (i = 0; i < draw->pt.nr_vertex_elements; i++) { - debug_printf(" format=%s comps=%u\n", - util_format_name(draw->pt.vertex_element[i].src_format), - draw->pt.vertex_element[i].nr_components); + debug_printf(" format=%s\n", + util_format_name(draw->pt.vertex_element[i].src_format)); } debug_printf("Buffers:\n"); for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { diff --git a/src/gallium/auxiliary/draw/draw_pt_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h index 4ca5b520204..3c44f7c11ee 100644 --- a/src/gallium/auxiliary/draw/draw_pt_decompose.h +++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h @@ -105,40 +105,20 @@ static void FUNC( ARGS, case PIPE_PRIM_QUADS: - if (flatfirst) { - for (i = 0; i+3 < count; i += 4) { - QUAD( (i + 1), - (i + 2), - (i + 3), - (i + 0) ); - } - } - else { - for (i = 0; i+3 < count; i += 4) { - QUAD( (i + 0), - (i + 1), - (i + 2), - (i + 3)); - } + for (i = 0; i+3 < count; i += 4) { + QUAD( (i + 0), + (i + 1), + (i + 2), + (i + 3)); } break; case PIPE_PRIM_QUAD_STRIP: - if (flatfirst) { - for (i = 0; i+3 < count; i += 2) { - QUAD( (i + 1), - (i + 3), - (i + 2), - (i + 0) ); - } - } - else { - for (i = 0; i+3 < count; i += 2) { - QUAD( (i + 2), - (i + 0), - (i + 1), - (i + 3)); - } + for (i = 0; i+3 < count; i += 2) { + QUAD( (i + 2), + (i + 0), + (i + 1), + (i + 3)); } break; diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h index 62822a3d562..7cba8547f15 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h @@ -118,39 +118,21 @@ static void FUNC( struct draw_pt_front_end *frontend, case PIPE_PRIM_QUADS: for (i = 0; i+3 < count; i += 4) { - if (flatfirst) { - QUAD( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2), - get_elt(elts, i + 3) ); - } - else { - QUAD( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2), - get_elt(elts, i + 3) ); - } + QUAD( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, i + 3) ); } break; case PIPE_PRIM_QUAD_STRIP: for (i = 0; i+3 < count; i += 2) { - if (flatfirst) { - QUAD( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 3), - get_elt(elts, i + 2) ); - } - else { - QUAD( vcache, - get_elt(elts, i + 2), - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 3) ); - } + QUAD( vcache, + get_elt(elts, i + 2), + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 3) ); } break; diff --git a/src/gallium/drivers/cell/ppu/cell_winsys.h b/src/gallium/auxiliary/gallivm/lp_bld.h index e227e065ff3..70a4960f913 100644 --- a/src/gallium/drivers/cell/ppu/cell_winsys.h +++ b/src/gallium/auxiliary/gallivm/lp_bld.h @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 2010 VMware, Inc. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,38 +10,38 @@ * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * **************************************************************************/ +/** + * @file + * Wrapper for LLVM header file #includes. + */ -#ifndef CELL_WINSYS_H -#define CELL_WINSYS_H -#include "pipe/p_compiler.h" +#ifndef LP_BLD_H +#define LP_BLD_H -/** - * Very simple winsys at this time. - * Will probably eventually add SPU control info. - */ -struct cell_winsys -{ - uint dummy; -}; +#include <llvm-c/Core.h> +/** Set version to 0 if missing to avoid #ifdef HAVE_LLVM everywhere */ +#ifndef HAVE_LLVM +#define HAVE_LLVM 0x0207 +#endif -#endif +#endif /* LP_BLD_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_alpha.h b/src/gallium/auxiliary/gallivm/lp_bld_alpha.h index 634575670db..0f99fec65ed 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_alpha.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_alpha.h @@ -35,7 +35,7 @@ #define LP_BLD_ALPHA_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct pipe_alpha_state; struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index 32f9e5201c5..8e8fcccf564 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -232,6 +232,37 @@ lp_build_add(struct lp_build_context *bld, } +/** Return the sum of the elements of a */ +LLVMValueRef +lp_build_sum_vector(struct lp_build_context *bld, + LLVMValueRef a) +{ + const struct lp_type type = bld->type; + LLVMValueRef index, res; + int i; + + if (a == bld->zero) + return bld->zero; + if (a == bld->undef) + return bld->undef; + assert(type.length > 1); + + assert(!bld->type.norm); + + index = LLVMConstInt(LLVMInt32Type(), 0, 0); + res = LLVMBuildExtractElement(bld->builder, a, index, ""); + + for (i = 1; i < type.length; i++) { + index = LLVMConstInt(LLVMInt32Type(), i, 0); + res = LLVMBuildAdd(bld->builder, res, + LLVMBuildExtractElement(bld->builder, a, index, ""), + ""); + } + + return res; +} + + /** * Generate a - b */ @@ -330,12 +361,12 @@ lp_build_mul_u8n(LLVMBuilderRef builder, LLVMValueRef c8; LLVMValueRef ab; - c8 = lp_build_int_const_scalar(i16_type, 8); + c8 = lp_build_const_int_vec(i16_type, 8); #if 0 /* a*b/255 ~= (a*(b + 1)) >> 256 */ - b = LLVMBuildAdd(builder, b, lp_build_int_const_scalar(i16_type, 1), ""); + b = LLVMBuildAdd(builder, b, lp_build_const_int_vec(i16_type, 1), ""); ab = LLVMBuildMul(builder, a, b, ""); #else @@ -343,7 +374,7 @@ lp_build_mul_u8n(LLVMBuilderRef builder, /* ab/255 ~= (ab + (ab >> 8) + 0x80) >> 8 */ ab = LLVMBuildMul(builder, a, b, ""); ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c8, ""), ""); - ab = LLVMBuildAdd(builder, ab, lp_build_int_const_scalar(i16_type, 0x80), ""); + ab = LLVMBuildAdd(builder, ab, lp_build_const_int_vec(i16_type, 0x80), ""); #endif @@ -398,7 +429,7 @@ lp_build_mul(struct lp_build_context *bld, } if(type.fixed) - shift = lp_build_int_const_scalar(type, type.width/2); + shift = lp_build_const_int_vec(type, type.width/2); else shift = NULL; @@ -460,7 +491,7 @@ lp_build_mul_imm(struct lp_build_context *bld, * for Inf and NaN. */ unsigned mantissa = lp_mantissa(bld->type); - factor = lp_build_int_const_scalar(bld->type, (unsigned long long)shift << mantissa); + factor = lp_build_const_int_vec(bld->type, (unsigned long long)shift << mantissa); a = LLVMBuildBitCast(bld->builder, a, lp_build_int_vec_type(bld->type), ""); a = LLVMBuildAdd(bld->builder, a, factor, ""); a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(bld->type), ""); @@ -468,12 +499,12 @@ lp_build_mul_imm(struct lp_build_context *bld, #endif } else { - factor = lp_build_const_scalar(bld->type, shift); + factor = lp_build_const_vec(bld->type, shift); return LLVMBuildShl(bld->builder, a, factor, ""); } } - factor = lp_build_const_scalar(bld->type, (double)b); + factor = lp_build_const_vec(bld->type, (double)b); return lp_build_mul(bld, a, factor); } @@ -536,7 +567,7 @@ lp_build_lerp(struct lp_build_context *bld, * but it will be wrong for other uses. Basically we need a more * powerful lp_type, capable of further distinguishing the values * interpretation from the value storage. */ - res = LLVMBuildAnd(bld->builder, res, lp_build_int_const_scalar(bld->type, (1 << bld->type.width/2) - 1), ""); + res = LLVMBuildAnd(bld->builder, res, lp_build_const_int_vec(bld->type, (1 << bld->type.width/2) - 1), ""); return res; } @@ -644,13 +675,26 @@ lp_build_abs(struct lp_build_context *bld, if(type.floating) { /* Mask out the sign bit */ - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - unsigned long long absMask = ~(1ULL << (type.width - 1)); - LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask)); - a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); - a = LLVMBuildAnd(bld->builder, a, mask, ""); - a = LLVMBuildBitCast(bld->builder, a, vec_type, ""); - return a; + if (type.length == 1) { + LLVMTypeRef int_type = LLVMIntType(type.width); + LLVMTypeRef float_type = LLVMFloatType(); + unsigned long long absMask = ~(1ULL << (type.width - 1)); + LLVMValueRef mask = LLVMConstInt(int_type, absMask, 0); + a = LLVMBuildBitCast(bld->builder, a, int_type, ""); + a = LLVMBuildAnd(bld->builder, a, mask, ""); + a = LLVMBuildBitCast(bld->builder, a, float_type, ""); + return a; + } + else { + /* vector of floats */ + LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); + unsigned long long absMask = ~(1ULL << (type.width - 1)); + LLVMValueRef mask = lp_build_const_int_vec(type, ((unsigned long long) absMask)); + a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); + a = LLVMBuildAnd(bld->builder, a, mask, ""); + a = LLVMBuildBitCast(bld->builder, a, vec_type, ""); + return a; + } } if(type.width*type.length == 128 && util_cpu_caps.has_ssse3) { @@ -676,12 +720,12 @@ lp_build_negate(struct lp_build_context *bld, } +/** Return -1, 0 or +1 depending on the sign of a */ LLVMValueRef lp_build_sgn(struct lp_build_context *bld, LLVMValueRef a) { const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); LLVMValueRef cond; LLVMValueRef res; @@ -691,27 +735,42 @@ lp_build_sgn(struct lp_build_context *bld, res = bld->one; } else if(type.floating) { - /* Take the sign bit and add it to 1 constant */ - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); + LLVMTypeRef vec_type; + LLVMTypeRef int_type; + LLVMValueRef mask; LLVMValueRef sign; LLVMValueRef one; - sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); + unsigned long long maskBit = (unsigned long long)1 << (type.width - 1); + + if (type.length == 1) { + int_type = lp_build_int_elem_type(type); + vec_type = lp_build_elem_type(type); + mask = LLVMConstInt(int_type, maskBit, 0); + } + else { + /* vector */ + int_type = lp_build_int_vec_type(type); + vec_type = lp_build_vec_type(type); + mask = lp_build_const_int_vec(type, maskBit); + } + + /* Take the sign bit and add it to 1 constant */ + sign = LLVMBuildBitCast(bld->builder, a, int_type, ""); sign = LLVMBuildAnd(bld->builder, sign, mask, ""); - one = LLVMConstBitCast(bld->one, int_vec_type); + one = LLVMConstBitCast(bld->one, int_type); res = LLVMBuildOr(bld->builder, sign, one, ""); res = LLVMBuildBitCast(bld->builder, res, vec_type, ""); } else { - LLVMValueRef minus_one = lp_build_const_scalar(type, -1.0); + LLVMValueRef minus_one = lp_build_const_vec(type, -1.0); cond = lp_build_cmp(bld, PIPE_FUNC_GREATER, a, bld->zero); res = lp_build_select(bld, cond, bld->one, minus_one); } /* Handle zero */ cond = lp_build_cmp(bld, PIPE_FUNC_EQUAL, a, bld->zero); - res = lp_build_select(bld, cond, bld->zero, bld->one); + res = lp_build_select(bld, cond, bld->zero, res); return res; } @@ -730,8 +789,8 @@ lp_build_set_sign(struct lp_build_context *bld, const struct lp_type type = bld->type; LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef shift = lp_build_int_const_scalar(type, type.width - 1); - LLVMValueRef mask = lp_build_int_const_scalar(type, + LLVMValueRef shift = lp_build_const_int_vec(type, type.width - 1); + LLVMValueRef mask = lp_build_const_int_vec(type, ~((unsigned long long) 1 << (type.width - 1))); LLVMValueRef val, res; @@ -753,7 +812,7 @@ lp_build_set_sign(struct lp_build_context *bld, /** - * Convert vector of int to vector of float. + * Convert vector of (or scalar) int to vector of (or scalar) float. */ LLVMValueRef lp_build_int_to_float(struct lp_build_context *bld, @@ -764,7 +823,11 @@ lp_build_int_to_float(struct lp_build_context *bld, assert(type.floating); /*assert(lp_check_value(type, a));*/ - { + if (type.length == 1) { + LLVMTypeRef float_type = LLVMFloatType(); + return LLVMBuildSIToFP(bld->builder, a, float_type, ""); + } + else { LLVMTypeRef vec_type = lp_build_vec_type(type); /*LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);*/ LLVMValueRef res; @@ -866,6 +929,13 @@ lp_build_floor(struct lp_build_context *bld, assert(type.floating); + if (type.length == 1) { + LLVMValueRef res; + res = lp_build_ifloor(bld, a); + res = LLVMBuildSIToFP(bld->builder, res, LLVMFloatType(), ""); + return res; + } + if(util_cpu_caps.has_sse4_1) return lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_FLOOR); else { @@ -921,15 +991,24 @@ lp_build_itrunc(struct lp_build_context *bld, LLVMValueRef a) { const struct lp_type type = bld->type; - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); assert(type.floating); - assert(lp_check_value(type, a)); - return LLVMBuildFPToSI(bld->builder, a, int_vec_type, ""); + if (type.length == 1) { + LLVMTypeRef int_type = LLVMIntType(type.width); + return LLVMBuildFPToSI(bld->builder, a, int_type, ""); + } + else { + LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); + assert(lp_check_value(type, a)); + return LLVMBuildFPToSI(bld->builder, a, int_vec_type, ""); + } } +/** + * Convert float[] to int[] with round(). + */ LLVMValueRef lp_build_iround(struct lp_build_context *bld, LLVMValueRef a) @@ -939,6 +1018,15 @@ lp_build_iround(struct lp_build_context *bld, LLVMValueRef res; assert(type.floating); + + if (type.length == 1) { + /* scalar float to int */ + LLVMTypeRef int_type = LLVMIntType(type.width); + /* XXX we want rounding here! */ + res = LLVMBuildFPToSI(bld->builder, a, int_type, ""); + return res; + } + assert(lp_check_value(type, a)); if(util_cpu_caps.has_sse4_1) { @@ -946,7 +1034,7 @@ lp_build_iround(struct lp_build_context *bld, } else { LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); + LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1)); LLVMValueRef sign; LLVMValueRef half; @@ -955,7 +1043,7 @@ lp_build_iround(struct lp_build_context *bld, sign = LLVMBuildAnd(bld->builder, sign, mask, ""); /* sign * 0.5 */ - half = lp_build_const_scalar(type, 0.5); + half = lp_build_const_vec(type, 0.5); half = LLVMBuildBitCast(bld->builder, half, int_vec_type, ""); half = LLVMBuildOr(bld->builder, sign, half, ""); half = LLVMBuildBitCast(bld->builder, half, vec_type, ""); @@ -981,6 +1069,14 @@ lp_build_ifloor(struct lp_build_context *bld, LLVMValueRef res; assert(type.floating); + + if (type.length == 1) { + /* scalar float to int */ + LLVMTypeRef int_type = LLVMIntType(type.width); + res = LLVMBuildFPToSI(bld->builder, a, int_type, ""); + return res; + } + assert(lp_check_value(type, a)); if(util_cpu_caps.has_sse4_1) { @@ -990,18 +1086,18 @@ lp_build_ifloor(struct lp_build_context *bld, /* Take the sign bit and add it to 1 constant */ LLVMTypeRef vec_type = lp_build_vec_type(type); unsigned mantissa = lp_mantissa(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); + LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1)); LLVMValueRef sign; LLVMValueRef offset; /* sign = a < 0 ? ~0 : 0 */ sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); sign = LLVMBuildAnd(bld->builder, sign, mask, ""); - sign = LLVMBuildAShr(bld->builder, sign, lp_build_int_const_scalar(type, type.width - 1), ""); + sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), ""); lp_build_name(sign, "floor.sign"); /* offset = -0.99999(9)f */ - offset = lp_build_const_scalar(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa)); + offset = lp_build_const_vec(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa)); offset = LLVMConstBitCast(offset, int_vec_type); /* offset = a < 0 ? -0.99999(9)f : 0.0f */ @@ -1172,7 +1268,7 @@ lp_build_exp(struct lp_build_context *bld, LLVMValueRef x) { /* log2(e) = 1/log(2) */ - LLVMValueRef log2e = lp_build_const_scalar(bld->type, 1.4426950408889634); + LLVMValueRef log2e = lp_build_const_vec(bld->type, 1.4426950408889634); return lp_build_mul(bld, log2e, lp_build_exp2(bld, x)); } @@ -1186,7 +1282,7 @@ lp_build_log(struct lp_build_context *bld, LLVMValueRef x) { /* log(2) */ - LLVMValueRef log2 = lp_build_const_scalar(bld->type, 0.69314718055994529); + LLVMValueRef log2 = lp_build_const_vec(bld->type, 0.69314718055994529); return lp_build_mul(bld, log2, lp_build_exp2(bld, x)); } @@ -1207,6 +1303,7 @@ lp_build_polynomial(struct lp_build_context *bld, unsigned num_coeffs) { const struct lp_type type = bld->type; + LLVMTypeRef float_type = LLVMFloatType(); LLVMValueRef res = NULL; unsigned i; @@ -1216,7 +1313,13 @@ lp_build_polynomial(struct lp_build_context *bld, __FUNCTION__); for (i = num_coeffs; i--; ) { - LLVMValueRef coeff = lp_build_const_scalar(type, coeffs[i]); + LLVMValueRef coeff; + + if (type.length == 1) + coeff = LLVMConstReal(float_type, coeffs[i]); + else + coeff = lp_build_const_vec(type, coeffs[i]); + if(res) res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res)); else @@ -1272,11 +1375,11 @@ lp_build_exp2_approx(struct lp_build_context *bld, assert(type.floating && type.width == 32); - x = lp_build_min(bld, x, lp_build_const_scalar(type, 129.0)); - x = lp_build_max(bld, x, lp_build_const_scalar(type, -126.99999)); + x = lp_build_min(bld, x, lp_build_const_vec(type, 129.0)); + x = lp_build_max(bld, x, lp_build_const_vec(type, -126.99999)); /* ipart = int(x - 0.5) */ - ipart = LLVMBuildSub(bld->builder, x, lp_build_const_scalar(type, 0.5f), ""); + ipart = LLVMBuildSub(bld->builder, x, lp_build_const_vec(type, 0.5f), ""); ipart = LLVMBuildFPToSI(bld->builder, ipart, int_vec_type, ""); /* fpart = x - ipart */ @@ -1286,8 +1389,8 @@ lp_build_exp2_approx(struct lp_build_context *bld, if(p_exp2_int_part || p_exp2) { /* expipart = (float) (1 << ipart) */ - expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_int_const_scalar(type, 127), ""); - expipart = LLVMBuildShl(bld->builder, expipart, lp_build_int_const_scalar(type, 23), ""); + expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_const_int_vec(type, 127), ""); + expipart = LLVMBuildShl(bld->builder, expipart, lp_build_const_int_vec(type, 23), ""); expipart = LLVMBuildBitCast(bld->builder, expipart, vec_type, ""); } @@ -1353,8 +1456,8 @@ lp_build_log2_approx(struct lp_build_context *bld, LLVMTypeRef vec_type = lp_build_vec_type(type); LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef expmask = lp_build_int_const_scalar(type, 0x7f800000); - LLVMValueRef mantmask = lp_build_int_const_scalar(type, 0x007fffff); + LLVMValueRef expmask = lp_build_const_int_vec(type, 0x7f800000); + LLVMValueRef mantmask = lp_build_const_int_vec(type, 0x007fffff); LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type); LLVMValueRef i = NULL; @@ -1379,8 +1482,8 @@ lp_build_log2_approx(struct lp_build_context *bld, } if(p_floor_log2 || p_log2) { - logexp = LLVMBuildLShr(bld->builder, exp, lp_build_int_const_scalar(type, 23), ""); - logexp = LLVMBuildSub(bld->builder, logexp, lp_build_int_const_scalar(type, 127), ""); + logexp = LLVMBuildLShr(bld->builder, exp, lp_build_const_int_vec(type, 23), ""); + logexp = LLVMBuildSub(bld->builder, logexp, lp_build_const_int_vec(type, 127), ""); logexp = LLVMBuildSIToFP(bld->builder, logexp, vec_type, ""); } @@ -1410,11 +1513,87 @@ lp_build_log2_approx(struct lp_build_context *bld, } +/** scalar version of above function */ +static void +lp_build_float_log2_approx(struct lp_build_context *bld, + LLVMValueRef x, + LLVMValueRef *p_exp, + LLVMValueRef *p_floor_log2, + LLVMValueRef *p_log2) +{ + const struct lp_type type = bld->type; + LLVMTypeRef float_type = LLVMFloatType(); + LLVMTypeRef int_type = LLVMIntType(type.width); + + LLVMValueRef expmask = LLVMConstInt(int_type, 0x7f800000, 0); + LLVMValueRef mantmask = LLVMConstInt(int_type, 0x007fffff, 0); + LLVMValueRef one = LLVMConstBitCast(bld->one, int_type); + + LLVMValueRef i = NULL; + LLVMValueRef exp = NULL; + LLVMValueRef mant = NULL; + LLVMValueRef logexp = NULL; + LLVMValueRef logmant = NULL; + LLVMValueRef res = NULL; + + if(p_exp || p_floor_log2 || p_log2) { + /* TODO: optimize the constant case */ + if(LLVMIsConstant(x)) + debug_printf("%s: inefficient/imprecise constant arithmetic\n", + __FUNCTION__); + + assert(type.floating && type.width == 32); + + i = LLVMBuildBitCast(bld->builder, x, int_type, ""); + + /* exp = (float) exponent(x) */ + exp = LLVMBuildAnd(bld->builder, i, expmask, ""); + } + + if(p_floor_log2 || p_log2) { + LLVMValueRef c23 = LLVMConstInt(int_type, 23, 0); + LLVMValueRef c127 = LLVMConstInt(int_type, 127, 0); + logexp = LLVMBuildLShr(bld->builder, exp, c23, ""); + logexp = LLVMBuildSub(bld->builder, logexp, c127, ""); + logexp = LLVMBuildSIToFP(bld->builder, logexp, float_type, ""); + } + + if(p_log2) { + /* mant = (float) mantissa(x) */ + mant = LLVMBuildAnd(bld->builder, i, mantmask, ""); + mant = LLVMBuildOr(bld->builder, mant, one, ""); + mant = LLVMBuildBitCast(bld->builder, mant, float_type, ""); + + logmant = lp_build_polynomial(bld, mant, lp_build_log2_polynomial, + Elements(lp_build_log2_polynomial)); + + /* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/ + logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildSub(bld->builder, mant, bld->one, ""), ""); + + res = LLVMBuildAdd(bld->builder, logmant, logexp, ""); + } + + if(p_exp) + *p_exp = exp; + + if(p_floor_log2) + *p_floor_log2 = logexp; + + if(p_log2) + *p_log2 = res; +} + + LLVMValueRef lp_build_log2(struct lp_build_context *bld, LLVMValueRef x) { LLVMValueRef res; - lp_build_log2_approx(bld, x, NULL, NULL, &res); + if (bld->type.length == 1) { + lp_build_float_log2_approx(bld, x, NULL, NULL, &res); + } + else { + lp_build_log2_approx(bld, x, NULL, NULL, &res); + } return res; } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.h b/src/gallium/auxiliary/gallivm/lp_bld_arit.h index 55385e3a66a..31efa9921ce 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.h @@ -37,7 +37,7 @@ #define LP_BLD_ARIT_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct lp_type; @@ -57,6 +57,10 @@ lp_build_add(struct lp_build_context *bld, LLVMValueRef b); LLVMValueRef +lp_build_sum_vector(struct lp_build_context *bld, + LLVMValueRef a); + +LLVMValueRef lp_build_sub(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_blend.h b/src/gallium/auxiliary/gallivm/lp_bld_blend.h index da272e549f3..ebbdb1a604c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_blend.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_blend.h @@ -40,7 +40,7 @@ * for a standalone example. */ -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include "pipe/p_format.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_const.c b/src/gallium/auxiliary/gallivm/lp_bld_const.c index c8eaa8c3940..57843e9a60c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_const.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_const.c @@ -221,8 +221,16 @@ lp_build_undef(struct lp_type type) LLVMValueRef lp_build_zero(struct lp_type type) { - LLVMTypeRef vec_type = lp_build_vec_type(type); - return LLVMConstNull(vec_type); + if (type.length == 1) { + if (type.floating) + return LLVMConstReal(LLVMFloatType(), 0.0); + else + return LLVMConstInt(LLVMIntType(type.width), 0, 0); + } + else { + LLVMTypeRef vec_type = lp_build_vec_type(type); + return LLVMConstNull(vec_type); + } } @@ -255,7 +263,7 @@ lp_build_one(struct lp_type type) if(type.sign) /* TODO: Unfortunately this caused "Tried to create a shift operation * on a non-integer type!" */ - vec = LLVMConstLShr(vec, lp_build_int_const_scalar(type, 1)); + vec = LLVMConstLShr(vec, lp_build_const_int_vec(type, 1)); #endif return vec; @@ -264,13 +272,19 @@ lp_build_one(struct lp_type type) for(i = 1; i < type.length; ++i) elems[i] = elems[0]; - return LLVMConstVector(elems, type.length); + if (type.length == 1) + return elems[0]; + else + return LLVMConstVector(elems, type.length); } +/** + * Build constant-valued vector from a scalar value. + */ LLVMValueRef -lp_build_const_scalar(struct lp_type type, - double val) +lp_build_const_vec(struct lp_type type, + double val) { LLVMTypeRef elem_type = lp_build_elem_type(type); LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; @@ -295,7 +309,7 @@ lp_build_const_scalar(struct lp_type type, LLVMValueRef -lp_build_int_const_scalar(struct lp_type type, +lp_build_const_int_vec(struct lp_type type, long long val) { LLVMTypeRef elem_type = lp_build_int_elem_type(type); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_const.h b/src/gallium/auxiliary/gallivm/lp_bld_const.h index cb8e1c7b006..9ca2f0664eb 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_const.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_const.h @@ -37,9 +37,9 @@ #define LP_BLD_CONST_H -#include <llvm-c/Core.h> +#include "pipe/p_compiler.h" +#include "gallivm/lp_bld.h" -#include <pipe/p_compiler.h> struct lp_type; @@ -85,13 +85,11 @@ lp_build_one(struct lp_type type); LLVMValueRef -lp_build_const_scalar(struct lp_type type, - double val); +lp_build_const_vec(struct lp_type type, double val); LLVMValueRef -lp_build_int_const_scalar(struct lp_type type, - long long val); +lp_build_const_int_vec(struct lp_type type, long long val); LLVMValueRef diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c index f77cf787213..3f7f2ebde9c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c @@ -114,13 +114,13 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder, scale = (double)mask/ubound; bias = (double)((unsigned long long)1 << (mantissa - n)); - res = LLVMBuildMul(builder, src, lp_build_const_scalar(src_type, scale), ""); - res = LLVMBuildAdd(builder, res, lp_build_const_scalar(src_type, bias), ""); + res = LLVMBuildMul(builder, src, lp_build_const_vec(src_type, scale), ""); + res = LLVMBuildAdd(builder, res, lp_build_const_vec(src_type, bias), ""); res = LLVMBuildBitCast(builder, res, int_vec_type, ""); if(dst_width > n) { int shift = dst_width - n; - res = LLVMBuildShl(builder, res, lp_build_int_const_scalar(src_type, shift), ""); + res = LLVMBuildShl(builder, res, lp_build_const_int_vec(src_type, shift), ""); /* TODO: Fill in the empty lower bits for additional precision? */ /* YES: this fixes progs/trivial/tri-z-eq.c. @@ -130,21 +130,21 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder, #if 0 { LLVMValueRef msb; - msb = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, dst_width - 1), ""); - msb = LLVMBuildShl(builder, msb, lp_build_int_const_scalar(src_type, shift), ""); - msb = LLVMBuildSub(builder, msb, lp_build_int_const_scalar(src_type, 1), ""); + msb = LLVMBuildLShr(builder, res, lp_build_const_int_vec(src_type, dst_width - 1), ""); + msb = LLVMBuildShl(builder, msb, lp_build_const_int_vec(src_type, shift), ""); + msb = LLVMBuildSub(builder, msb, lp_build_const_int_vec(src_type, 1), ""); res = LLVMBuildOr(builder, res, msb, ""); } #elif 0 while(shift > 0) { - res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, n), ""), ""); + res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_const_int_vec(src_type, n), ""), ""); shift -= n; n *= 2; } #endif } else - res = LLVMBuildAnd(builder, res, lp_build_int_const_scalar(src_type, mask), ""); + res = LLVMBuildAnd(builder, res, lp_build_const_int_vec(src_type, mask), ""); return res; } @@ -183,10 +183,10 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder, if(src_width > mantissa) { int shift = src_width - mantissa; - res = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(dst_type, shift), ""); + res = LLVMBuildLShr(builder, res, lp_build_const_int_vec(dst_type, shift), ""); } - bias_ = lp_build_const_scalar(dst_type, bias); + bias_ = lp_build_const_vec(dst_type, bias); res = LLVMBuildOr(builder, res, @@ -195,7 +195,7 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder, res = LLVMBuildBitCast(builder, res, vec_type, ""); res = LLVMBuildSub(builder, res, bias_, ""); - res = LLVMBuildMul(builder, res, lp_build_const_scalar(dst_type, scale), ""); + res = LLVMBuildMul(builder, res, lp_build_const_vec(dst_type, scale), ""); return res; } @@ -251,7 +251,7 @@ lp_build_conv(LLVMBuilderRef builder, if(dst_min == 0.0) thres = bld.zero; else - thres = lp_build_const_scalar(src_type, dst_min); + thres = lp_build_const_vec(src_type, dst_min); for(i = 0; i < num_tmps; ++i) tmp[i] = lp_build_max(&bld, tmp[i], thres); } @@ -260,7 +260,7 @@ lp_build_conv(LLVMBuilderRef builder, if(dst_max == 1.0) thres = bld.one; else - thres = lp_build_const_scalar(src_type, dst_max); + thres = lp_build_const_vec(src_type, dst_max); for(i = 0; i < num_tmps; ++i) tmp[i] = lp_build_min(&bld, tmp[i], thres); } @@ -288,7 +288,7 @@ lp_build_conv(LLVMBuilderRef builder, LLVMTypeRef tmp_vec_type; if (dst_scale != 1.0) { - LLVMValueRef scale = lp_build_const_scalar(tmp_type, dst_scale); + LLVMValueRef scale = lp_build_const_vec(tmp_type, dst_scale); for(i = 0; i < num_tmps; ++i) tmp[i] = LLVMBuildMul(builder, tmp[i], scale, ""); } @@ -315,7 +315,7 @@ lp_build_conv(LLVMBuilderRef builder, /* FIXME: compensate different offsets too */ if(src_shift > dst_shift) { - LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, src_shift - dst_shift); + LLVMValueRef shift = lp_build_const_int_vec(tmp_type, src_shift - dst_shift); for(i = 0; i < num_tmps; ++i) if(src_type.sign) tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, ""); @@ -388,7 +388,7 @@ lp_build_conv(LLVMBuilderRef builder, } if (src_scale != 1.0) { - LLVMValueRef scale = lp_build_const_scalar(tmp_type, 1.0/src_scale); + LLVMValueRef scale = lp_build_const_vec(tmp_type, 1.0/src_scale); for(i = 0; i < num_tmps; ++i) tmp[i] = LLVMBuildMul(builder, tmp[i], scale, ""); } @@ -400,7 +400,7 @@ lp_build_conv(LLVMBuilderRef builder, /* FIXME: compensate different offsets too */ if(src_shift < dst_shift) { - LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, dst_shift - src_shift); + LLVMValueRef shift = lp_build_const_int_vec(tmp_type, dst_shift - src_shift); for(i = 0; i < num_tmps; ++i) tmp[i] = LLVMBuildShl(builder, tmp[i], shift, ""); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.h b/src/gallium/auxiliary/gallivm/lp_bld_conv.h index 948e68fae4f..628831c3ada 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.h @@ -37,7 +37,7 @@ #define LP_BLD_CONV_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.h b/src/gallium/auxiliary/gallivm/lp_bld_debug.h index 583e6132b4b..7b010cbdb09 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_debug.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.h @@ -30,7 +30,7 @@ #define LP_BLD_DEBUG_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include "pipe/p_compiler.h" #include "util/u_string.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_depth.c b/src/gallium/auxiliary/gallivm/lp_bld_depth.c index f08f8eb6d8b..cbc48f98651 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_depth.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_depth.c @@ -61,11 +61,104 @@ #include "util/u_format.h" #include "lp_bld_type.h" +#include "lp_bld_arit.h" #include "lp_bld_const.h" #include "lp_bld_logic.h" #include "lp_bld_flow.h" #include "lp_bld_debug.h" #include "lp_bld_depth.h" +#include "lp_bld_swizzle.h" + + + +/** + * Do the stencil test comparison (compare fb Z values against ref value. + * \param stencilVals vector of stencil values from framebuffer + * \param stencilRef the stencil reference value, replicated as a vector + * \return mask of pass/fail values + */ +static LLVMValueRef +lp_build_stencil_test(struct lp_build_context *bld, + const struct pipe_stencil_state *stencil, + LLVMValueRef stencilVals, + LLVMValueRef stencilRef) +{ + const unsigned stencilMax = 255; /* XXX fix */ + struct lp_type type = bld->type; + LLVMValueRef res; + + assert(stencil->enabled); + + if (stencil->valuemask != stencilMax) { + /* compute stencilRef = stencilRef & valuemask */ + LLVMValueRef valuemask = lp_build_const_int_vec(type, stencil->valuemask); + stencilRef = LLVMBuildAnd(bld->builder, stencilRef, valuemask, ""); + /* compute stencilVals = stencilVals & valuemask */ + stencilVals = LLVMBuildAnd(bld->builder, stencilVals, valuemask, ""); + } + + res = lp_build_compare(bld->builder, bld->type, stencil->func, + stencilVals, stencilRef); + + return res; +} + + +/** + * Apply the stencil operator (add/sub/keep/etc) to the given vector + * of stencil values. + * \return new stencil values vector + */ +static LLVMValueRef +lp_build_stencil_op(struct lp_build_context *bld, + unsigned stencil_op, + LLVMValueRef stencilRef, + const struct pipe_stencil_state *stencil, + LLVMValueRef stencilVals) + +{ + const unsigned stencilMax = 255; /* XXX fix */ + struct lp_type type = bld->type; + LLVMValueRef res; + LLVMValueRef max = lp_build_const_int_vec(type, stencilMax); + + switch (stencil_op) { + case PIPE_STENCIL_OP_KEEP: + res = stencilVals; + case PIPE_STENCIL_OP_ZERO: + res = bld->zero; + case PIPE_STENCIL_OP_REPLACE: + res = lp_build_broadcast_scalar(bld, stencilRef); + case PIPE_STENCIL_OP_INCR: + res = lp_build_add(bld, stencilVals, bld->one); + res = lp_build_min(bld, res, max); + case PIPE_STENCIL_OP_DECR: + res = lp_build_sub(bld, stencilVals, bld->one); + res = lp_build_max(bld, res, bld->zero); + case PIPE_STENCIL_OP_INCR_WRAP: + res = lp_build_add(bld, stencilVals, bld->one); + res = LLVMBuildAnd(bld->builder, res, max, ""); + case PIPE_STENCIL_OP_DECR_WRAP: + res = lp_build_sub(bld, stencilVals, bld->one); + res = LLVMBuildAnd(bld->builder, res, max, ""); + case PIPE_STENCIL_OP_INVERT: + res = LLVMBuildNot(bld->builder, stencilVals, ""); + default: + assert(0 && "bad stencil op mode"); + res = NULL; + } + + if (stencil->writemask != stencilMax) { + /* compute res = (res & mask) | (stencilVals & ~mask) */ + LLVMValueRef mask = lp_build_const_int_vec(type, stencil->writemask); + LLVMValueRef cmask = LLVMBuildNot(bld->builder, mask, "notWritemask"); + LLVMValueRef t1 = LLVMBuildAnd(bld->builder, res, mask, "t1"); + LLVMValueRef t2 = LLVMBuildAnd(bld->builder, stencilVals, cmask, "t2"); + res = LLVMBuildOr(bld->builder, t1, t2, "t1_or_t2"); + } + + return res; +} /** @@ -109,7 +202,14 @@ lp_depth_type(const struct util_format_description *format_desc, /** - * Depth test. + * Generate code for performing depth and/or stencil tests. + * We operate on a vector of values (typically a 2x2 quad). + * + * \param type the data type of the fragment depth/stencil values + * \param format_desc description of the depth/stencil surface + * \param mask the alive/dead pixel mask for the quad + * \param src the incoming depth/stencil values (a 2x2 quad) + * \param dst_ptr the outgoing/updated depth/stencil values */ void lp_build_depth_test(LLVMBuilderRef builder, @@ -126,6 +226,9 @@ lp_build_depth_test(LLVMBuilderRef builder, LLVMValueRef z_bitmask = NULL; LLVMValueRef test; + (void) lp_build_stencil_test; + (void) lp_build_stencil_op; + if(!state->enabled) return; @@ -185,11 +288,11 @@ lp_build_depth_test(LLVMBuilderRef builder, if(padding_left || padding_right) { const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1; const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1; - z_bitmask = lp_build_int_const_scalar(type, mask_left ^ mask_right); + z_bitmask = lp_build_const_int_vec(type, mask_left ^ mask_right); } if(padding_left) - src = LLVMBuildLShr(builder, src, lp_build_int_const_scalar(type, padding_left), ""); + src = LLVMBuildLShr(builder, src, lp_build_const_int_vec(type, padding_left), ""); if(padding_right) src = LLVMBuildAnd(builder, src, z_bitmask, ""); if(padding_left || padding_right) @@ -198,6 +301,7 @@ lp_build_depth_test(LLVMBuilderRef builder, lp_build_name(dst, "zsbuf.z"); + /* compare src Z to dst Z, returning 'pass' mask */ test = lp_build_cmp(&bld, state->func, src, dst); lp_build_mask_update(mask, test); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_depth.h b/src/gallium/auxiliary/gallivm/lp_bld_depth.h index 79d6981bb51..8375824cbf4 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_depth.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_depth.h @@ -36,7 +36,7 @@ #define LP_BLD_DEPTH_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct pipe_depth_state; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.c b/src/gallium/auxiliary/gallivm/lp_bld_flow.c index bc831389085..106fc03e46f 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.c @@ -308,7 +308,7 @@ lp_build_flow_scope_end(struct lp_build_flow_context *flow) * Note: this function has no dependencies on the flow code and could * be used elsewhere. */ -static LLVMBasicBlockRef +LLVMBasicBlockRef lp_build_insert_new_block(LLVMBuilderRef builder, const char *name) { LLVMBasicBlockRef current_block; @@ -648,7 +648,9 @@ lp_build_if(struct lp_build_if_state *ctx, ifthen->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), ""); /* add add the initial value of the var from the entry block */ - LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->entry_block, 1); + if (!LLVMIsUndef(*flow->variables[i])) + LLVMAddIncoming(ifthen->phi[i], flow->variables[i], + &ifthen->entry_block, 1); } /* create/insert true_block before merge_block */ @@ -695,18 +697,21 @@ lp_build_endif(struct lp_build_if_state *ctx) { struct lp_build_flow_context *flow = ctx->flow; struct lp_build_flow_if *ifthen; + LLVMBasicBlockRef curBlock = LLVMGetInsertBlock(ctx->builder); unsigned i; ifthen = &lp_build_flow_pop(flow, LP_BUILD_FLOW_IF)->ifthen; assert(ifthen); + /* Insert branch to the merge block from current block */ + LLVMBuildBr(ctx->builder, ifthen->merge_block); + if (ifthen->false_block) { LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block); /* for each variable, update the Phi node with a (variable, block) pair */ for (i = 0; i < flow->num_variables; i++) { assert(*flow->variables[i]); - LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->false_block, 1); - + LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &curBlock, 1); /* replace the variable ref with the phi function */ *flow->variables[i] = ifthen->phi[i]; } @@ -742,15 +747,18 @@ lp_build_endif(struct lp_build_if_state *ctx) ifthen->true_block, ifthen->merge_block); } - /* Append an unconditional Br(anch) instruction on the true_block */ - LLVMPositionBuilderAtEnd(ctx->builder, ifthen->true_block); - LLVMBuildBr(ctx->builder, ifthen->merge_block); + /* Insert branch from end of true_block to merge_block */ if (ifthen->false_block) { - /* Append an unconditional Br(anch) instruction on the false_block */ - LLVMPositionBuilderAtEnd(ctx->builder, ifthen->false_block); + /* Append an unconditional Br(anch) instruction on the true_block */ + LLVMPositionBuilderAtEnd(ctx->builder, ifthen->true_block); LLVMBuildBr(ctx->builder, ifthen->merge_block); } - + else { + /* No else clause. + * Note that we've already inserted the branch at the end of + * true_block. See the very first LLVMBuildBr() call in this function. + */ + } /* Resume building code at end of the ifthen->merge_block */ LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.h b/src/gallium/auxiliary/gallivm/lp_bld_flow.h index 4c225a0d4f9..c2b50e1b602 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.h @@ -35,7 +35,7 @@ #define LP_BLD_FLOW_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct lp_type; @@ -145,7 +145,9 @@ lp_build_else(struct lp_build_if_state *ctx); void lp_build_endif(struct lp_build_if_state *ctx); - + +LLVMBasicBlockRef +lp_build_insert_new_block(LLVMBuilderRef builder, const char *name); #endif /* !LP_BLD_FLOW_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format.h b/src/gallium/auxiliary/gallivm/lp_bld_format.h index 970bee379f5..73ab6de3f21 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_format.h @@ -34,7 +34,7 @@ * Pixel format helpers. */ -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include "pipe/p_format.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c index abb27e4c328..45ee4b12ced 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c @@ -114,10 +114,10 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, case UTIL_FORMAT_TYPE_UNSIGNED: if(type.floating) { if(start) - input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(type, start), ""); + input = LLVMBuildLShr(builder, input, lp_build_const_int_vec(type, start), ""); if(stop < format_desc->block.bits) { unsigned mask = ((unsigned long long)1 << width) - 1; - input = LLVMBuildAnd(builder, input, lp_build_int_const_scalar(type, mask), ""); + input = LLVMBuildAnd(builder, input, lp_build_const_int_vec(type, mask), ""); } if(format_desc->channel[chan].normalized) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_interp.c b/src/gallium/auxiliary/gallivm/lp_bld_interp.c index 2fc894017d8..09efb161217 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_interp.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_interp.c @@ -289,17 +289,17 @@ pos_update(struct lp_build_interp_soa_context *bld, int quad_index) /* top-right or bottom-right quad in block */ /* build x += xstep */ x = lp_build_add(&bld->base, x, - lp_build_const_scalar(bld->base.type, xstep)); + lp_build_const_vec(bld->base.type, xstep)); } if (quad_index == 2) { /* bottom-left quad in block */ /* build y += ystep */ y = lp_build_add(&bld->base, y, - lp_build_const_scalar(bld->base.type, ystep)); + lp_build_const_vec(bld->base.type, ystep)); /* build x -= xstep */ x = lp_build_sub(&bld->base, x, - lp_build_const_scalar(bld->base.type, xstep)); + lp_build_const_vec(bld->base.type, xstep)); } lp_build_name(x, "pos.x"); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_interp.h b/src/gallium/auxiliary/gallivm/lp_bld_interp.h index ca958cdf343..a4937bbb048 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_interp.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_interp.h @@ -41,7 +41,7 @@ #define LP_BLD_INTERP_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include "tgsi/tgsi_exec.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.h b/src/gallium/auxiliary/gallivm/lp_bld_intr.h index f813f27074b..977f7673228 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.h @@ -37,7 +37,7 @@ #define LP_BLD_INTR_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" /** diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.c b/src/gallium/auxiliary/gallivm/lp_bld_logic.c index 2726747eaea..e2e533fa7ec 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_logic.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.c @@ -42,6 +42,26 @@ #include "lp_bld_logic.h" +/* + * XXX + * + * Selection with vector conditional like + * + * select <4 x i1> %C, %A, %B + * + * is valid IR (e.g. llvm/test/Assembler/vector-select.ll), but it is not + * supported on any backend. + * + * Expanding the boolean vector to full SIMD register width, as in + * + * sext <4 x i1> %C to <4 x i32> + * + * is valid and supported (e.g., llvm/test/CodeGen/X86/vec_compare.ll), but + * it causes assertion failures in LLVM 2.6. It appears to work correctly on + * LLVM 2.7. + */ + + /** * Build code to compare two values 'a' and 'b' of 'type' using the given func. * \param func one of PIPE_FUNC_x @@ -54,13 +74,11 @@ lp_build_compare(LLVMBuilderRef builder, LLVMValueRef a, LLVMValueRef b) { - LLVMTypeRef vec_type = lp_build_vec_type(type); LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); LLVMValueRef zeros = LLVMConstNull(int_vec_type); LLVMValueRef ones = LLVMConstAllOnes(int_vec_type); LLVMValueRef cond; LLVMValueRef res; - unsigned i; assert(func >= PIPE_FUNC_NEVER); assert(func <= PIPE_FUNC_ALWAYS); @@ -74,10 +92,12 @@ lp_build_compare(LLVMBuilderRef builder, /* XXX: It is not clear if we should use the ordered or unordered operators */ +#if HAVE_LLVM < 0x0207 #if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) if(type.width * type.length == 128) { if(type.floating && util_cpu_caps.has_sse) { /* float[4] comparison */ + LLVMTypeRef vec_type = lp_build_vec_type(type); LLVMValueRef args[3]; unsigned cc; boolean swap; @@ -147,6 +167,7 @@ lp_build_compare(LLVMBuilderRef builder, const char *pcmpgt; LLVMValueRef args[2]; LLVMValueRef res; + LLVMTypeRef vec_type = lp_build_vec_type(type); switch (type.width) { case 8: @@ -172,7 +193,7 @@ lp_build_compare(LLVMBuilderRef builder, if(table[func].gt && ((type.width == 8 && type.sign) || (type.width != 8 && !type.sign))) { - LLVMValueRef msb = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); + LLVMValueRef msb = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1)); a = LLVMBuildXor(builder, a, msb, ""); b = LLVMBuildXor(builder, b, msb, ""); } @@ -198,8 +219,9 @@ lp_build_compare(LLVMBuilderRef builder, return res; } - } + } /* if (type.width * type.length == 128) */ #endif +#endif /* HAVE_LLVM < 0x0207 */ if(type.floating) { LLVMRealPredicate op; @@ -233,25 +255,33 @@ lp_build_compare(LLVMBuilderRef builder, return lp_build_undef(type); } -#if 0 - /* XXX: Although valid IR, no LLVM target currently support this */ +#if HAVE_LLVM >= 0x0207 cond = LLVMBuildFCmp(builder, op, a, b, ""); - res = LLVMBuildSelect(builder, cond, ones, zeros, ""); + res = LLVMBuildSExt(builder, cond, int_vec_type, ""); #else - debug_printf("%s: warning: using slow element-wise vector comparison\n", - __FUNCTION__); - res = LLVMGetUndef(int_vec_type); - for(i = 0; i < type.length; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - cond = LLVMBuildFCmp(builder, op, - LLVMBuildExtractElement(builder, a, index, ""), - LLVMBuildExtractElement(builder, b, index, ""), - ""); - cond = LLVMBuildSelect(builder, cond, - LLVMConstExtractElement(ones, index), - LLVMConstExtractElement(zeros, index), - ""); - res = LLVMBuildInsertElement(builder, res, cond, index, ""); + if (type.length == 1) { + cond = LLVMBuildFCmp(builder, op, a, b, ""); + res = LLVMBuildSExt(builder, cond, int_vec_type, ""); + } + else { + unsigned i; + + res = LLVMGetUndef(int_vec_type); + + debug_printf("%s: warning: using slow element-wise float" + " vector comparison\n", __FUNCTION__); + for (i = 0; i < type.length; ++i) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + cond = LLVMBuildFCmp(builder, op, + LLVMBuildExtractElement(builder, a, index, ""), + LLVMBuildExtractElement(builder, b, index, ""), + ""); + cond = LLVMBuildSelect(builder, cond, + LLVMConstExtractElement(ones, index), + LLVMConstExtractElement(zeros, index), + ""); + res = LLVMBuildInsertElement(builder, res, cond, index, ""); + } } #endif } @@ -281,25 +311,34 @@ lp_build_compare(LLVMBuilderRef builder, return lp_build_undef(type); } -#if 0 - /* XXX: Although valid IR, no LLVM target currently support this */ +#if HAVE_LLVM >= 0x0207 cond = LLVMBuildICmp(builder, op, a, b, ""); - res = LLVMBuildSelect(builder, cond, ones, zeros, ""); + res = LLVMBuildSExt(builder, cond, int_vec_type, ""); #else - debug_printf("%s: warning: using slow element-wise int vector comparison\n", - __FUNCTION__); - res = LLVMGetUndef(int_vec_type); - for(i = 0; i < type.length; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - cond = LLVMBuildICmp(builder, op, - LLVMBuildExtractElement(builder, a, index, ""), - LLVMBuildExtractElement(builder, b, index, ""), - ""); - cond = LLVMBuildSelect(builder, cond, - LLVMConstExtractElement(ones, index), - LLVMConstExtractElement(zeros, index), - ""); - res = LLVMBuildInsertElement(builder, res, cond, index, ""); + if (type.length == 1) { + cond = LLVMBuildICmp(builder, op, a, b, ""); + res = LLVMBuildSExt(builder, cond, int_vec_type, ""); + } + else { + unsigned i; + + res = LLVMGetUndef(int_vec_type); + + debug_printf("%s: warning: using slow element-wise int" + " vector comparison\n", __FUNCTION__); + + for(i = 0; i < type.length; ++i) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + cond = LLVMBuildICmp(builder, op, + LLVMBuildExtractElement(builder, a, index, ""), + LLVMBuildExtractElement(builder, b, index, ""), + ""); + cond = LLVMBuildSelect(builder, cond, + LLVMConstExtractElement(ones, index), + LLVMConstExtractElement(zeros, index), + ""); + res = LLVMBuildInsertElement(builder, res, cond, index, ""); + } } #endif } @@ -326,6 +365,8 @@ lp_build_cmp(struct lp_build_context *bld, /** * Return mask ? a : b; + * + * mask is a bitwise mask, composed of 0 or ~0 for each element. */ LLVMValueRef lp_build_select(struct lp_build_context *bld, @@ -339,26 +380,32 @@ lp_build_select(struct lp_build_context *bld, if(a == b) return a; - if(type.floating) { - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); - b = LLVMBuildBitCast(bld->builder, b, int_vec_type, ""); + if (type.length == 1) { + mask = LLVMBuildTrunc(bld->builder, mask, LLVMInt1Type(), ""); + res = LLVMBuildSelect(bld->builder, mask, a, b, ""); } + else { + if(type.floating) { + LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); + a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); + b = LLVMBuildBitCast(bld->builder, b, int_vec_type, ""); + } - a = LLVMBuildAnd(bld->builder, a, mask, ""); + a = LLVMBuildAnd(bld->builder, a, mask, ""); - /* This often gets translated to PANDN, but sometimes the NOT is - * pre-computed and stored in another constant. The best strategy depends - * on available registers, so it is not a big deal -- hopefully LLVM does - * the right decision attending the rest of the program. - */ - b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), ""); + /* This often gets translated to PANDN, but sometimes the NOT is + * pre-computed and stored in another constant. The best strategy depends + * on available registers, so it is not a big deal -- hopefully LLVM does + * the right decision attending the rest of the program. + */ + b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), ""); - res = LLVMBuildOr(bld->builder, a, b, ""); + res = LLVMBuildOr(bld->builder, a, b, ""); - if(type.floating) { - LLVMTypeRef vec_type = lp_build_vec_type(type); - res = LLVMBuildBitCast(bld->builder, res, vec_type, ""); + if(type.floating) { + LLVMTypeRef vec_type = lp_build_vec_type(type); + res = LLVMBuildBitCast(bld->builder, res, vec_type, ""); + } } return res; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.h b/src/gallium/auxiliary/gallivm/lp_bld_logic.h index a399ebf39ef..d849d29e95d 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_logic.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.h @@ -37,7 +37,7 @@ #define LP_BLD_LOGIC_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_pack.c b/src/gallium/auxiliary/gallivm/lp_bld_pack.c index bc360ad77ad..2daa8a3b582 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_pack.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_pack.c @@ -164,7 +164,7 @@ lp_build_unpack2(LLVMBuilderRef builder, if(dst_type.sign && src_type.sign) { /* Replicate the sign bit in the most significant bits */ - msb = LLVMBuildAShr(builder, src, lp_build_int_const_scalar(src_type, src_type.width - 1), ""); + msb = LLVMBuildAShr(builder, src, lp_build_const_int_vec(src_type, src_type.width - 1), ""); } else /* Most significant bits always zero */ @@ -256,7 +256,9 @@ lp_build_pack2(LLVMBuilderRef builder, LLVMValueRef lo, LLVMValueRef hi) { +#if HAVE_LLVM < 0x0207 LLVMTypeRef src_vec_type = lp_build_vec_type(src_type); +#endif LLVMTypeRef dst_vec_type = lp_build_vec_type(dst_type); LLVMValueRef shuffle; LLVMValueRef res; @@ -272,11 +274,14 @@ lp_build_pack2(LLVMBuilderRef builder, switch(src_type.width) { case 32: if(dst_type.sign) { +#if HAVE_LLVM >= 0x0207 + res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", dst_vec_type, lo, hi); +#else res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", src_vec_type, lo, hi); +#endif } else { if (util_cpu_caps.has_sse4_1) { - /* PACKUSDW is the only instrinsic with a consistent signature */ return lp_build_intrinsic_binary(builder, "llvm.x86.sse41.packusdw", dst_vec_type, lo, hi); } else { @@ -288,9 +293,17 @@ lp_build_pack2(LLVMBuilderRef builder, case 16: if(dst_type.sign) +#if HAVE_LLVM >= 0x0207 + res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packsswb.128", dst_vec_type, lo, hi); +#else res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packsswb.128", src_vec_type, lo, hi); +#endif else +#if HAVE_LLVM >= 0x0207 + res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packuswb.128", dst_vec_type, lo, hi); +#else res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packuswb.128", src_vec_type, lo, hi); +#endif break; default: @@ -348,7 +361,7 @@ lp_build_packs2(LLVMBuilderRef builder, if(clamp) { struct lp_build_context bld; unsigned dst_bits = dst_type.sign ? dst_type.width - 1 : dst_type.width; - LLVMValueRef dst_max = lp_build_int_const_scalar(src_type, ((unsigned long long)1 << dst_bits) - 1); + LLVMValueRef dst_max = lp_build_const_int_vec(src_type, ((unsigned long long)1 << dst_bits) - 1); lp_build_context_init(&bld, builder, src_type); lo = lp_build_min(&bld, lo, dst_max); hi = lp_build_min(&bld, hi, dst_max); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_pack.h b/src/gallium/auxiliary/gallivm/lp_bld_pack.h index fb2a34984a4..41adeed220c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_pack.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_pack.h @@ -37,7 +37,7 @@ #define LP_BLD_PACK_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index 6a026e468e1..bb76ad4c6bf 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -62,6 +62,18 @@ lp_sampler_static_state(struct lp_sampler_static_state *state, if(!sampler) return; + /* + * We don't copy sampler state over unless it is actually enabled, to avoid + * spurious recompiles, as the sampler static state is part of the shader + * key. + * + * Ideally the state tracker or cso_cache module would make all state + * canonical, but until that happens it's better to be safe than sorry here. + * + * XXX: Actually there's much more than can be done here, especially + * regarding 1D/2D/3D/CUBE textures, wrap modes, etc. + */ + state->format = texture->format; state->target = texture->target; state->pot_width = util_is_pot(texture->width0); @@ -72,10 +84,18 @@ lp_sampler_static_state(struct lp_sampler_static_state *state, state->wrap_t = sampler->wrap_t; state->wrap_r = sampler->wrap_r; state->min_img_filter = sampler->min_img_filter; - state->min_mip_filter = sampler->min_mip_filter; state->mag_img_filter = sampler->mag_img_filter; + if (texture->last_level) { + state->min_mip_filter = sampler->min_mip_filter; + } else { + state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + } + state->compare_mode = sampler->compare_mode; - state->compare_func = sampler->compare_func; + if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE) { + state->compare_func = sampler->compare_func; + } + state->normalized_coords = sampler->normalized_coords; state->lod_bias = sampler->lod_bias; state->min_lod = sampler->min_lod; @@ -139,20 +159,21 @@ lp_build_gather(LLVMBuilderRef builder, /** * Compute the offset of a pixel. * - * x, y, y_stride are vectors + * x, y, z, y_stride, z_stride are vectors */ LLVMValueRef lp_build_sample_offset(struct lp_build_context *bld, const struct util_format_description *format_desc, LLVMValueRef x, LLVMValueRef y, + LLVMValueRef z, LLVMValueRef y_stride, - LLVMValueRef data_ptr) + LLVMValueRef z_stride) { LLVMValueRef x_stride; LLVMValueRef offset; - x_stride = lp_build_const_scalar(bld->type, format_desc->block.bits/8); + x_stride = lp_build_const_vec(bld->type, format_desc->block.bits/8); if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { LLVMValueRef x_lo, x_hi; @@ -163,6 +184,10 @@ lp_build_sample_offset(struct lp_build_context *bld, LLVMValueRef y_offset_lo, y_offset_hi; LLVMValueRef offset_lo, offset_hi; + /* XXX 1D & 3D addressing not done yet */ + assert(!z); + assert(!z_stride); + x_lo = LLVMBuildAnd(bld->builder, x, bld->one, ""); y_lo = LLVMBuildAnd(bld->builder, y, bld->one, ""); @@ -170,9 +195,9 @@ lp_build_sample_offset(struct lp_build_context *bld, y_hi = LLVMBuildLShr(bld->builder, y, bld->one, ""); x_stride_lo = x_stride; - y_stride_lo = lp_build_const_scalar(bld->type, 2*format_desc->block.bits/8); + y_stride_lo = lp_build_const_vec(bld->type, 2*format_desc->block.bits/8); - x_stride_hi = lp_build_const_scalar(bld->type, 4*format_desc->block.bits/8); + x_stride_hi = lp_build_const_vec(bld->type, 4*format_desc->block.bits/8); y_stride_hi = LLVMBuildShl(bld->builder, y_stride, bld->one, ""); x_offset_lo = lp_build_mul(bld, x_lo, x_stride_lo); @@ -186,13 +211,17 @@ lp_build_sample_offset(struct lp_build_context *bld, offset = lp_build_add(bld, offset_hi, offset_lo); } else { - LLVMValueRef x_offset; - LLVMValueRef y_offset; + offset = lp_build_mul(bld, x, x_stride); - x_offset = lp_build_mul(bld, x, x_stride); - y_offset = lp_build_mul(bld, y, y_stride); + if (y && y_stride) { + LLVMValueRef y_offset = lp_build_mul(bld, y, y_stride); + offset = lp_build_add(bld, offset, y_offset); + } - offset = lp_build_add(bld, x_offset, y_offset); + if (z && z_stride) { + LLVMValueRef z_offset = lp_build_mul(bld, z, z_stride); + offset = lp_build_add(bld, offset, z_offset); + } } return offset; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index 5ba0925bb69..92f3c57435a 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -36,7 +36,7 @@ #define LP_BLD_SAMPLE_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct pipe_texture; struct pipe_sampler_state; @@ -113,9 +113,9 @@ struct lp_sampler_dynamic_state unsigned unit); LLVMValueRef - (*stride)( struct lp_sampler_dynamic_state *state, - LLVMBuilderRef builder, - unsigned unit); + (*row_stride)( struct lp_sampler_dynamic_state *state, + LLVMBuilderRef builder, + unsigned unit); LLVMValueRef (*data_ptr)( struct lp_sampler_dynamic_state *state, @@ -148,8 +148,9 @@ lp_build_sample_offset(struct lp_build_context *bld, const struct util_format_description *format_desc, LLVMValueRef x, LLVMValueRef y, + LLVMValueRef z, LLVMValueRef y_stride, - LLVMValueRef data_ptr); + LLVMValueRef z_stride); void diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 9058f76c1df..995c016b9dd 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -48,6 +48,7 @@ #include "lp_bld_logic.h" #include "lp_bld_swizzle.h" #include "lp_bld_pack.h" +#include "lp_bld_flow.h" #include "lp_bld_format.h" #include "lp_bld_sample.h" @@ -65,6 +66,14 @@ struct lp_build_sample_context const struct util_format_description *format_desc; + /** regular scalar float type */ + struct lp_type float_type; + struct lp_build_context float_bld; + + /** regular scalar float type */ + struct lp_type int_type; + struct lp_build_context int_bld; + /** Incoming coordinates type and build context */ struct lp_type coord_type; struct lp_build_context coord_bld; @@ -108,9 +117,78 @@ wrap_mode_uses_border_color(unsigned mode) } +static LLVMValueRef +lp_build_get_mipmap_level(struct lp_build_sample_context *bld, + LLVMValueRef data_array, LLVMValueRef level) +{ + LLVMValueRef indexes[2], data_ptr; + indexes[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); + indexes[1] = level; + data_ptr = LLVMBuildGEP(bld->builder, data_array, indexes, 2, ""); + data_ptr = LLVMBuildLoad(bld->builder, data_ptr, ""); + return data_ptr; +} + + +static LLVMValueRef +lp_build_get_const_mipmap_level(struct lp_build_sample_context *bld, + LLVMValueRef data_array, int level) +{ + LLVMValueRef lvl = LLVMConstInt(LLVMInt32Type(), level, 0); + return lp_build_get_mipmap_level(bld, data_array, lvl); +} + + +/** + * Dereference stride_array[mipmap_level] array to get a stride. + * Return stride as a vector. + */ +static LLVMValueRef +lp_build_get_level_stride_vec(struct lp_build_sample_context *bld, + LLVMValueRef stride_array, LLVMValueRef level) +{ + LLVMValueRef indexes[2], stride; + indexes[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); + indexes[1] = level; + stride = LLVMBuildGEP(bld->builder, stride_array, indexes, 2, ""); + stride = LLVMBuildLoad(bld->builder, stride, ""); + stride = lp_build_broadcast_scalar(&bld->int_coord_bld, stride); + return stride; +} + + +/** Dereference stride_array[0] array to get a stride (as vector). */ +static LLVMValueRef +lp_build_get_const_level_stride_vec(struct lp_build_sample_context *bld, + LLVMValueRef stride_array, int level) +{ + LLVMValueRef lvl = LLVMConstInt(LLVMInt32Type(), level, 0); + return lp_build_get_level_stride_vec(bld, stride_array, lvl); +} + + +static int +texture_dims(enum pipe_texture_target tex) +{ + switch (tex) { + case PIPE_TEXTURE_1D: + return 1; + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_CUBE: + return 2; + case PIPE_TEXTURE_3D: + return 3; + default: + assert(0 && "bad texture target in texture_dims()"); + return 2; + } +} + + /** - * Gen code to fetch a texel from a texture at int coords (x, y). + * Generate code to fetch a texel from a texture at int coords (x, y, z). + * The computation depends on whether the texture is 1D, 2D or 3D. * The result, texel, will be: * texel[0] = red values * texel[1] = green values @@ -121,12 +199,16 @@ static void lp_build_sample_texel_soa(struct lp_build_sample_context *bld, LLVMValueRef width, LLVMValueRef height, + LLVMValueRef depth, LLVMValueRef x, LLVMValueRef y, + LLVMValueRef z, LLVMValueRef y_stride, + LLVMValueRef z_stride, LLVMValueRef data_ptr, LLVMValueRef *texel) { + const int dims = texture_dims(bld->static_state->target); struct lp_build_context *int_coord_bld = &bld->int_coord_bld; LLVMValueRef offset; LLVMValueRef packed; @@ -140,7 +222,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2"); } - if (wrap_mode_uses_border_color(bld->static_state->wrap_t)) { + if (dims >= 2 && wrap_mode_uses_border_color(bld->static_state->wrap_t)) { LLVMValueRef b1, b2; b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, y, int_coord_bld->zero); b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, y, height); @@ -153,6 +235,19 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, } } + if (dims == 3 && wrap_mode_uses_border_color(bld->static_state->wrap_r)) { + LLVMValueRef b1, b2; + b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, z, int_coord_bld->zero); + b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, z, depth); + if (use_border) { + use_border = LLVMBuildOr(bld->builder, use_border, b1, "ub_or_b1"); + use_border = LLVMBuildOr(bld->builder, use_border, b2, "ub_or_b2"); + } + else { + use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2"); + } + } + /* * Note: if we find an app which frequently samples the texture border * we might want to implement a true conditional here to avoid sampling @@ -168,11 +263,10 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, * the texel color results with the border color. */ - /* convert x,y coords to linear offset from start of texture, in bytes */ + /* convert x,y,z coords to linear offset from start of texture, in bytes */ offset = lp_build_sample_offset(&bld->uint_coord_bld, bld->format_desc, - x, y, y_stride, - data_ptr); + x, y, z, y_stride, z_stride); assert(bld->format_desc->block.width == 1); assert(bld->format_desc->block.height == 1); @@ -185,6 +279,8 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, bld->texel_type.width, data_ptr, offset); + texel[0] = texel[1] = texel[2] = texel[3] = NULL; + /* convert texels to float rgba */ lp_build_unpack_rgba_soa(bld->builder, bld->format_desc, @@ -196,7 +292,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, int chan; for (chan = 0; chan < 4; chan++) { LLVMValueRef border_chan = - lp_build_const_scalar(bld->texel_type, + lp_build_const_vec(bld->texel_type, bld->static_state->border_color[chan]); texel[chan] = lp_build_select(&bld->texel_bld, use_border, border_chan, texel[chan]); @@ -210,19 +306,22 @@ lp_build_sample_packed(struct lp_build_sample_context *bld, LLVMValueRef x, LLVMValueRef y, LLVMValueRef y_stride, - LLVMValueRef data_ptr) + LLVMValueRef data_array) { LLVMValueRef offset; + LLVMValueRef data_ptr; offset = lp_build_sample_offset(&bld->uint_coord_bld, bld->format_desc, - x, y, y_stride, - data_ptr); + x, y, NULL, y_stride, NULL); assert(bld->format_desc->block.width == 1); assert(bld->format_desc->block.height == 1); assert(bld->format_desc->block.bits <= bld->texel_type.width); + /* get pointer to mipmap level 0 data */ + data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0); + return lp_build_gather(bld->builder, bld->texel_type.length, bld->format_desc->block.bits, @@ -358,8 +457,8 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, struct lp_build_context *coord_bld = &bld->coord_bld; struct lp_build_context *int_coord_bld = &bld->int_coord_bld; struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld; - LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0); - LLVMValueRef half = lp_build_const_scalar(coord_bld->type, 0.5); + LLVMValueRef two = lp_build_const_vec(coord_bld->type, 2.0); + LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5); LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length); LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one); LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one); @@ -413,7 +512,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, else { LLVMValueRef min, max; /* clamp to [0.5, length - 0.5] */ - min = lp_build_const_scalar(coord_bld->type, 0.5F); + min = lp_build_const_vec(coord_bld->type, 0.5F); max = lp_build_sub(coord_bld, length_f, min); coord = lp_build_clamp(coord_bld, coord, min, max); } @@ -434,7 +533,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, if (bld->static_state->normalized_coords) { /* min = -1.0 / (2 * length) = -0.5 / length */ min = lp_build_mul(coord_bld, - lp_build_const_scalar(coord_bld->type, -0.5F), + lp_build_const_vec(coord_bld->type, -0.5F), lp_build_rcp(coord_bld, length_f)); /* max = 1.0 - min */ max = lp_build_sub(coord_bld, coord_bld->one, min); @@ -446,7 +545,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, } else { /* clamp to [-0.5, length + 0.5] */ - min = lp_build_const_scalar(coord_bld->type, -0.5F); + min = lp_build_const_vec(coord_bld->type, -0.5F); max = lp_build_sub(coord_bld, length_f, min); coord = lp_build_clamp(coord_bld, coord, min, max); coord = lp_build_sub(coord_bld, coord, half); @@ -521,7 +620,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, LLVMValueRef min, max; /* min = -1.0 / (2 * length) = -0.5 / length */ min = lp_build_mul(coord_bld, - lp_build_const_scalar(coord_bld->type, -0.5F), + lp_build_const_vec(coord_bld->type, -0.5F), lp_build_rcp(coord_bld, length_f)); /* max = 1.0 - min */ max = lp_build_sub(coord_bld, coord_bld->one, min); @@ -566,7 +665,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, struct lp_build_context *coord_bld = &bld->coord_bld; struct lp_build_context *int_coord_bld = &bld->int_coord_bld; struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld; - LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0); + LLVMValueRef two = lp_build_const_vec(coord_bld->type, 2.0); LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length); LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one); LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one); @@ -609,7 +708,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, } else { /* clamp to [0.5, length - 0.5] */ - min = lp_build_const_scalar(coord_bld->type, 0.5F); + min = lp_build_const_vec(coord_bld->type, 0.5F); max = lp_build_sub(coord_bld, length_f, min); } /* coord = clamp(coord, min, max) */ @@ -625,7 +724,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, if (bld->static_state->normalized_coords) { /* min = -1.0 / (2 * length) = -0.5 / length */ min = lp_build_mul(coord_bld, - lp_build_const_scalar(coord_bld->type, -0.5F), + lp_build_const_vec(coord_bld->type, -0.5F), lp_build_rcp(coord_bld, length_f)); /* max = length - min */ max = lp_build_sub(coord_bld, length_f, min); @@ -634,7 +733,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, } else { /* clamp to [-0.5, length + 0.5] */ - min = lp_build_const_scalar(coord_bld->type, -0.5F); + min = lp_build_const_vec(coord_bld->type, -0.5F); max = lp_build_sub(coord_bld, length_f, min); } /* coord = clamp(coord, min, max) */ @@ -711,83 +810,905 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, /** - * Sample 2D texture with nearest filtering. + * Codegen equivalent for u_minify(). + * Return max(1, base_size >> level); + */ +static LLVMValueRef +lp_build_minify(struct lp_build_sample_context *bld, + LLVMValueRef base_size, + LLVMValueRef level) +{ + LLVMValueRef size = LLVMBuildAShr(bld->builder, base_size, level, "minify"); + size = lp_build_max(&bld->int_coord_bld, size, bld->int_coord_bld.one); + return size; +} + + +/** + * Generate code to compute texture level of detail (lambda). + * \param s vector of texcoord s values + * \param t vector of texcoord t values + * \param r vector of texcoord r values + * \param width scalar int texture width + * \param height scalar int texture height + * \param depth scalar int texture depth + */ +static LLVMValueRef +lp_build_lod_selector(struct lp_build_sample_context *bld, + LLVMValueRef s, + LLVMValueRef t, + LLVMValueRef r, + LLVMValueRef width, + LLVMValueRef height, + LLVMValueRef depth) + +{ + if (bld->static_state->min_lod == bld->static_state->max_lod) { + /* User is forcing sampling from a particular mipmap level. + * This is hit during mipmap generation. + */ + return LLVMConstReal(LLVMFloatType(), bld->static_state->min_lod); + } + else { + const int dims = texture_dims(bld->static_state->target); + struct lp_build_context *float_bld = &bld->float_bld; + LLVMValueRef lod_bias = LLVMConstReal(LLVMFloatType(), + bld->static_state->lod_bias); + LLVMValueRef min_lod = LLVMConstReal(LLVMFloatType(), + bld->static_state->min_lod); + LLVMValueRef max_lod = LLVMConstReal(LLVMFloatType(), + bld->static_state->max_lod); + + LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0); + LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0); + LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0); + + LLVMValueRef s0, s1, s2; + LLVMValueRef t0, t1, t2; + LLVMValueRef r0, r1, r2; + LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy; + LLVMValueRef rho, lod; + + /* + * dsdx = abs(s[1] - s[0]); + * dsdy = abs(s[2] - s[0]); + * dtdx = abs(t[1] - t[0]); + * dtdy = abs(t[2] - t[0]); + * drdx = abs(r[1] - r[0]); + * drdy = abs(r[2] - r[0]); + * XXX we're assuming a four-element quad in 2x2 layout here. + */ + s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0"); + s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1"); + s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2"); + dsdx = LLVMBuildSub(bld->builder, s1, s0, ""); + dsdx = lp_build_abs(float_bld, dsdx); + dsdy = LLVMBuildSub(bld->builder, s2, s0, ""); + dsdy = lp_build_abs(float_bld, dsdy); + if (dims > 1) { + t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0"); + t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1"); + t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2"); + dtdx = LLVMBuildSub(bld->builder, t1, t0, ""); + dtdx = lp_build_abs(float_bld, dtdx); + dtdy = LLVMBuildSub(bld->builder, t2, t0, ""); + dtdy = lp_build_abs(float_bld, dtdy); + if (dims > 2) { + r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0"); + r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1"); + r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2"); + drdx = LLVMBuildSub(bld->builder, r1, r0, ""); + drdx = lp_build_abs(float_bld, drdx); + drdy = LLVMBuildSub(bld->builder, r2, r0, ""); + drdy = lp_build_abs(float_bld, drdy); + } + } + + /* Compute rho = max of all partial derivatives scaled by texture size. + * XXX this could be vectorized somewhat + */ + rho = LLVMBuildMul(bld->builder, + lp_build_max(float_bld, dsdx, dsdy), + lp_build_int_to_float(float_bld, width), ""); + if (dims > 1) { + LLVMValueRef max; + max = LLVMBuildMul(bld->builder, + lp_build_max(float_bld, dtdx, dtdy), + lp_build_int_to_float(float_bld, height), ""); + rho = lp_build_max(float_bld, rho, max); + if (dims > 2) { + max = LLVMBuildMul(bld->builder, + lp_build_max(float_bld, drdx, drdy), + lp_build_int_to_float(float_bld, depth), ""); + rho = lp_build_max(float_bld, rho, max); + } + } + + /* compute lod = log2(rho) */ + lod = lp_build_log2(float_bld, rho); + + /* add lod bias */ + lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "LOD bias"); + + /* clamp lod */ + lod = lp_build_clamp(float_bld, lod, min_lod, max_lod); + + return lod; + } +} + + +/** + * For PIPE_TEX_MIPFILTER_NEAREST, convert float LOD to integer + * mipmap level index. + * Note: this is all scalar code. + * \param lod scalar float texture level of detail + * \param level_out returns integer */ static void -lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld, - LLVMValueRef s, - LLVMValueRef t, - LLVMValueRef width, - LLVMValueRef height, - LLVMValueRef stride, - LLVMValueRef data_ptr, - LLVMValueRef *texel) +lp_build_nearest_mip_level(struct lp_build_sample_context *bld, + unsigned unit, + LLVMValueRef lod, + LLVMValueRef *level_out) { - LLVMValueRef x, y; + struct lp_build_context *float_bld = &bld->float_bld; + struct lp_build_context *int_bld = &bld->int_bld; + LLVMValueRef last_level, level; - x = lp_build_sample_wrap_nearest(bld, s, width, - bld->static_state->pot_width, - bld->static_state->wrap_s); - y = lp_build_sample_wrap_nearest(bld, t, height, - bld->static_state->pot_height, - bld->static_state->wrap_t); + LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, 0); - lp_build_name(x, "tex.x.wrapped"); - lp_build_name(y, "tex.y.wrapped"); + last_level = bld->dynamic_state->last_level(bld->dynamic_state, + bld->builder, unit); + + /* convert float lod to integer */ + level = lp_build_iround(float_bld, lod); - lp_build_sample_texel_soa(bld, width, height, x, y, stride, data_ptr, texel); + /* clamp level to legal range of levels */ + *level_out = lp_build_clamp(int_bld, level, zero, last_level); } /** - * Sample 2D texture with bilinear filtering. + * For PIPE_TEX_MIPFILTER_LINEAR, convert float LOD to integer to + * two (adjacent) mipmap level indexes. Later, we'll sample from those + * two mipmap levels and interpolate between them. */ static void -lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld, +lp_build_linear_mip_levels(struct lp_build_sample_context *bld, + unsigned unit, + LLVMValueRef lod, + LLVMValueRef *level0_out, + LLVMValueRef *level1_out, + LLVMValueRef *weight_out) +{ + struct lp_build_context *float_bld = &bld->float_bld; + struct lp_build_context *int_bld = &bld->int_bld; + LLVMValueRef last_level, level; + + last_level = bld->dynamic_state->last_level(bld->dynamic_state, + bld->builder, unit); + + /* convert float lod to integer */ + level = lp_build_ifloor(float_bld, lod); + + /* compute level 0 and clamp to legal range of levels */ + *level0_out = lp_build_clamp(int_bld, level, + int_bld->zero, + last_level); + /* compute level 1 and clamp to legal range of levels */ + *level1_out = lp_build_add(int_bld, *level0_out, int_bld->one); + *level1_out = lp_build_min(int_bld, *level1_out, last_level); + + *weight_out = lp_build_fract(float_bld, lod); +} + + +/** + * Generate code to sample a mipmap level with nearest filtering. + * If sampling a cube texture, r = cube face in [0,5]. + */ +static void +lp_build_sample_image_nearest(struct lp_build_sample_context *bld, + LLVMValueRef width_vec, + LLVMValueRef height_vec, + LLVMValueRef depth_vec, + LLVMValueRef row_stride_vec, + LLVMValueRef img_stride_vec, + LLVMValueRef data_ptr, LLVMValueRef s, LLVMValueRef t, - LLVMValueRef width, - LLVMValueRef height, - LLVMValueRef stride, - LLVMValueRef data_ptr, - LLVMValueRef *texel) + LLVMValueRef r, + LLVMValueRef colors_out[4]) { - LLVMValueRef s_fpart; - LLVMValueRef t_fpart; - LLVMValueRef x0, x1; - LLVMValueRef y0, y1; + const int dims = texture_dims(bld->static_state->target); + LLVMValueRef x, y, z; + + /* + * Compute integer texcoords. + */ + x = lp_build_sample_wrap_nearest(bld, s, width_vec, + bld->static_state->pot_width, + bld->static_state->wrap_s); + lp_build_name(x, "tex.x.wrapped"); + + if (dims >= 2) { + y = lp_build_sample_wrap_nearest(bld, t, height_vec, + bld->static_state->pot_height, + bld->static_state->wrap_t); + lp_build_name(y, "tex.y.wrapped"); + + if (dims == 3) { + z = lp_build_sample_wrap_nearest(bld, r, depth_vec, + bld->static_state->pot_height, + bld->static_state->wrap_r); + lp_build_name(z, "tex.z.wrapped"); + } + else if (bld->static_state->target == PIPE_TEXTURE_CUBE) { + z = r; + } + else { + z = NULL; + } + } + else { + y = z = NULL; + } + + /* + * Get texture colors. + */ + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x, y, z, + row_stride_vec, img_stride_vec, + data_ptr, colors_out); +} + + +/** + * Generate code to sample a mipmap level with linear filtering. + * If sampling a cube texture, r = cube face in [0,5]. + */ +static void +lp_build_sample_image_linear(struct lp_build_sample_context *bld, + LLVMValueRef width_vec, + LLVMValueRef height_vec, + LLVMValueRef depth_vec, + LLVMValueRef row_stride_vec, + LLVMValueRef img_stride_vec, + LLVMValueRef data_ptr, + LLVMValueRef s, + LLVMValueRef t, + LLVMValueRef r, + LLVMValueRef colors_out[4]) +{ + const int dims = texture_dims(bld->static_state->target); + LLVMValueRef x0, y0, z0, x1, y1, z1; + LLVMValueRef s_fpart, t_fpart, r_fpart; LLVMValueRef neighbors[2][2][4]; - unsigned chan; + int chan; - lp_build_sample_wrap_linear(bld, s, width, bld->static_state->pot_width, - bld->static_state->wrap_s, &x0, &x1, &s_fpart); - lp_build_sample_wrap_linear(bld, t, height, bld->static_state->pot_height, - bld->static_state->wrap_t, &y0, &y1, &t_fpart); + /* + * Compute integer texcoords. + */ + lp_build_sample_wrap_linear(bld, s, width_vec, + bld->static_state->pot_width, + bld->static_state->wrap_s, + &x0, &x1, &s_fpart); + lp_build_name(x0, "tex.x0.wrapped"); + lp_build_name(x1, "tex.x1.wrapped"); + + if (dims >= 2) { + lp_build_sample_wrap_linear(bld, t, height_vec, + bld->static_state->pot_height, + bld->static_state->wrap_t, + &y0, &y1, &t_fpart); + lp_build_name(y0, "tex.y0.wrapped"); + lp_build_name(y1, "tex.y1.wrapped"); + + if (dims == 3) { + lp_build_sample_wrap_linear(bld, r, depth_vec, + bld->static_state->pot_depth, + bld->static_state->wrap_r, + &z0, &z1, &r_fpart); + lp_build_name(z0, "tex.z0.wrapped"); + lp_build_name(z1, "tex.z1.wrapped"); + } + else if (bld->static_state->target == PIPE_TEXTURE_CUBE) { + z0 = z1 = r; /* cube face */ + r_fpart = NULL; + } + else { + z0 = z1 = NULL; + r_fpart = NULL; + } + } + else { + y0 = y1 = t_fpart = NULL; + z0 = z1 = r_fpart = NULL; + } - lp_build_sample_texel_soa(bld, width, height, x0, y0, stride, data_ptr, neighbors[0][0]); - lp_build_sample_texel_soa(bld, width, height, x1, y0, stride, data_ptr, neighbors[0][1]); - lp_build_sample_texel_soa(bld, width, height, x0, y1, stride, data_ptr, neighbors[1][0]); - lp_build_sample_texel_soa(bld, width, height, x1, y1, stride, data_ptr, neighbors[1][1]); + /* + * Get texture colors. + */ + /* get x0/x1 texels */ + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x0, y0, z0, + row_stride_vec, img_stride_vec, + data_ptr, neighbors[0][0]); + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x1, y0, z0, + row_stride_vec, img_stride_vec, + data_ptr, neighbors[0][1]); + + if (dims == 1) { + /* Interpolate two samples from 1D image to produce one color */ + for (chan = 0; chan < 4; chan++) { + colors_out[chan] = lp_build_lerp(&bld->texel_bld, s_fpart, + neighbors[0][0][chan], + neighbors[0][1][chan]); + } + } + else { + /* 2D/3D texture */ + LLVMValueRef colors0[4]; + + /* get x0/x1 texels at y1 */ + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x0, y1, z0, + row_stride_vec, img_stride_vec, + data_ptr, neighbors[1][0]); + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x1, y1, z0, + row_stride_vec, img_stride_vec, + data_ptr, neighbors[1][1]); + + /* Bilinear interpolate the four samples from the 2D image / 3D slice */ + for (chan = 0; chan < 4; chan++) { + colors0[chan] = lp_build_lerp_2d(&bld->texel_bld, + s_fpart, t_fpart, + neighbors[0][0][chan], + neighbors[0][1][chan], + neighbors[1][0][chan], + neighbors[1][1][chan]); + } - /* TODO: Don't interpolate missing channels */ - for(chan = 0; chan < 4; ++chan) { - texel[chan] = lp_build_lerp_2d(&bld->texel_bld, - s_fpart, t_fpart, - neighbors[0][0][chan], - neighbors[0][1][chan], - neighbors[1][0][chan], - neighbors[1][1][chan]); + if (dims == 3) { + LLVMValueRef neighbors1[2][2][4]; + LLVMValueRef colors1[4]; + + /* get x0/x1/y0/y1 texels at z1 */ + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x0, y0, z1, + row_stride_vec, img_stride_vec, + data_ptr, neighbors1[0][0]); + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x1, y0, z1, + row_stride_vec, img_stride_vec, + data_ptr, neighbors1[0][1]); + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x0, y1, z1, + row_stride_vec, img_stride_vec, + data_ptr, neighbors1[1][0]); + lp_build_sample_texel_soa(bld, width_vec, height_vec, depth_vec, + x1, y1, z1, + row_stride_vec, img_stride_vec, + data_ptr, neighbors1[1][1]); + + /* Bilinear interpolate the four samples from the second Z slice */ + for (chan = 0; chan < 4; chan++) { + colors1[chan] = lp_build_lerp_2d(&bld->texel_bld, + s_fpart, t_fpart, + neighbors1[0][0][chan], + neighbors1[0][1][chan], + neighbors1[1][0][chan], + neighbors1[1][1][chan]); + } + + /* Linearly interpolate the two samples from the two 3D slices */ + for (chan = 0; chan < 4; chan++) { + colors_out[chan] = lp_build_lerp(&bld->texel_bld, + r_fpart, + colors0[chan], colors1[chan]); + } + } + else { + /* 2D tex */ + for (chan = 0; chan < 4; chan++) { + colors_out[chan] = colors0[chan]; + } + } + } +} + + +/** Helper used by lp_build_cube_lookup() */ +static LLVMValueRef +lp_build_cube_ima(struct lp_build_context *coord_bld, LLVMValueRef coord) +{ + /* ima = -0.5 / abs(coord); */ + LLVMValueRef negHalf = lp_build_const_vec(coord_bld->type, -0.5); + LLVMValueRef absCoord = lp_build_abs(coord_bld, coord); + LLVMValueRef ima = lp_build_mul(coord_bld, negHalf, + lp_build_rcp(coord_bld, absCoord)); + return ima; +} + + +/** + * Helper used by lp_build_cube_lookup() + * \param sign scalar +1 or -1 + * \param coord float vector + * \param ima float vector + */ +static LLVMValueRef +lp_build_cube_coord(struct lp_build_context *coord_bld, + LLVMValueRef sign, int negate_coord, + LLVMValueRef coord, LLVMValueRef ima) +{ + /* return negate(coord) * ima * sign + 0.5; */ + LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5); + LLVMValueRef res; + + assert(negate_coord == +1 || negate_coord == -1); + + if (negate_coord == -1) { + coord = lp_build_negate(coord_bld, coord); + } + + res = lp_build_mul(coord_bld, coord, ima); + if (sign) { + sign = lp_build_broadcast_scalar(coord_bld, sign); + res = lp_build_mul(coord_bld, res, sign); + } + res = lp_build_add(coord_bld, res, half); + + return res; +} + + +/** Helper used by lp_build_cube_lookup() + * Return (major_coord >= 0) ? pos_face : neg_face; + */ +static LLVMValueRef +lp_build_cube_face(struct lp_build_sample_context *bld, + LLVMValueRef major_coord, + unsigned pos_face, unsigned neg_face) +{ + LLVMValueRef cmp = LLVMBuildFCmp(bld->builder, LLVMRealUGE, + major_coord, + bld->float_bld.zero, ""); + LLVMValueRef pos = LLVMConstInt(LLVMInt32Type(), pos_face, 0); + LLVMValueRef neg = LLVMConstInt(LLVMInt32Type(), neg_face, 0); + LLVMValueRef res = LLVMBuildSelect(bld->builder, cmp, pos, neg, ""); + return res; +} + + + +/** + * Generate code to do cube face selection and per-face texcoords. + */ +static void +lp_build_cube_lookup(struct lp_build_sample_context *bld, + LLVMValueRef s, + LLVMValueRef t, + LLVMValueRef r, + LLVMValueRef *face, + LLVMValueRef *face_s, + LLVMValueRef *face_t) +{ + struct lp_build_context *float_bld = &bld->float_bld; + struct lp_build_context *coord_bld = &bld->coord_bld; + LLVMValueRef rx, ry, rz; + LLVMValueRef arx, ary, arz; + LLVMValueRef c25 = LLVMConstReal(LLVMFloatType(), 0.25); + LLVMValueRef arx_ge_ary, arx_ge_arz; + LLVMValueRef ary_ge_arx, ary_ge_arz; + LLVMValueRef arx_ge_ary_arz, ary_ge_arx_arz; + LLVMValueRef rx_pos, ry_pos, rz_pos; + + assert(bld->coord_bld.type.length == 4); + + /* + * Use the average of the four pixel's texcoords to choose the face. + */ + rx = lp_build_mul(float_bld, c25, + lp_build_sum_vector(&bld->coord_bld, s)); + ry = lp_build_mul(float_bld, c25, + lp_build_sum_vector(&bld->coord_bld, t)); + rz = lp_build_mul(float_bld, c25, + lp_build_sum_vector(&bld->coord_bld, r)); + + arx = lp_build_abs(float_bld, rx); + ary = lp_build_abs(float_bld, ry); + arz = lp_build_abs(float_bld, rz); + + /* + * Compare sign/magnitude of rx,ry,rz to determine face + */ + arx_ge_ary = LLVMBuildFCmp(bld->builder, LLVMRealUGE, arx, ary, ""); + arx_ge_arz = LLVMBuildFCmp(bld->builder, LLVMRealUGE, arx, arz, ""); + ary_ge_arx = LLVMBuildFCmp(bld->builder, LLVMRealUGE, ary, arx, ""); + ary_ge_arz = LLVMBuildFCmp(bld->builder, LLVMRealUGE, ary, arz, ""); + + arx_ge_ary_arz = LLVMBuildAnd(bld->builder, arx_ge_ary, arx_ge_arz, ""); + ary_ge_arx_arz = LLVMBuildAnd(bld->builder, ary_ge_arx, ary_ge_arz, ""); + + rx_pos = LLVMBuildFCmp(bld->builder, LLVMRealUGE, rx, float_bld->zero, ""); + ry_pos = LLVMBuildFCmp(bld->builder, LLVMRealUGE, ry, float_bld->zero, ""); + rz_pos = LLVMBuildFCmp(bld->builder, LLVMRealUGE, rz, float_bld->zero, ""); + + { + struct lp_build_flow_context *flow_ctx; + struct lp_build_if_state if_ctx; + + flow_ctx = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx); + + *face_s = bld->coord_bld.undef; + *face_t = bld->coord_bld.undef; + *face = bld->int_bld.undef; + + lp_build_name(*face_s, "face_s"); + lp_build_name(*face_t, "face_t"); + lp_build_name(*face, "face"); + + lp_build_flow_scope_declare(flow_ctx, face_s); + lp_build_flow_scope_declare(flow_ctx, face_t); + lp_build_flow_scope_declare(flow_ctx, face); + + lp_build_if(&if_ctx, flow_ctx, bld->builder, arx_ge_ary_arz); + { + /* +/- X face */ + LLVMValueRef sign = lp_build_sgn(float_bld, rx); + LLVMValueRef ima = lp_build_cube_ima(coord_bld, s); + *face_s = lp_build_cube_coord(coord_bld, sign, +1, r, ima); + *face_t = lp_build_cube_coord(coord_bld, NULL, +1, t, ima); + *face = lp_build_cube_face(bld, rx, + PIPE_TEX_FACE_POS_X, + PIPE_TEX_FACE_NEG_X); + } + lp_build_else(&if_ctx); + { + struct lp_build_flow_context *flow_ctx2; + struct lp_build_if_state if_ctx2; + + LLVMValueRef face_s2 = bld->coord_bld.undef; + LLVMValueRef face_t2 = bld->coord_bld.undef; + LLVMValueRef face2 = bld->int_bld.undef; + + flow_ctx2 = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx2); + lp_build_flow_scope_declare(flow_ctx2, &face_s2); + lp_build_flow_scope_declare(flow_ctx2, &face_t2); + lp_build_flow_scope_declare(flow_ctx2, &face2); + + ary_ge_arx_arz = LLVMBuildAnd(bld->builder, ary_ge_arx, ary_ge_arz, ""); + + lp_build_if(&if_ctx2, flow_ctx2, bld->builder, ary_ge_arx_arz); + { + /* +/- Y face */ + LLVMValueRef sign = lp_build_sgn(float_bld, ry); + LLVMValueRef ima = lp_build_cube_ima(coord_bld, t); + face_s2 = lp_build_cube_coord(coord_bld, NULL, -1, s, ima); + face_t2 = lp_build_cube_coord(coord_bld, sign, -1, r, ima); + face2 = lp_build_cube_face(bld, ry, + PIPE_TEX_FACE_POS_Y, + PIPE_TEX_FACE_NEG_Y); + } + lp_build_else(&if_ctx2); + { + /* +/- Z face */ + LLVMValueRef sign = lp_build_sgn(float_bld, rz); + LLVMValueRef ima = lp_build_cube_ima(coord_bld, r); + face_s2 = lp_build_cube_coord(coord_bld, sign, -1, s, ima); + face_t2 = lp_build_cube_coord(coord_bld, NULL, +1, t, ima); + face2 = lp_build_cube_face(bld, rz, + PIPE_TEX_FACE_POS_Z, + PIPE_TEX_FACE_NEG_Z); + } + lp_build_endif(&if_ctx2); + lp_build_flow_scope_end(flow_ctx2); + lp_build_flow_destroy(flow_ctx2); + + *face_s = face_s2; + *face_t = face_t2; + *face = face2; + } + + lp_build_endif(&if_ctx); + lp_build_flow_scope_end(flow_ctx); + lp_build_flow_destroy(flow_ctx); + } +} + + + +/** + * Sample the texture/mipmap using given image filter and mip filter. + * data0_ptr and data1_ptr point to the two mipmap levels to sample + * from. width0/1_vec, height0/1_vec, depth0/1_vec indicate their sizes. + * If we're using nearest miplevel sampling the '1' values will be null/unused. + */ +static void +lp_build_sample_mipmap(struct lp_build_sample_context *bld, + unsigned img_filter, + unsigned mip_filter, + LLVMValueRef s, + LLVMValueRef t, + LLVMValueRef r, + LLVMValueRef lod_fpart, + LLVMValueRef width0_vec, + LLVMValueRef width1_vec, + LLVMValueRef height0_vec, + LLVMValueRef height1_vec, + LLVMValueRef depth0_vec, + LLVMValueRef depth1_vec, + LLVMValueRef row_stride0_vec, + LLVMValueRef row_stride1_vec, + LLVMValueRef img_stride0_vec, + LLVMValueRef img_stride1_vec, + LLVMValueRef data_ptr0, + LLVMValueRef data_ptr1, + LLVMValueRef *colors_out) +{ + LLVMValueRef colors0[4], colors1[4]; + int chan; + + if (img_filter == PIPE_TEX_FILTER_NEAREST) { + lp_build_sample_image_nearest(bld, + width0_vec, height0_vec, depth0_vec, + row_stride0_vec, img_stride0_vec, + data_ptr0, s, t, r, colors0); + + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + /* sample the second mipmap level, and interp */ + lp_build_sample_image_nearest(bld, + width1_vec, height1_vec, depth1_vec, + row_stride1_vec, img_stride1_vec, + data_ptr1, s, t, r, colors1); + } + } + else { + assert(img_filter == PIPE_TEX_FILTER_LINEAR); + + lp_build_sample_image_linear(bld, + width0_vec, height0_vec, depth0_vec, + row_stride0_vec, img_stride0_vec, + data_ptr0, s, t, r, colors0); + + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + /* sample the second mipmap level, and interp */ + lp_build_sample_image_linear(bld, + width1_vec, height1_vec, depth1_vec, + row_stride1_vec, img_stride1_vec, + data_ptr1, s, t, r, colors1); + } + } + + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + /* interpolate samples from the two mipmap levels */ + for (chan = 0; chan < 4; chan++) { + colors_out[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart, + colors0[chan], colors1[chan]); + } + } + else { + /* use first/only level's colors */ + for (chan = 0; chan < 4; chan++) { + colors_out[chan] = colors0[chan]; + } } } + +/** + * General texture sampling codegen. + * This function handles texture sampling for all texture targets (1D, + * 2D, 3D, cube) and all filtering modes. + */ +static void +lp_build_sample_general(struct lp_build_sample_context *bld, + unsigned unit, + LLVMValueRef s, + LLVMValueRef t, + LLVMValueRef r, + LLVMValueRef width, + LLVMValueRef height, + LLVMValueRef depth, + LLVMValueRef width_vec, + LLVMValueRef height_vec, + LLVMValueRef depth_vec, + LLVMValueRef row_stride_array, + LLVMValueRef img_stride_vec, + LLVMValueRef data_array, + LLVMValueRef *colors_out) +{ + struct lp_build_context *float_bld = &bld->float_bld; + const unsigned mip_filter = bld->static_state->min_mip_filter; + const unsigned min_filter = bld->static_state->min_img_filter; + const unsigned mag_filter = bld->static_state->mag_img_filter; + const int dims = texture_dims(bld->static_state->target); + LLVMValueRef lod, lod_fpart; + LLVMValueRef ilevel0, ilevel1, ilevel0_vec, ilevel1_vec; + LLVMValueRef width0_vec = NULL, height0_vec = NULL, depth0_vec = NULL; + LLVMValueRef width1_vec = NULL, height1_vec = NULL, depth1_vec = NULL; + LLVMValueRef row_stride0_vec = NULL, row_stride1_vec = NULL; + LLVMValueRef img_stride0_vec = NULL, img_stride1_vec = NULL; + LLVMValueRef data_ptr0, data_ptr1; + + /* + printf("%s mip %d min %d mag %d\n", __FUNCTION__, + mip_filter, min_filter, mag_filter); + */ + + /* + * Compute the level of detail (float). + */ + if (min_filter != mag_filter || + mip_filter != PIPE_TEX_MIPFILTER_NONE) { + /* Need to compute lod either to choose mipmap levels or to + * distinguish between minification/magnification with one mipmap level. + */ + lod = lp_build_lod_selector(bld, s, t, r, width, height, depth); + } + + /* + * Compute integer mipmap level(s) to fetch texels from. + */ + if (mip_filter == PIPE_TEX_MIPFILTER_NONE) { + /* always use mip level 0 */ + ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0); + } + else { + if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { + lp_build_nearest_mip_level(bld, unit, lod, &ilevel0); + } + else { + assert(mip_filter == PIPE_TEX_MIPFILTER_LINEAR); + lp_build_linear_mip_levels(bld, unit, lod, &ilevel0, &ilevel1, + &lod_fpart); + lod_fpart = lp_build_broadcast_scalar(&bld->coord_bld, lod_fpart); + } + } + + /* + * Convert scalar integer mipmap levels into vectors. + */ + ilevel0_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, ilevel0); + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) + ilevel1_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, ilevel1); + + /* + * Compute width, height at mipmap level 'ilevel0' + */ + width0_vec = lp_build_minify(bld, width_vec, ilevel0_vec); + if (dims >= 2) { + height0_vec = lp_build_minify(bld, height_vec, ilevel0_vec); + row_stride0_vec = lp_build_get_level_stride_vec(bld, row_stride_array, + ilevel0); + if (dims == 3 || bld->static_state->target == PIPE_TEXTURE_CUBE) { + img_stride0_vec = lp_build_mul(&bld->int_coord_bld, + row_stride0_vec, height0_vec); + if (dims == 3) { + depth0_vec = lp_build_minify(bld, depth_vec, ilevel0_vec); + } + } + } + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + /* compute width, height, depth for second mipmap level at 'ilevel1' */ + width1_vec = lp_build_minify(bld, width_vec, ilevel1_vec); + if (dims >= 2) { + height1_vec = lp_build_minify(bld, height_vec, ilevel1_vec); + row_stride1_vec = lp_build_get_level_stride_vec(bld, row_stride_array, + ilevel1); + if (dims == 3 || bld->static_state->target == PIPE_TEXTURE_CUBE) { + img_stride1_vec = lp_build_mul(&bld->int_coord_bld, + row_stride1_vec, height1_vec); + if (dims ==3) { + depth1_vec = lp_build_minify(bld, depth_vec, ilevel1_vec); + } + } + } + } + + /* + * Choose cube face, recompute per-face texcoords. + */ + if (bld->static_state->target == PIPE_TEXTURE_CUBE) { + LLVMValueRef face, face_s, face_t; + lp_build_cube_lookup(bld, s, t, r, &face, &face_s, &face_t); + s = face_s; /* vec */ + t = face_t; /* vec */ + /* use 'r' to indicate cube face */ + r = lp_build_broadcast_scalar(&bld->int_coord_bld, face); /* vec */ + } + + /* + * Get pointer(s) to image data for mipmap level(s). + */ + data_ptr0 = lp_build_get_mipmap_level(bld, data_array, ilevel0); + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + data_ptr1 = lp_build_get_mipmap_level(bld, data_array, ilevel1); + } + + /* + * Get/interpolate texture colors. + */ + if (min_filter == mag_filter) { + /* no need to distinquish between minification and magnification */ + lp_build_sample_mipmap(bld, min_filter, mip_filter, s, t, r, lod_fpart, + width0_vec, width1_vec, + height0_vec, height1_vec, + depth0_vec, depth1_vec, + row_stride0_vec, row_stride1_vec, + img_stride0_vec, img_stride1_vec, + data_ptr0, data_ptr1, + colors_out); + } + else { + /* Emit conditional to choose min image filter or mag image filter + * depending on the lod being >0 or <= 0, respectively. + */ + struct lp_build_flow_context *flow_ctx; + struct lp_build_if_state if_ctx; + LLVMValueRef minify; + + flow_ctx = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx); + + lp_build_flow_scope_declare(flow_ctx, &colors_out[0]); + lp_build_flow_scope_declare(flow_ctx, &colors_out[1]); + lp_build_flow_scope_declare(flow_ctx, &colors_out[2]); + lp_build_flow_scope_declare(flow_ctx, &colors_out[3]); + + /* minify = lod > 0.0 */ + minify = LLVMBuildFCmp(bld->builder, LLVMRealUGE, + lod, float_bld->zero, ""); + + lp_build_if(&if_ctx, flow_ctx, bld->builder, minify); + { + /* Use the minification filter */ + lp_build_sample_mipmap(bld, min_filter, mip_filter, + s, t, r, lod_fpart, + width0_vec, width1_vec, + height0_vec, height1_vec, + depth0_vec, depth1_vec, + row_stride0_vec, row_stride1_vec, + img_stride0_vec, img_stride1_vec, + data_ptr0, data_ptr1, + colors_out); + } + lp_build_else(&if_ctx); + { + /* Use the magnification filter */ + lp_build_sample_mipmap(bld, mag_filter, mip_filter, + s, t, r, lod_fpart, + width0_vec, width1_vec, + height0_vec, height1_vec, + depth0_vec, depth1_vec, + row_stride0_vec, row_stride1_vec, + img_stride0_vec, img_stride1_vec, + data_ptr0, data_ptr1, + colors_out); + } + lp_build_endif(&if_ctx); + + lp_build_flow_scope_end(flow_ctx); + lp_build_flow_destroy(flow_ctx); + } +} + + + static void lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder, struct lp_type dst_type, LLVMValueRef packed, LLVMValueRef *rgba) { - LLVMValueRef mask = lp_build_int_const_scalar(dst_type, 0xff); + LLVMValueRef mask = lp_build_const_int_vec(dst_type, 0xff); unsigned chan; /* Decode the input vector components */ @@ -799,7 +1720,7 @@ lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder, input = packed; if(start) - input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(dst_type, start), ""); + input = LLVMBuildLShr(builder, input, lp_build_const_int_vec(dst_type, start), ""); if(stop < 32) input = LLVMBuildAnd(builder, input, mask, ""); @@ -817,8 +1738,8 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld, LLVMValueRef t, LLVMValueRef width, LLVMValueRef height, - LLVMValueRef stride, - LLVMValueRef data_ptr, + LLVMValueRef stride_array, + LLVMValueRef data_array, LLVMValueRef *texel) { LLVMBuilderRef builder = bld->builder; @@ -834,8 +1755,9 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld, LLVMValueRef neighbors_hi[2][2]; LLVMValueRef packed, packed_lo, packed_hi; LLVMValueRef unswizzled[4]; + LLVMValueRef stride; - lp_build_context_init(&i32, builder, lp_type_int(32)); + lp_build_context_init(&i32, builder, lp_type_int_vec(32)); lp_build_context_init(&h16, builder, lp_type_ufixed(16)); lp_build_context_init(&u8n, builder, lp_type_unorm(8)); @@ -860,17 +1782,17 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld, t = LLVMBuildFPToSI(builder, t, i32_vec_type, ""); /* subtract 0.5 (add -128) */ - i32_c128 = lp_build_int_const_scalar(i32.type, -128); + i32_c128 = lp_build_const_int_vec(i32.type, -128); s = LLVMBuildAdd(builder, s, i32_c128, ""); t = LLVMBuildAdd(builder, t, i32_c128, ""); /* compute floor (shift right 8) */ - i32_c8 = lp_build_int_const_scalar(i32.type, 8); + i32_c8 = lp_build_const_int_vec(i32.type, 8); s_ipart = LLVMBuildAShr(builder, s, i32_c8, ""); t_ipart = LLVMBuildAShr(builder, t, i32_c8, ""); /* compute fractional part (AND with 0xff) */ - i32_c255 = lp_build_int_const_scalar(i32.type, 255); + i32_c255 = lp_build_const_int_vec(i32.type, 255); s_fpart = LLVMBuildAnd(builder, s, i32_c255, ""); t_fpart = LLVMBuildAnd(builder, t, i32_c255, ""); @@ -941,6 +1863,8 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld, t_fpart_hi = LLVMBuildShuffleVector(builder, t_fpart, h16.undef, shuffle_hi, ""); } + stride = lp_build_get_const_level_stride_vec(bld, stride_array, 0); + /* * Fetch the pixels as 4 x 32bit (rgba order might differ): * @@ -958,10 +1882,10 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld, * The higher 8 bits of the resulting elements will be zero. */ - neighbors[0][0] = lp_build_sample_packed(bld, x0, y0, stride, data_ptr); - neighbors[0][1] = lp_build_sample_packed(bld, x1, y0, stride, data_ptr); - neighbors[1][0] = lp_build_sample_packed(bld, x0, y1, stride, data_ptr); - neighbors[1][1] = lp_build_sample_packed(bld, x1, y1, stride, data_ptr); + neighbors[0][0] = lp_build_sample_packed(bld, x0, y0, stride, data_array); + neighbors[0][1] = lp_build_sample_packed(bld, x1, y0, stride, data_array); + neighbors[1][0] = lp_build_sample_packed(bld, x0, y1, stride, data_array); + neighbors[1][1] = lp_build_sample_packed(bld, x1, y1, stride, data_array); neighbors[0][0] = LLVMBuildBitCast(builder, neighbors[0][0], u8n_vec_type, ""); neighbors[0][1] = LLVMBuildBitCast(builder, neighbors[0][1], u8n_vec_type, ""); @@ -1035,7 +1959,7 @@ lp_build_sample_compare(struct lp_build_sample_context *bld, } assert(res); - res = lp_build_mul(texel_bld, res, lp_build_const_scalar(texel_bld->type, 0.25)); + res = lp_build_mul(texel_bld, res, lp_build_const_vec(texel_bld->type, 0.25)); /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ for(chan = 0; chan < 3; ++chan) @@ -1044,194 +1968,11 @@ lp_build_sample_compare(struct lp_build_sample_context *bld, } -static int -texture_dims(enum pipe_texture_target tex) -{ - switch (tex) { - case PIPE_TEXTURE_1D: - return 1; - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_CUBE: - return 2; - case PIPE_TEXTURE_3D: - return 3; - default: - assert(0 && "bad texture target in texture_dims()"); - return 2; - } -} - - -/** - * Generate code to compute texture level of detail (lambda). - * \param s vector of texcoord s values - * \param t vector of texcoord t values - * \param r vector of texcoord r values - * \param width scalar int texture width - * \param height scalar int texture height - * \param depth scalar int texture depth - */ -static LLVMValueRef -lp_build_lod_selector(struct lp_build_sample_context *bld, - LLVMValueRef s, - LLVMValueRef t, - LLVMValueRef r, - LLVMValueRef width, - LLVMValueRef height, - LLVMValueRef depth) - -{ - const int dims = texture_dims(bld->static_state->target); - struct lp_build_context *coord_bld = &bld->coord_bld; - - LLVMValueRef lod_bias = lp_build_const_scalar(bld->coord_bld.type, - bld->static_state->lod_bias); - LLVMValueRef min_lod = lp_build_const_scalar(bld->coord_bld.type, - bld->static_state->min_lod); - LLVMValueRef max_lod = lp_build_const_scalar(bld->coord_bld.type, - bld->static_state->max_lod); - - LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0); - LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0); - LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0); - - LLVMValueRef s0, s1, s2; - LLVMValueRef t0, t1, t2; - LLVMValueRef r0, r1, r2; - LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy; - LLVMValueRef rho, lod; - - /* - * dsdx = abs(s[1] - s[0]); - * dsdy = abs(s[2] - s[0]); - * dtdx = abs(t[1] - t[0]); - * dtdy = abs(t[2] - t[0]); - * drdx = abs(r[1] - r[0]); - * drdy = abs(r[2] - r[0]); - * XXX we're assuming a four-element quad in 2x2 layout here. - */ - s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0"); - s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1"); - s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2"); - dsdx = lp_build_abs(coord_bld, lp_build_sub(coord_bld, s1, s0)); - dsdy = lp_build_abs(coord_bld, lp_build_sub(coord_bld, s2, s0)); - if (dims > 1) { - t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0"); - t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1"); - t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2"); - dtdx = lp_build_abs(coord_bld, lp_build_sub(coord_bld, t1, t0)); - dtdy = lp_build_abs(coord_bld, lp_build_sub(coord_bld, t2, t0)); - if (dims > 2) { - r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0"); - r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1"); - r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2"); - drdx = lp_build_abs(coord_bld, lp_build_sub(coord_bld, r1, r0)); - drdy = lp_build_abs(coord_bld, lp_build_sub(coord_bld, r2, r0)); - } - } - - /* Compute rho = max of all partial derivatives scaled by texture size. - * XXX this can be vectorized somewhat - */ - rho = lp_build_mul(coord_bld, - lp_build_max(coord_bld, dsdx, dsdy), - lp_build_int_to_float(coord_bld, width)); - if (dims > 1) { - LLVMValueRef max; - max = lp_build_mul(coord_bld, - lp_build_max(coord_bld, dtdx, dtdy), - lp_build_int_to_float(coord_bld, height)); - rho = lp_build_max(coord_bld, rho, max); - if (dims > 2) { - max = lp_build_mul(coord_bld, - lp_build_max(coord_bld, drdx, drdy), - lp_build_int_to_float(coord_bld, depth)); - rho = lp_build_max(coord_bld, rho, max); - } - } - - /* compute lod = log2(rho) */ - lod = lp_build_log2(coord_bld, rho); - - /* add lod bias */ - lod = lp_build_add(coord_bld, lod, lod_bias); - - /* clamp lod */ - lod = lp_build_clamp(coord_bld, lod, min_lod, max_lod); - - return lod; -} - - -/** - * For PIPE_TEX_MIPFILTER_NEAREST, convert float LOD to integer - * mipmap level index. - * \param lod scalar float texture level of detail - * \param level_out returns integer - */ -static void -lp_build_nearest_mip_level(struct lp_build_sample_context *bld, - unsigned unit, - LLVMValueRef lod, - LLVMValueRef *level_out) -{ - struct lp_build_context *coord_bld = &bld->coord_bld; - struct lp_build_context *int_coord_bld = &bld->int_coord_bld; - LLVMValueRef last_level, level; - - last_level = bld->dynamic_state->last_level(bld->dynamic_state, - bld->builder, unit); - - /* convert float lod to integer */ - level = lp_build_iround(coord_bld, lod); - - /* clamp level to legal range of levels */ - *level_out = lp_build_clamp(int_coord_bld, level, - int_coord_bld->zero, - last_level); -} - - -/** - * For PIPE_TEX_MIPFILTER_LINEAR, convert float LOD to integer to - * two (adjacent) mipmap level indexes. Later, we'll sample from those - * two mipmap levels and interpolate between them. - */ -static void -lp_build_linear_mip_levels(struct lp_build_sample_context *bld, - unsigned unit, - LLVMValueRef lod, - LLVMValueRef *level0_out, - LLVMValueRef *level1_out, - LLVMValueRef *weight_out) -{ - struct lp_build_context *coord_bld = &bld->coord_bld; - struct lp_build_context *int_coord_bld = &bld->int_coord_bld; - LLVMValueRef last_level, level; - - last_level = bld->dynamic_state->last_level(bld->dynamic_state, - bld->builder, unit); - - /* convert float lod to integer */ - level = lp_build_ifloor(coord_bld, lod); - - /* compute level 0 and clamp to legal range of levels */ - *level0_out = lp_build_clamp(int_coord_bld, level, - int_coord_bld->zero, - last_level); - /* compute level 1 and clamp to legal range of levels */ - *level1_out = lp_build_add(int_coord_bld, *level0_out, int_coord_bld->one); - *level1_out = lp_build_min(int_coord_bld, *level1_out, int_coord_bld->zero); - - *weight_out = lp_build_fract(coord_bld, lod); -} - - - /** * Build texture sampling code. * 'texel' will return a vector of four LLVMValueRefs corresponding to * R, G, B, A. + * \param type vector float type to use for coords, etc. */ void lp_build_sample_soa(LLVMBuilderRef builder, @@ -1245,10 +1986,11 @@ lp_build_sample_soa(LLVMBuilderRef builder, LLVMValueRef *texel) { struct lp_build_sample_context bld; - LLVMValueRef width; - LLVMValueRef height; - LLVMValueRef stride; - LLVMValueRef data_ptr; + LLVMValueRef width, width_vec; + LLVMValueRef height, height_vec; + LLVMValueRef depth, depth_vec; + LLVMValueRef stride_array; + LLVMValueRef data_array; LLVMValueRef s; LLVMValueRef t; LLVMValueRef r; @@ -1256,6 +1998,7 @@ lp_build_sample_soa(LLVMBuilderRef builder, (void) lp_build_lod_selector; /* temporary to silence warning */ (void) lp_build_nearest_mip_level; (void) lp_build_linear_mip_levels; + (void) lp_build_minify; /* Setup our build context */ memset(&bld, 0, sizeof bld); @@ -1263,10 +2006,16 @@ lp_build_sample_soa(LLVMBuilderRef builder, bld.static_state = static_state; bld.dynamic_state = dynamic_state; bld.format_desc = util_format_description(static_state->format); + + bld.float_type = lp_type_float(32); + bld.int_type = lp_type_int(32); bld.coord_type = type; bld.uint_coord_type = lp_uint_type(type); bld.int_coord_type = lp_int_type(type); bld.texel_type = type; + + lp_build_context_init(&bld.float_bld, builder, bld.float_type); + lp_build_context_init(&bld.int_bld, builder, bld.int_type); lp_build_context_init(&bld.coord_bld, builder, bld.coord_type); lp_build_context_init(&bld.uint_coord_bld, builder, bld.uint_coord_type); lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type); @@ -1275,41 +2024,37 @@ lp_build_sample_soa(LLVMBuilderRef builder, /* Get the dynamic state */ width = dynamic_state->width(dynamic_state, builder, unit); height = dynamic_state->height(dynamic_state, builder, unit); - stride = dynamic_state->stride(dynamic_state, builder, unit); - data_ptr = dynamic_state->data_ptr(dynamic_state, builder, unit); + depth = dynamic_state->depth(dynamic_state, builder, unit); + stride_array = dynamic_state->row_stride(dynamic_state, builder, unit); + data_array = dynamic_state->data_ptr(dynamic_state, builder, unit); + /* Note that data_array is an array[level] of pointers to texture images */ s = coords[0]; t = coords[1]; r = coords[2]; - width = lp_build_broadcast_scalar(&bld.uint_coord_bld, width); - height = lp_build_broadcast_scalar(&bld.uint_coord_bld, height); - stride = lp_build_broadcast_scalar(&bld.uint_coord_bld, stride); - - if(static_state->target == PIPE_TEXTURE_1D) - t = bld.coord_bld.zero; - - switch (static_state->min_img_filter) { - case PIPE_TEX_FILTER_NEAREST: - lp_build_sample_2d_nearest_soa(&bld, s, t, width, height, - stride, data_ptr, texel); - break; - case PIPE_TEX_FILTER_LINEAR: - if(lp_format_is_rgba8(bld.format_desc) && - is_simple_wrap_mode(static_state->wrap_s) && - is_simple_wrap_mode(static_state->wrap_t)) - lp_build_sample_2d_linear_aos(&bld, s, t, width, height, - stride, data_ptr, texel); - else - lp_build_sample_2d_linear_soa(&bld, s, t, width, height, - stride, data_ptr, texel); - break; - default: - assert(0); + width_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, width); + height_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, height); + depth_vec = lp_build_broadcast_scalar(&bld.uint_coord_bld, depth); + + if (lp_format_is_rgba8(bld.format_desc) && + static_state->target == PIPE_TEXTURE_2D && + static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR && + static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR && + static_state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE && + is_simple_wrap_mode(static_state->wrap_s) && + is_simple_wrap_mode(static_state->wrap_t)) { + /* special case */ + lp_build_sample_2d_linear_aos(&bld, s, t, width_vec, height_vec, + stride_array, data_array, texel); + } + else { + lp_build_sample_general(&bld, unit, s, t, r, + width, height, depth, + width_vec, height_vec, depth_vec, + stride_array, NULL, data_array, + texel); } - - /* FIXME: respect static_state->min_mip_filter */; - /* FIXME: respect static_state->mag_img_filter */; lp_build_sample_compare(&bld, r, texel); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_struct.h b/src/gallium/auxiliary/gallivm/lp_bld_struct.h index 740392f5611..147336edb4b 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_struct.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_struct.h @@ -37,7 +37,7 @@ #define LP_BLD_STRUCT_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include <llvm-c/Target.h> #include "util/u_debug.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c index 64e81f7b1fe..278c838eaca 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c @@ -144,9 +144,9 @@ lp_build_broadcast_aos(struct lp_build_context *bld, #endif if(shift > 0) - tmp = LLVMBuildLShr(bld->builder, a, lp_build_int_const_scalar(type4, shift*type.width), ""); + tmp = LLVMBuildLShr(bld->builder, a, lp_build_const_int_vec(type4, shift*type.width), ""); if(shift < 0) - tmp = LLVMBuildShl(bld->builder, a, lp_build_int_const_scalar(type4, -shift*type.width), ""); + tmp = LLVMBuildShl(bld->builder, a, lp_build_const_int_vec(type4, -shift*type.width), ""); assert(tmp); if(tmp) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h index b9472127a63..138ca620e63 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h @@ -37,7 +37,7 @@ #define LP_BLD_SWIZZLE_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h index eddb7a83fa2..63b938bfa98 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h @@ -35,7 +35,7 @@ #ifndef LP_BLD_TGSI_H #define LP_BLD_TGSI_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct tgsi_token; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index 5f2c2a54ee9..f160be878f8 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -41,6 +41,7 @@ #include "util/u_debug.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_info.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" @@ -95,6 +96,19 @@ struct lp_exec_mask { int cond_stack_size; LLVMValueRef cond_mask; + LLVMValueRef break_stack[LP_TGSI_MAX_NESTING]; + int break_stack_size; + LLVMValueRef break_mask; + + LLVMValueRef cont_stack[LP_TGSI_MAX_NESTING]; + int cont_stack_size; + LLVMValueRef cont_mask; + + LLVMBasicBlockRef loop_stack[LP_TGSI_MAX_NESTING]; + int loop_stack_size; + LLVMBasicBlockRef loop_block; + + LLVMValueRef exec_mask; }; @@ -145,15 +159,33 @@ static void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context mask->bld = bld; mask->has_mask = FALSE; mask->cond_stack_size = 0; + mask->loop_stack_size = 0; + mask->break_stack_size = 0; + mask->cont_stack_size = 0; mask->int_vec_type = lp_build_int_vec_type(mask->bld->type); } static void lp_exec_mask_update(struct lp_exec_mask *mask) { - mask->exec_mask = mask->cond_mask; - if (mask->cond_stack_size > 0) - mask->has_mask = TRUE; + if (mask->loop_stack_size) { + /*for loops we need to update the entire mask at + * runtime */ + LLVMValueRef tmp; + tmp = LLVMBuildAnd(mask->bld->builder, + mask->cont_mask, + mask->break_mask, + "maskcb"); + mask->exec_mask = LLVMBuildAnd(mask->bld->builder, + mask->cond_mask, + tmp, + "maskfull"); + } else + mask->exec_mask = mask->cond_mask; + + + mask->has_mask = (mask->cond_stack_size > 0 || + mask->loop_stack_size > 0); } static void lp_exec_mask_cond_push(struct lp_exec_mask *mask, @@ -190,6 +222,89 @@ static void lp_exec_mask_cond_pop(struct lp_exec_mask *mask) lp_exec_mask_update(mask); } +static void lp_exec_bgnloop(struct lp_exec_mask *mask) +{ + + if (mask->cont_stack_size == 0) + mask->cont_mask = LLVMConstAllOnes(mask->int_vec_type); + if (mask->cont_stack_size == 0) + mask->break_mask = LLVMConstAllOnes(mask->int_vec_type); + if (mask->cond_stack_size == 0) + mask->cond_mask = LLVMConstAllOnes(mask->int_vec_type); + mask->loop_stack[mask->loop_stack_size++] = mask->loop_block; + mask->loop_block = lp_build_insert_new_block(mask->bld->builder, "bgnloop"); + LLVMBuildBr(mask->bld->builder, mask->loop_block); + LLVMPositionBuilderAtEnd(mask->bld->builder, mask->loop_block); + + lp_exec_mask_update(mask); +} + +static void lp_exec_break(struct lp_exec_mask *mask) +{ + LLVMValueRef exec_mask = LLVMBuildNot(mask->bld->builder, + mask->exec_mask, + "break"); + + mask->break_stack[mask->break_stack_size++] = mask->break_mask; + if (mask->break_stack_size > 1) { + mask->break_mask = LLVMBuildAnd(mask->bld->builder, + mask->break_mask, + exec_mask, "break_full"); + } else + mask->break_mask = exec_mask; + + lp_exec_mask_update(mask); +} + +static void lp_exec_continue(struct lp_exec_mask *mask) +{ + LLVMValueRef exec_mask = LLVMBuildNot(mask->bld->builder, + mask->exec_mask, + ""); + + mask->cont_stack[mask->cont_stack_size++] = mask->cont_mask; + if (mask->cont_stack_size > 1) { + mask->cont_mask = LLVMBuildAnd(mask->bld->builder, + mask->cont_mask, + exec_mask, ""); + } else + mask->cont_mask = exec_mask; + + lp_exec_mask_update(mask); +} + + +static void lp_exec_endloop(struct lp_exec_mask *mask) +{ + LLVMBasicBlockRef endloop; + LLVMTypeRef reg_type = LLVMIntType(mask->bld->type.width* + mask->bld->type.length); + /* i1cond = (mask == 0) */ + LLVMValueRef i1cond = LLVMBuildICmp( + mask->bld->builder, + LLVMIntNE, + LLVMBuildBitCast(mask->bld->builder, mask->break_mask, reg_type, ""), + LLVMConstNull(reg_type), ""); + + endloop = lp_build_insert_new_block(mask->bld->builder, "endloop"); + + LLVMBuildCondBr(mask->bld->builder, + i1cond, mask->loop_block, endloop); + + LLVMPositionBuilderAtEnd(mask->bld->builder, endloop); + + mask->loop_block = mask->loop_stack[--mask->loop_stack_size]; + /* pop the break mask */ + if (mask->cont_stack_size) { + mask->cont_mask = mask->cont_stack[--mask->cont_stack_size]; + } + if (mask->break_stack_size) { + mask->break_mask = mask->cont_stack[--mask->break_stack_size]; + } + + lp_exec_mask_update(mask); +} + static void lp_exec_mask_store(struct lp_exec_mask *mask, LLVMValueRef val, LLVMValueRef dst) @@ -360,7 +475,7 @@ emit_store( break; case TGSI_SAT_MINUS_PLUS_ONE: - value = lp_build_max(&bld->base, value, lp_build_const_scalar(bld->base.type, -1.0)); + value = lp_build_max(&bld->base, value, lp_build_const_vec(bld->base.type, -1.0)); value = lp_build_min(&bld->base, value, bld->base.one); break; @@ -384,6 +499,11 @@ emit_store( assert(0); break; + case TGSI_FILE_PREDICATE: + /* FIXME */ + assert(0); + break; + default: assert( 0 ); } @@ -581,6 +701,17 @@ emit_instruction( if (indirect_temp_reference(inst)) return FALSE; + /* + * Stores and write masks are handled in a general fashion after the long + * instruction opcode switch statement. + * + * Although not stricitly necessary, we avoid generating instructions for + * channels which won't be stored, in cases where's that easy. For some + * complex instructions, like texture sampling, it is more convenient to + * assume a full writemask and then let LLVM optimization passes eliminate + * redundant code. + */ + assert(info->num_dst <= 1); if(info->num_dst) { FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { @@ -865,7 +996,7 @@ emit_instruction( src0 = emit_fetch( bld, inst, 0, chan_index ); src1 = emit_fetch( bld, inst, 1, chan_index ); src2 = emit_fetch( bld, inst, 2, chan_index ); - tmp1 = lp_build_const_scalar(bld->base.type, 0.5); + tmp1 = lp_build_const_vec(bld->base.type, 0.5); tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src2, tmp1); dst0[chan_index] = lp_build_select( &bld->base, tmp0, src0, src1 ); } @@ -1126,7 +1257,6 @@ emit_instruction( break; case TGSI_OPCODE_TEX: - /* XXX what about dst0 writemask? */ emit_tex( bld, inst, FALSE, FALSE, dst0 ); break; @@ -1349,14 +1479,15 @@ emit_instruction( case TGSI_OPCODE_TXP: emit_tex( bld, inst, FALSE, TRUE, dst0 ); break; - + case TGSI_OPCODE_BRK: - /* FIXME */ - return 0; + lp_exec_break(&bld->exec_mask); break; case TGSI_OPCODE_IF: tmp0 = emit_fetch(bld, inst, 0, CHAN_X); + tmp0 = lp_build_cmp(&bld->base, PIPE_FUNC_NOTEQUAL, + tmp0, bld->base.zero); lp_exec_mask_cond_push(&bld->exec_mask, tmp0); break; @@ -1366,6 +1497,10 @@ emit_instruction( return 0; break; + case TGSI_OPCODE_BGNLOOP: + lp_exec_bgnloop(&bld->exec_mask); + break; + case TGSI_OPCODE_REP: /* deprecated */ assert(0); @@ -1386,6 +1521,10 @@ emit_instruction( return 0; break; + case TGSI_OPCODE_ENDLOOP: + lp_exec_endloop(&bld->exec_mask); + break; + case TGSI_OPCODE_ENDREP: /* deprecated */ assert(0); @@ -1485,8 +1624,7 @@ emit_instruction( break; case TGSI_OPCODE_CONT: - /* FIXME */ - return 0; + lp_exec_continue(&bld->exec_mask); break; case TGSI_OPCODE_EMIT: @@ -1575,7 +1713,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, assert(num_immediates < LP_MAX_IMMEDIATES); for( i = 0; i < size; ++i ) bld.immediates[num_immediates][i] = - lp_build_const_scalar(type, parse.FullToken.FullImmediate.u[i].Float); + lp_build_const_vec(type, parse.FullToken.FullImmediate.u[i].Float); for( i = size; i < 4; ++i ) bld.immediates[num_immediates][i] = bld.base.undef; num_immediates++; @@ -1589,7 +1727,14 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, assert( 0 ); } } - + if (0) { + LLVMBasicBlockRef block = LLVMGetInsertBlock(builder); + LLVMValueRef function = LLVMGetBasicBlockParent(block); + debug_printf("11111111111111111111111111111 \n"); + tgsi_dump(tokens, 0); + LLVMDumpValue(function); + debug_printf("2222222222222222222222222222 \n"); + } tgsi_parse_free( &parse ); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.c b/src/gallium/auxiliary/gallivm/lp_bld_type.c index c327ba045a6..796af88caad 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_type.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_type.c @@ -58,7 +58,10 @@ LLVMTypeRef lp_build_vec_type(struct lp_type type) { LLVMTypeRef elem_type = lp_build_elem_type(type); - return LLVMVectorType(elem_type, type.length); + if (type.length == 1) + return elem_type; + else + return LLVMVectorType(elem_type, type.length); } @@ -115,6 +118,9 @@ lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type) if(!vec_type) return FALSE; + if (type.length == 1) + return lp_check_elem_type(type, vec_type); + if(LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind) return FALSE; @@ -153,7 +159,10 @@ LLVMTypeRef lp_build_int_vec_type(struct lp_type type) { LLVMTypeRef elem_type = lp_build_int_elem_type(type); - return LLVMVectorType(elem_type, type.length); + if (type.length == 1) + return elem_type; + else + return LLVMVectorType(elem_type, type.length); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.h b/src/gallium/auxiliary/gallivm/lp_bld_type.h index 16946cc28a2..cd59d2faa66 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_type.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_type.h @@ -37,9 +37,9 @@ #define LP_BLD_TYPE_H -#include <llvm-c/Core.h> +#include "pipe/p_compiler.h" +#include "gallivm/lp_bld.h" -#include <pipe/p_compiler.h> /** @@ -103,7 +103,7 @@ struct lp_type { unsigned width:14; /** - * Vector length. + * Vector length. If length==1, this is a scalar (float/int) type. * * width*length should be a power of two greater or equal to eight. * @@ -139,6 +139,7 @@ struct lp_build_context }; +/** Create scalar float type */ static INLINE struct lp_type lp_type_float(unsigned width) { @@ -148,12 +149,29 @@ lp_type_float(unsigned width) res_type.floating = TRUE; res_type.sign = TRUE; res_type.width = width; + res_type.length = 1; + + return res_type; +} + + +/** Create vector of float type */ +static INLINE struct lp_type +lp_type_float_vec(unsigned width) +{ + struct lp_type res_type; + + memset(&res_type, 0, sizeof res_type); + res_type.floating = TRUE; + res_type.sign = TRUE; + res_type.width = width; res_type.length = LP_NATIVE_VECTOR_WIDTH / width; return res_type; } +/** Create scalar int type */ static INLINE struct lp_type lp_type_int(unsigned width) { @@ -162,12 +180,28 @@ lp_type_int(unsigned width) memset(&res_type, 0, sizeof res_type); res_type.sign = TRUE; res_type.width = width; + res_type.length = 1; + + return res_type; +} + + +/** Create vector int type */ +static INLINE struct lp_type +lp_type_int_vec(unsigned width) +{ + struct lp_type res_type; + + memset(&res_type, 0, sizeof res_type); + res_type.sign = TRUE; + res_type.width = width; res_type.length = LP_NATIVE_VECTOR_WIDTH / width; return res_type; } +/** Create scalar uint type */ static INLINE struct lp_type lp_type_uint(unsigned width) { @@ -175,6 +209,20 @@ lp_type_uint(unsigned width) memset(&res_type, 0, sizeof res_type); res_type.width = width; + res_type.length = 1; + + return res_type; +} + + +/** Create vector uint type */ +static INLINE struct lp_type +lp_type_uint_vec(unsigned width) +{ + struct lp_type res_type; + + memset(&res_type, 0, sizeof res_type); + res_type.width = width; res_type.length = LP_NATIVE_VECTOR_WIDTH / width; return res_type; diff --git a/src/gallium/auxiliary/target-helpers/wrap_screen.c b/src/gallium/auxiliary/target-helpers/wrap_screen.c new file mode 100644 index 00000000000..5fe30139386 --- /dev/null +++ b/src/gallium/auxiliary/target-helpers/wrap_screen.c @@ -0,0 +1,65 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/* + * Authors: + * Keith Whitwell + */ + +#include "target-helpers/wrap_screen.h" +#include "trace/tr_public.h" +#include "identity/id_public.h" +#include "util/u_debug.h" + + +/* Centralized code to inject common wrapping layers: + */ +struct pipe_screen * +gallium_wrap_screen( struct pipe_screen *screen ) +{ + /* Screen wrapping functions are required not to fail. If it is + * impossible to wrap a screen, the unwrapped screen should be + * returned instead. Any failure condition should be returned in + * an OUT argument. + * + * Otherwise it is really messy trying to clean up in this code. + */ + if (debug_get_bool_option("GALLIUM_WRAP", FALSE)) { + screen = identity_screen_create(screen); + } + + if (debug_get_bool_option("GALLIUM_TRACE", FALSE)) { + screen = trace_screen_create( screen ); + } + + return screen; +} + + + + diff --git a/src/gallium/auxiliary/target-helpers/wrap_screen.h b/src/gallium/auxiliary/target-helpers/wrap_screen.h new file mode 100644 index 00000000000..7e76beb7c5a --- /dev/null +++ b/src/gallium/auxiliary/target-helpers/wrap_screen.h @@ -0,0 +1,16 @@ +#ifndef WRAP_SCREEN_HELPER_H +#define WRAP_SCREEN_HELPER_H + +#include "pipe/p_compiler.h" + +struct pipe_screen; + +/* Centralized code to inject common wrapping layers. Other layers + * can be introduced by specific targets, but these are the generally + * helpful ones we probably want everywhere. + */ +struct pipe_screen * +gallium_wrap_screen( struct pipe_screen *screen ); + + +#endif diff --git a/src/gallium/auxiliary/translate/translate_generic.c b/src/gallium/auxiliary/translate/translate_generic.c index c9ec2b32bfe..c3ec9ae3f4b 100644 --- a/src/gallium/auxiliary/translate/translate_generic.c +++ b/src/gallium/auxiliary/translate/translate_generic.c @@ -393,10 +393,10 @@ static fetch_func get_fetch_func( enum pipe_format format ) return &fetch_R8G8B8A8_SSCALED; case PIPE_FORMAT_B8G8R8A8_UNORM: - return &fetch_A8R8G8B8_UNORM; + return &fetch_B8G8R8A8_UNORM; case PIPE_FORMAT_A8R8G8B8_UNORM: - return &fetch_B8G8R8A8_UNORM; + return &fetch_A8R8G8B8_UNORM; case PIPE_FORMAT_R32_FIXED: return &fetch_R32_FIXED; @@ -552,10 +552,10 @@ static emit_func get_emit_func( enum pipe_format format ) return &emit_R8G8B8A8_SSCALED; case PIPE_FORMAT_B8G8R8A8_UNORM: - return &emit_A8R8G8B8_UNORM; + return &emit_B8G8R8A8_UNORM; case PIPE_FORMAT_A8R8G8B8_UNORM: - return &emit_B8G8R8A8_UNORM; + return &emit_A8R8G8B8_UNORM; default: assert(0); diff --git a/src/gallium/auxiliary/translate/translate_sse.c b/src/gallium/auxiliary/translate/translate_sse.c index 03e093c11ea..c13e7427387 100644 --- a/src/gallium/auxiliary/translate/translate_sse.c +++ b/src/gallium/auxiliary/translate/translate_sse.c @@ -336,7 +336,7 @@ static boolean translate_attr( struct translate_sse *p, case PIPE_FORMAT_R32G32B32A32_FLOAT: emit_load_R32G32B32A32(p, dataXMM, srcECX); break; - case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_B8G8R8A8_UNORM: emit_load_R8G8B8A8_UNORM(p, dataXMM, srcECX); emit_swizzle(p, dataXMM, dataXMM, SHUF(Z,Y,X,W)); break; @@ -360,7 +360,7 @@ static boolean translate_attr( struct translate_sse *p, case PIPE_FORMAT_R32G32B32A32_FLOAT: emit_store_R32G32B32A32(p, dstEAX, dataXMM); break; - case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_B8G8R8A8_UNORM: emit_swizzle(p, dataXMM, dataXMM, SHUF(Z,Y,X,W)); emit_store_R8G8B8A8_UNORM(p, dstEAX, dataXMM); break; diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 0b263a9db5c..cd95f85b63b 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -45,6 +45,7 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "util/u_simple_shaders.h" #include "util/u_surface.h" #include "util/u_rect.h" @@ -63,6 +64,7 @@ struct blit_state struct pipe_sampler_state sampler; struct pipe_viewport_state viewport; struct pipe_clip_state clip; + struct pipe_vertex_element velem[2]; void *vs; void *fs[TGSI_WRITEMASK_XYZW + 1]; @@ -114,6 +116,15 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) ctx->sampler.mag_img_filter = 0; /* set later */ ctx->sampler.normalized_coords = 1; + /* vertex elements state */ + memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2); + for (i = 0; i < 2; i++) { + ctx->velem[i].src_offset = i * 4 * sizeof(float); + ctx->velem[i].instance_divisor = 0; + ctx->velem[i].vertex_buffer_index = 0; + ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + /* vertex shader - still required to provide the linkage between * fragment shader input semantics and vertex_element/buffers. */ @@ -270,6 +281,7 @@ regions_overlap(int srcX0, int srcY0, void util_blit_pixels_writemask(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -280,7 +292,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_texture *tex = NULL; + struct pipe_sampler_view *sampler_view = NULL; struct pipe_framebuffer_state fb; const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); @@ -335,6 +347,8 @@ util_blit_pixels_writemask(struct blit_state *ctx, src->texture->last_level != 0) { struct pipe_texture texTemp; + struct pipe_texture *tex; + struct pipe_sampler_view sv_templ; struct pipe_surface *texSurf; const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); @@ -366,6 +380,14 @@ util_blit_pixels_writemask(struct blit_state *ctx, if (!tex) return; + u_sampler_view_default_template(&sv_templ, tex, tex->format); + + sampler_view = ctx->pipe->create_sampler_view(ctx->pipe, tex, &sv_templ); + if (!sampler_view) { + pipe_texture_reference(&tex, NULL); + return; + } + texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); @@ -389,33 +411,38 @@ util_blit_pixels_writemask(struct blit_state *ctx, s1 = 1.0f; t0 = 0.0f; t1 = 1.0f; + + pipe_texture_reference(&tex, NULL); } else { - pipe_texture_reference(&tex, src->texture); - s0 = srcX0 / (float)tex->width0; - s1 = srcX1 / (float)tex->width0; - t0 = srcY0 / (float)tex->height0; - t1 = srcY1 / (float)tex->height0; + pipe_sampler_view_reference(&sampler_view, src_sampler_view); + s0 = srcX0 / (float)src->texture->width0; + s1 = srcX1 / (float)src->texture->width0; + t0 = srcY0 / (float)src->texture->height0; + t1 = srcY1 / (float)src->texture->height0; } + /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_clip(ctx->cso); + cso_save_vertex_elements(ctx->cso); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend); cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); + cso_set_vertex_elements(ctx->cso, 2, ctx->velem); /* sampler */ ctx->sampler.min_img_filter = filter; @@ -435,7 +462,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_set_viewport(ctx->cso, &ctx->viewport); /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &tex); + cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view); if (ctx->fs[writemask] == NULL) ctx->fs[writemask] = @@ -474,20 +501,22 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_viewport(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_clip(ctx->cso); + cso_restore_vertex_elements(ctx->cso); - pipe_texture_reference(&tex, NULL); + pipe_sampler_view_reference(&sampler_view, NULL); } void util_blit_pixels(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -495,7 +524,7 @@ util_blit_pixels(struct blit_state *ctx, int dstX1, int dstY1, float z, uint filter ) { - util_blit_pixels_writemask( ctx, src, + util_blit_pixels_writemask( ctx, src, src_sampler_view, srcX0, srcY0, srcX1, srcY1, dst, @@ -526,21 +555,23 @@ void util_blit_flush( struct blit_state *ctx ) */ void util_blit_pixels_tex(struct blit_state *ctx, - struct pipe_texture *tex, - int srcX0, int srcY0, - int srcX1, int srcY1, - struct pipe_surface *dst, - int dstX0, int dstY0, - int dstX1, int dstY1, - float z, uint filter) + struct pipe_sampler_view *src_sampler_view, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter) { struct pipe_framebuffer_state fb; float s0, t0, s1, t1; unsigned offset; + struct pipe_texture *tex = src_sampler_view->texture; assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); + assert(tex); assert(tex->width0 != 0); assert(tex->height0 != 0); @@ -559,17 +590,19 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_clip(ctx->cso); + cso_save_vertex_elements(ctx->cso); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend); cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); + cso_set_vertex_elements(ctx->cso, 2, ctx->velem); /* sampler */ ctx->sampler.min_img_filter = filter; @@ -589,7 +622,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_set_viewport(ctx->cso, &ctx->viewport); /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &tex); + cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view); /* shaders */ cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]); @@ -623,9 +656,10 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_clip(ctx->cso); + cso_restore_vertex_elements(ctx->cso); } diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h index a102021529e..1ebe65b4558 100644 --- a/src/gallium/auxiliary/util/u_blit.h +++ b/src/gallium/auxiliary/util/u_blit.h @@ -53,6 +53,7 @@ util_destroy_blit(struct blit_state *ctx); extern void util_blit_pixels(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -63,6 +64,7 @@ util_blit_pixels(struct blit_state *ctx, void util_blit_pixels_writemask(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -73,7 +75,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, extern void util_blit_pixels_tex(struct blit_state *ctx, - struct pipe_texture *tex, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 0ba09d33bfc..1692987e8e3 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -45,6 +45,7 @@ #include "util/u_draw_quad.h" #include "util/u_pack_color.h" #include "util/u_rect.h" +#include "util/u_sampler.h" #include "util/u_simple_shaders.h" #include "util/u_texture.h" @@ -88,12 +89,16 @@ struct blitter_context_priv void *dsa_write_depth_keep_stencil; void *dsa_keep_depth_stencil; + void *velem_state; + /* Sampler state for clamping to a miplevel. */ void *sampler_state[PIPE_MAX_TEXTURE_LEVELS]; /* Rasterizer state. */ void *rs_state; + struct pipe_sampler_view *sampler_view; + /* Viewport state. */ struct pipe_viewport_state viewport; @@ -104,10 +109,11 @@ struct blitter_context_priv struct blitter_context *util_blitter_create(struct pipe_context *pipe) { struct blitter_context_priv *ctx; - struct pipe_blend_state blend = { 0 }; - struct pipe_depth_stencil_alpha_state dsa = { { 0 } }; - struct pipe_rasterizer_state rs_state = { 0 }; + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_rasterizer_state rs_state; struct pipe_sampler_state *sampler_state; + struct pipe_vertex_element velem[2]; unsigned i; ctx = CALLOC_STRUCT(blitter_context_priv); @@ -122,17 +128,20 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->blitter.saved_rs_state = INVALID_PTR; ctx->blitter.saved_fs = INVALID_PTR; ctx->blitter.saved_vs = INVALID_PTR; + ctx->blitter.saved_velem_state = INVALID_PTR; ctx->blitter.saved_fb_state.nr_cbufs = ~0; - ctx->blitter.saved_num_textures = ~0; + ctx->blitter.saved_num_sampler_views = ~0; ctx->blitter.saved_num_sampler_states = ~0; /* blend state objects */ + memset(&blend, 0, sizeof(blend)); ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); blend.rt[0].colormask = PIPE_MASK_RGBA; ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); /* depth stencil alpha state objects */ + memset(&dsa, 0, sizeof(dsa)); ctx->dsa_keep_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &dsa); @@ -170,6 +179,16 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) rs_state.flatshade = 1; ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); + /* vertex elements state */ + memset(&velem[0], 0, sizeof(velem[0]) * 2); + for (i = 0; i < 2; i++) { + velem[i].src_offset = i * 4 * sizeof(float); + velem[i].instance_divisor = 0; + velem[i].vertex_buffer_index = 0; + velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); + /* fragment shaders are created on-demand */ /* vertex shaders */ @@ -219,6 +238,7 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_rasterizer_state(pipe, ctx->rs_state); pipe->delete_vs_state(pipe, ctx->vs_col); pipe->delete_vs_state(pipe, ctx->vs_tex); + pipe->delete_vertex_elements_state(pipe, ctx->velem_state); for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { if (ctx->fs_texfetch_col[i]) @@ -235,6 +255,10 @@ void util_blitter_destroy(struct blitter_context *blitter) if (ctx->sampler_state[i]) pipe->delete_sampler_state(pipe, ctx->sampler_state[i]); + if (ctx->sampler_view) { + pipe_sampler_view_reference(&ctx->sampler_view, NULL); + } + pipe_buffer_reference(&ctx->vbuf, NULL); FREE(ctx); } @@ -246,7 +270,8 @@ static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx) ctx->blitter.saved_dsa_state != INVALID_PTR && ctx->blitter.saved_rs_state != INVALID_PTR && ctx->blitter.saved_fs != INVALID_PTR && - ctx->blitter.saved_vs != INVALID_PTR); + ctx->blitter.saved_vs != INVALID_PTR && + ctx->blitter.saved_velem_state != INVALID_PTR); } static void blitter_restore_CSOs(struct blitter_context_priv *ctx) @@ -259,12 +284,14 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx) pipe->bind_rasterizer_state(pipe, ctx->blitter.saved_rs_state); pipe->bind_fs_state(pipe, ctx->blitter.saved_fs); pipe->bind_vs_state(pipe, ctx->blitter.saved_vs); + pipe->bind_vertex_elements_state(pipe, ctx->blitter.saved_velem_state); ctx->blitter.saved_blend_state = INVALID_PTR; ctx->blitter.saved_dsa_state = INVALID_PTR; ctx->blitter.saved_rs_state = INVALID_PTR; ctx->blitter.saved_fs = INVALID_PTR; ctx->blitter.saved_vs = INVALID_PTR; + ctx->blitter.saved_velem_state = INVALID_PTR; pipe->set_stencil_ref(pipe, &ctx->blitter.saved_stencil_ref); @@ -285,11 +312,11 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx) ctx->blitter.saved_num_sampler_states = ~0; } - if (ctx->blitter.saved_num_textures != ~0) { - pipe->set_fragment_sampler_textures(pipe, - ctx->blitter.saved_num_textures, - ctx->blitter.saved_textures); - ctx->blitter.saved_num_textures = ~0; + if (ctx->blitter.saved_num_sampler_views != ~0) { + pipe->set_fragment_sampler_views(pipe, + ctx->blitter.saved_num_sampler_views, + ctx->blitter.saved_sampler_views); + ctx->blitter.saved_num_sampler_views = ~0; } } @@ -569,6 +596,7 @@ void util_blitter_clear(struct blitter_context *blitter, pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs)); pipe->bind_vs_state(pipe, ctx->vs_col); @@ -600,9 +628,10 @@ static void util_blitter_do_copy(struct blitter_context *blitter, struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->pipe; struct pipe_framebuffer_state fb_state; + struct pipe_sampler_view viewTempl, *view; assert(blitter->saved_fb_state.nr_cbufs != ~0); - assert(blitter->saved_num_textures != ~0); + assert(blitter->saved_num_sampler_views != ~0); assert(blitter->saved_num_sampler_states != ~0); assert(src->texture->target < PIPE_MAX_TEXTURE_TYPES); @@ -630,11 +659,24 @@ static void util_blitter_do_copy(struct blitter_context *blitter, fb_state.zsbuf = 0; } + u_sampler_view_default_template(&viewTempl, + src->texture, + src->texture->format); + view = pipe->create_sampler_view(pipe, + src->texture, + &viewTempl); + + if (ctx->sampler_view) { + pipe_sampler_view_reference(&ctx->sampler_view, NULL); + } + ctx->sampler_view = view; + pipe->bind_rasterizer_state(pipe, ctx->rs_state); pipe->bind_vs_state(pipe, ctx->vs_tex); pipe->bind_fragment_sampler_states(pipe, 1, blitter_get_sampler_state(ctx, src->level)); - pipe->set_fragment_sampler_textures(pipe, 1, &src->texture); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + pipe->set_fragment_sampler_views(pipe, 1, &view); pipe->set_framebuffer_state(pipe, &fb_state); /* set texture coordinates */ @@ -807,6 +849,7 @@ void util_blitter_fill(struct blitter_context *blitter, pipe->bind_rasterizer_state(pipe, ctx->rs_state); pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1)); pipe->bind_vs_state(pipe, ctx->vs_col); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); /* set a framebuffer state */ fb_state.width = dst->width; diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index 92008fce992..2ad7201a29d 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -43,6 +43,7 @@ struct blitter_context /* Private members, really. */ void *saved_blend_state; /**< blend state */ void *saved_dsa_state; /**< depth stencil alpha state */ + void *saved_velem_state; /**< vertex elements state */ void *saved_rs_state; /**< rasterizer state */ void *saved_fs, *saved_vs; /**< fragment shader, vertex shader */ @@ -52,10 +53,10 @@ struct blitter_context struct pipe_clip_state saved_clip; int saved_num_sampler_states; - void *saved_sampler_states[32]; + void *saved_sampler_states[PIPE_MAX_SAMPLERS]; - int saved_num_textures; - struct pipe_texture *saved_textures[32]; /* is 32 enough? */ + int saved_num_sampler_views; + struct pipe_sampler_view *saved_sampler_views[PIPE_MAX_SAMPLERS]; }; /** @@ -173,6 +174,13 @@ void util_blitter_save_depth_stencil_alpha(struct blitter_context *blitter, } static INLINE +void util_blitter_save_vertex_elements(struct blitter_context *blitter, + void *state) +{ + blitter->saved_velem_state = state; +} + +static INLINE void util_blitter_save_stencil_ref(struct blitter_context *blitter, const struct pipe_stencil_ref *state) { @@ -234,17 +242,17 @@ void util_blitter_save_fragment_sampler_states( num_sampler_states * sizeof(void *)); } -static INLINE -void util_blitter_save_fragment_sampler_textures( - struct blitter_context *blitter, - int num_textures, - struct pipe_texture **textures) +static INLINE void +util_blitter_save_fragment_sampler_views(struct blitter_context *blitter, + int num_views, + struct pipe_sampler_view **views) { - assert(num_textures <= Elements(blitter->saved_textures)); + assert(num_views <= Elements(blitter->saved_sampler_views)); - blitter->saved_num_textures = num_textures; - memcpy(blitter->saved_textures, textures, - num_textures * sizeof(struct pipe_texture *)); + blitter->saved_num_sampler_views = num_views; + memcpy(blitter->saved_sampler_views, + views, + num_views * sizeof(struct pipe_sampler_view *)); } #ifdef __cplusplus diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c index 94be682c4b1..e997cfa8a38 100644 --- a/src/gallium/auxiliary/util/u_debug.c +++ b/src/gallium/auxiliary/util/u_debug.c @@ -421,26 +421,31 @@ void debug_dump_image(const char *prefix, #endif } -void debug_dump_surface(const char *prefix, +void debug_dump_surface(struct pipe_context *pipe, + const char *prefix, struct pipe_surface *surface) { struct pipe_texture *texture; - struct pipe_screen *screen; struct pipe_transfer *transfer; void *data; if (!surface) return; + /* XXX: this doesn't necessarily work, as the driver may be using + * temporary storage for the surface which hasn't been propagated + * back into the texture. Need to nail down the semantics of views + * and transfers a bit better before we can say if extra work needs + * to be done here: + */ texture = surface->texture; - screen = texture->screen; - transfer = screen->get_tex_transfer(screen, texture, surface->face, - surface->level, surface->zslice, - PIPE_TRANSFER_READ, 0, 0, surface->width, - surface->height); + transfer = pipe->get_tex_transfer(pipe, texture, surface->face, + surface->level, surface->zslice, + PIPE_TRANSFER_READ, 0, 0, surface->width, + surface->height); - data = screen->transfer_map(screen, transfer); + data = pipe->transfer_map(pipe, transfer); if(!data) goto error; @@ -452,13 +457,14 @@ void debug_dump_surface(const char *prefix, transfer->stride, data); - screen->transfer_unmap(screen, transfer); + pipe->transfer_unmap(pipe, transfer); error: - screen->tex_transfer_destroy(transfer); + pipe->tex_transfer_destroy(pipe, transfer); } -void debug_dump_texture(const char *prefix, +void debug_dump_texture(struct pipe_context *pipe, + const char *prefix, struct pipe_texture *texture) { struct pipe_surface *surface; @@ -473,7 +479,7 @@ void debug_dump_texture(const char *prefix, surface = screen->get_tex_surface(screen, texture, 0, 0, 0, PIPE_TEXTURE_USAGE_SAMPLER); if (surface) { - debug_dump_surface(prefix, surface); + debug_dump_surface(pipe, prefix, surface); screen->tex_surface_destroy(surface); } } @@ -511,27 +517,28 @@ struct bmp_rgb_quad { }; void -debug_dump_surface_bmp(const char *filename, +debug_dump_surface_bmp(struct pipe_context *pipe, + const char *filename, struct pipe_surface *surface) { #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT struct pipe_transfer *transfer; struct pipe_texture *texture = surface->texture; - struct pipe_screen *screen = texture->screen; - transfer = screen->get_tex_transfer(screen, texture, surface->face, - surface->level, surface->zslice, - PIPE_TRANSFER_READ, 0, 0, surface->width, - surface->height); + transfer = pipe->get_tex_transfer(pipe, texture, surface->face, + surface->level, surface->zslice, + PIPE_TRANSFER_READ, 0, 0, surface->width, + surface->height); - debug_dump_transfer_bmp(filename, transfer); + debug_dump_transfer_bmp(pipe, filename, transfer); - screen->tex_transfer_destroy(transfer); + pipe->tex_transfer_destroy(pipe, transfer); #endif } void -debug_dump_transfer_bmp(const char *filename, +debug_dump_transfer_bmp(struct pipe_context *pipe, + const char *filename, struct pipe_transfer *transfer) { #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT @@ -544,7 +551,7 @@ debug_dump_transfer_bmp(const char *filename, if(!rgba) goto error1; - pipe_get_tile_rgba(transfer, 0, 0, + pipe_get_tile_rgba(pipe, transfer, 0, 0, transfer->width, transfer->height, rgba); diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h index 0f4768f3444..98addeb372e 100644 --- a/src/gallium/auxiliary/util/u_debug.h +++ b/src/gallium/auxiliary/util/u_debug.h @@ -312,6 +312,7 @@ debug_memory_end(unsigned long beginning); #ifdef DEBUG +struct pipe_context; struct pipe_surface; struct pipe_transfer; struct pipe_texture; @@ -321,21 +322,25 @@ void debug_dump_image(const char *prefix, unsigned width, unsigned height, unsigned stride, const void *data); -void debug_dump_surface(const char *prefix, +void debug_dump_surface(struct pipe_context *pipe, + const char *prefix, struct pipe_surface *surface); -void debug_dump_texture(const char *prefix, +void debug_dump_texture(struct pipe_context *pipe, + const char *prefix, struct pipe_texture *texture); -void debug_dump_surface_bmp(const char *filename, +void debug_dump_surface_bmp(struct pipe_context *pipe, + const char *filename, struct pipe_surface *surface); -void debug_dump_transfer_bmp(const char *filename, +void debug_dump_transfer_bmp(struct pipe_context *pipe, + const char *filename, struct pipe_transfer *transfer); void debug_dump_float_rgba_bmp(const char *filename, unsigned width, unsigned height, float *rgba, unsigned stride); #else #define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0) -#define debug_dump_surface(prefix, surface) ((void)0) -#define debug_dump_surface_bmp(filename, surface) ((void)0) +#define debug_dump_surface(pipe, prefix, surface) ((void)0) +#define debug_dump_surface_bmp(pipe, filename, surface) ((void)0) #define debug_dump_transfer_bmp(filename, transfer) ((void)0) #define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0) #endif diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c index 14506e84519..8c194102bfc 100644 --- a/src/gallium/auxiliary/util/u_draw_quad.c +++ b/src/gallium/auxiliary/util/u_draw_quad.c @@ -45,8 +45,6 @@ util_draw_vertex_buffer(struct pipe_context *pipe, uint num_attribs) { struct pipe_vertex_buffer vbuffer; - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; - uint i; assert(num_attribs <= PIPE_MAX_ATTRIBS); @@ -58,15 +56,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe, vbuffer.max_index = num_verts - 1; pipe->set_vertex_buffers(pipe, 1, &vbuffer); - /* tell pipe about the vertex attributes */ - for (i = 0; i < num_attribs; i++) { - velements[i].src_offset = i * 4 * sizeof(float); - velements[i].instance_divisor = 0; - velements[i].vertex_buffer_index = 0; - velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - velements[i].nr_components = 4; - } - pipe->set_vertex_elements(pipe, num_attribs, velements); + /* note: vertex elements already set by caller */ /* draw */ pipe->draw_arrays(pipe, prim_type, 0, num_verts); diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c index ae7afd7311e..52cf3ef4ce0 100644 --- a/src/gallium/auxiliary/util/u_dump_state.c +++ b/src/gallium/auxiliary/util/u_dump_state.c @@ -700,7 +700,6 @@ util_dump_vertex_element(struct os_stream *stream, const struct pipe_vertex_elem util_dump_member(stream, uint, state, src_offset); util_dump_member(stream, uint, state, vertex_buffer_index); - util_dump_member(stream, uint, state, nr_components); util_dump_member(stream, format, state, src_format); diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h index e8fa0022b5b..c08fdcafcc8 100644 --- a/src/gallium/auxiliary/util/u_format.h +++ b/src/gallium/auxiliary/util/u_format.h @@ -120,9 +120,15 @@ struct util_format_channel_description struct util_format_description { enum pipe_format format; + const char *name; /** + * Short name, striped of the prefix, lower case. + */ + const char *short_name; + + /** * Pixel block dimensions. */ struct util_format_block block; @@ -140,6 +146,15 @@ struct util_format_description unsigned is_array:1; /** + * Whether the pixel format can be described as a bitfield structure. + * + * In particular: + * - pixel depth must be 8, 16, or 32 bits; + * - all channels must be unsigned, signed, or void + */ + unsigned is_bitmask:1; + + /** * Whether channels have mixed types (ignoring UTIL_FORMAT_TYPE_VOID). */ unsigned is_mixed:1; @@ -400,6 +415,16 @@ util_format_has_alpha(enum pipe_format format) } } +/** + * Return the number of components stored. + * Formats with block size != 1x1 will always have 1 component (the block). + */ +static INLINE unsigned +util_format_get_nr_components(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + return desc->nr_channels; +} /* * Format access functions. diff --git a/src/gallium/auxiliary/util/u_format_pack.py b/src/gallium/auxiliary/util/u_format_pack.py index 3f33f7cc021..409d024c637 100644 --- a/src/gallium/auxiliary/util/u_format_pack.py +++ b/src/gallium/auxiliary/util/u_format_pack.py @@ -252,9 +252,6 @@ def conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=True if src_channel.type == FLOAT and dst_channel.type == FLOAT: return '(%s)%s' % (dst_native_type, value) - if not src_channel.norm and not dst_channel.norm: - return '(%s)%s' % (dst_native_type, value) - if clamp: value = clamp_expr(src_channel, dst_channel, dst_native_type, value) @@ -280,15 +277,15 @@ def conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=True value = '(%s * %s)' % (value, scale) return '(%s)%s' % (dst_native_type, value) - if not src_channel.norm and not dst_channel.norm: - # neither is normalized -- just cast - return '(%s)%s' % (dst_native_type, value) - if src_channel.type in (SIGNED, UNSIGNED) and dst_channel.type in (SIGNED, UNSIGNED): + if not src_channel.norm and not dst_channel.norm: + # neither is normalized -- just cast + return '(%s)%s' % (dst_native_type, value) + src_one = get_one(src_channel) dst_one = get_one(dst_channel) - if src_one > dst_one and src_channel.norm: + if src_one > dst_one and src_channel.norm and dst_channel.norm: # We can just bitshift src_shift = get_one_shift(src_channel) dst_shift = get_one_shift(dst_channel) @@ -296,7 +293,7 @@ def conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=True else: # We need to rescale using an intermediate type big enough to hold the multiplication of both tmp_native_type = intermediate_native_type(src_channel.size + dst_channel.size, src_channel.sign and dst_channel.sign) - value = '(%s)%s' % (tmp_native_type, value) + value = '((%s)%s)' % (tmp_native_type, value) value = '(%s * 0x%x / 0x%x)' % (value, dst_one, src_one) value = '(%s)%s' % (dst_native_type, value) return value @@ -307,6 +304,8 @@ def conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=True def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix): '''Generate the function to unpack pixels from a particular format''' + assert format.layout == PLAIN + name = format.short_name() src_native_type = native_type(format) @@ -314,32 +313,99 @@ def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix): print 'static INLINE void' print 'util_format_%s_unpack_%s(%s *dst, const void *src)' % (name, dst_suffix, dst_native_type) print '{' - print ' union util_format_%s pixel;' % format.short_name() - print ' memcpy(&pixel, src, sizeof pixel);' - bswap_format(format) + + if format.is_bitmask(): + depth = format.block_size() + print ' uint%u_t value = *(uint%u_t *)src;' % (depth, depth) - assert format.layout == PLAIN + # Declare the intermediate variables + for i in range(format.nr_channels()): + src_channel = format.channels[i] + if src_channel.type == UNSIGNED: + print ' uint%u_t %s;' % (depth, src_channel.name) + elif src_channel.type == SIGNED: + print ' int%u_t %s;' % (depth, src_channel.name) - for i in range(4): - swizzle = format.swizzles[i] - if swizzle < 4: - src_channel = format.channels[swizzle] - value = 'pixel.chan.%s' % src_channel.name - value = conversion_expr(src_channel, dst_channel, dst_native_type, value) - elif swizzle == SWIZZLE_0: - value = '0' - elif swizzle == SWIZZLE_1: - value = get_one(dst_channel) - elif swizzle == SWIZZLE_NONE: - value = '0' - else: - assert False - if format.colorspace == ZS: - if i == 3: + print '#ifdef PIPE_ARCH_BIG_ENDIAN' + print ' value = util_bswap%u(value);' % depth + print '#endif' + + # Compute the intermediate unshifted values + shift = 0 + for i in range(format.nr_channels()): + src_channel = format.channels[i] + value = 'value' + if src_channel.type == UNSIGNED: + if shift: + value = '%s >> %u' % (value, shift) + if shift + src_channel.size < depth: + value = '(%s) & 0x%x' % (value, (1 << src_channel.size) - 1) + elif src_channel.type == SIGNED: + if shift + src_channel.size < depth: + # Align the sign bit + lshift = depth - (shift + src_channel.size) + value = '%s << %u' % (value, lshift) + # Cast to signed + value = '(int%u_t)(%s) ' % (depth, value) + if src_channel.size < depth: + # Align the LSB bit + rshift = depth - src_channel.size + value = '(%s) >> %u' % (value, rshift) + else: + value = None + + if value is not None: + print ' %s = %s;' % (src_channel.name, value) + + shift += src_channel.size + + # Convert, swizzle, and store final values + for i in range(4): + swizzle = format.swizzles[i] + if swizzle < 4: + src_channel = format.channels[swizzle] + value = src_channel.name + value = conversion_expr(src_channel, dst_channel, dst_native_type, value) + elif swizzle == SWIZZLE_0: + value = '0' + elif swizzle == SWIZZLE_1: + value = get_one(dst_channel) + elif swizzle == SWIZZLE_NONE: + value = '0' + else: + assert False + if format.colorspace == ZS: + if i == 3: + value = get_one(dst_channel) + elif i >= 1: + value = 'dst[0]' + print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i]) + + else: + print ' union util_format_%s pixel;' % format.short_name() + print ' memcpy(&pixel, src, sizeof pixel);' + bswap_format(format) + + for i in range(4): + swizzle = format.swizzles[i] + if swizzle < 4: + src_channel = format.channels[swizzle] + value = 'pixel.chan.%s' % src_channel.name + value = conversion_expr(src_channel, dst_channel, dst_native_type, value) + elif swizzle == SWIZZLE_0: + value = '0' + elif swizzle == SWIZZLE_1: value = get_one(dst_channel) - elif i >= 1: - value = 'dst[0]' - print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i]) + elif swizzle == SWIZZLE_NONE: + value = '0' + else: + assert False + if format.colorspace == ZS: + if i == 3: + value = get_one(dst_channel) + elif i >= 1: + value = 'dst[0]' + print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i]) print '}' print @@ -352,31 +418,70 @@ def generate_format_pack(format, src_channel, src_native_type, src_suffix): dst_native_type = native_type(format) - print 'static INLINE void' - print 'util_format_%s_pack_%s(void *dst, %s r, %s g, %s b, %s a)' % (name, src_suffix, src_native_type, src_native_type, src_native_type, src_native_type) - print '{' - print ' union util_format_%s pixel;' % format.short_name() - assert format.layout == PLAIN inv_swizzle = format.inv_swizzles() + + print 'static INLINE void' + print 'util_format_%s_pack_%s(void *dst, %s r, %s g, %s b, %s a)' % (name, src_suffix, src_native_type, src_native_type, src_native_type, src_native_type) + print '{' + + if format.is_bitmask(): + depth = format.block_size() + print ' uint%u_t value = 0;' % depth + + shift = 0 + for i in range(4): + dst_channel = format.channels[i] + if inv_swizzle[i] is not None: + value = 'rgba'[inv_swizzle[i]] + value = conversion_expr(src_channel, dst_channel, dst_native_type, value) + if format.colorspace == ZS: + if i == 3: + value = get_one(dst_channel) + elif i >= 1: + value = '0' + if dst_channel.type in (UNSIGNED, SIGNED): + if shift + dst_channel.size < depth: + value = '(%s) & 0x%x' % (value, (1 << dst_channel.size) - 1) + if shift: + value = '(%s) << %u' % (value, shift) + if dst_channel.type == SIGNED: + # Cast to unsigned + value = '(uint%u_t)(%s) ' % (depth, value) + else: + value = None + if value is not None: + print ' value |= %s;' % (value) + + shift += dst_channel.size - for i in range(4): - dst_channel = format.channels[i] - width = dst_channel.size - if inv_swizzle[i] is None: - continue - value = 'rgba'[inv_swizzle[i]] - value = conversion_expr(src_channel, dst_channel, dst_native_type, value) - if format.colorspace == ZS: - if i == 3: - value = get_one(dst_channel) - elif i >= 1: - value = '0' - print ' pixel.chan.%s = %s;' % (dst_channel.name, value) + print '#ifdef PIPE_ARCH_BIG_ENDIAN' + print ' value = util_bswap%u(value);' % depth + print '#endif' + + print ' *(uint%u_t *)dst = value;' % depth - bswap_format(format) - print ' memcpy(dst, &pixel, sizeof pixel);' + else: + print ' union util_format_%s pixel;' % format.short_name() + + for i in range(4): + dst_channel = format.channels[i] + width = dst_channel.size + if inv_swizzle[i] is None: + continue + value = 'rgba'[inv_swizzle[i]] + value = conversion_expr(src_channel, dst_channel, dst_native_type, value) + if format.colorspace == ZS: + if i == 3: + value = get_one(dst_channel) + elif i >= 1: + value = '0' + print ' pixel.chan.%s = %s;' % (dst_channel.name, value) + + bswap_format(format) + print ' memcpy(dst, &pixel, sizeof pixel);' + print '}' print diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py index 250926418ec..f74dc5e88a4 100755 --- a/src/gallium/auxiliary/util/u_format_parse.py +++ b/src/gallium/auxiliary/util/u_format_parse.py @@ -78,7 +78,7 @@ class Channel: if self.type == UNSIGNED: return (1 << self.size) - 1 if self.type == SIGNED: - return self.size - 1 + return (1 << (self.size - 1)) - 1 assert False def min(self): @@ -166,17 +166,11 @@ class Format: return True def is_bitmask(self): - if self.block_size() > 32: - return False - if not self.is_pot(): + if self.block_size() not in (8, 16, 32): return False for channel in self.channels: - if not is_pot(channel.size): - return True if channel.type not in (VOID, UNSIGNED, SIGNED): return False - if channel.size >= 32: - return False return True def inv_swizzles(self): diff --git a/src/gallium/auxiliary/util/u_format_table.py b/src/gallium/auxiliary/util/u_format_table.py index 4e29d15f3bb..fb68852a530 100755 --- a/src/gallium/auxiliary/util/u_format_table.py +++ b/src/gallium/auxiliary/util/u_format_table.py @@ -90,11 +90,13 @@ def write_format_table(formats): print 'util_format_none_description = {' print " PIPE_FORMAT_NONE," print " \"PIPE_FORMAT_NONE\"," + print " \"none\"," print " {0, 0, 0}," print " 0," print " 0," print " 0," print " 0," + print " 0," print " {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}," print " {0, 0, 0, 0}," print " 0" @@ -105,10 +107,12 @@ def write_format_table(formats): print 'util_format_%s_description = {' % (format.short_name(),) print " %s," % (format.name,) print " \"%s\"," % (format.name,) + print " \"%s\"," % (format.short_name(),) print " {%u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_size()) print " %s," % (layout_map(format.layout),) print " %u,\t/* nr_channels */" % (format.nr_channels(),) print " %s,\t/* is_array */" % (bool_map(format.is_array()),) + print " %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),) print " %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),) print " {" for i in range(4): diff --git a/src/gallium/auxiliary/util/u_format_tests.c b/src/gallium/auxiliary/util/u_format_tests.c new file mode 100644 index 00000000000..182a4740448 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_tests.c @@ -0,0 +1,544 @@ +/************************************************************************** + * + * Copyright 2009-2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "u_memory.h" +#include "u_format_tests.h" + + +/* + * Helper macros to create the packed bytes for longer words. + */ + +#define PACKED_1x8(x) {x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_2x8(x, y) {x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_3x8(x, y, z) {x, y, z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_4x8(x, y, z, w) {x, y, z, w, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +#define PACKED_1x16(x) {(x) & 0xff, (x) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_2x16(x, y) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_3x16(x, y, z) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_4x16(x, y, z, w) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, (w) & 0xff, (w) >> 8, 0, 0, 0, 0, 0, 0, 0, 0} + +#define PACKED_1x32(x) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_2x32(x, y) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_3x32(x, y, z) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, 0, 0, 0, 0} +#define PACKED_4x32(x, y, z, w) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, (w) & 0xff, ((w) >> 8) & 0xff, ((w) >> 16) & 0xff, (w) >> 24} + + +/** + * Test cases. + * + * These were manually entered. We could generate these + * + * To keep this to a we cover only the corner cases, which should produce + * good enough coverage since that pixel format transformations are afine for + * non SRGB formats. + */ +const struct util_format_test_case +util_format_test_cases[] = +{ + + /* + * 32-bit rendertarget formats + */ + + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xff000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), {0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), {0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000003ff), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000ffc00), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x3ff00000), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + /* + * 16-bit rendertarget formats + */ + + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7c00), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00f0), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0f00), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x07e0), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf800), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, + + /* + * Luminance/intensity/alpha formats + */ + + {PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {0.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00ff), {1.0, 1.0, 1.0, 0.0}}, + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xff00), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, + + /* + * TODO: SRGB formats + */ + + /* + * Mixed-signed formats + */ + + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x81, 0x00, 0x00, 0x00), {-1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x81, 0x00, 0x00), { 0.0, -1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x00, 0xff, 0x00), { 0.0, 0.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0011), {-1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x01e0), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0220), { 0.0, -1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0xfc00), { 0.0, 0.0, 1.0, 1.0}}, + + /* + * TODO: Depth-stencil formats + */ + + /* + * TODO: YUV formats + */ + + /* + * TODO: Compressed formats + */ + + /* + * Standard 8-bit integer formats + */ + + {PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), {1.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), {1.0, 1.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), {0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0xff), {255.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), {255.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), { 0.0, 255.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), {255.0, 255.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), {255.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), { 0.0, 255.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), { 0.0, 0.0, 255.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), {255.0, 255.0, 255.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), {255.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), { 0.0, 255.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), { 0.0, 0.0, 255.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), { 0.0, 0.0, 0.0, 255.0}}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), {255.0, 255.0, 255.0, 255.0}}, + + {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x7f), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x81), {-1.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x81, 0x00), {-1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x81), { 0.0, -1.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x81, 0x00, 0x00), {-1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x81, 0x00), { 0.0, -1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), { 0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x81), { 0.0, 0.0, -1.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), { 1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x81, 0x00, 0x00, 0x00), {-1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), { 0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x81, 0x00, 0x00), { 0.0, -1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), { 0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x81, 0x00), { 0.0, 0.0, -1.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x81), { 0.0, 0.0, 0.0, -1.0}}, + + {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x7f), { 127.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x80), {-128.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), { 127.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x80, 0x00), {-128.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), { 0.0, 127.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x80), { 0.0, -128.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), { 127.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x80, 0x00, 0x00), {-128.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), { 0.0, 127.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x80, 0x00), { 0.0, -128.0, 0.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), { 0.0, 0.0, 127.0, 1.0}}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x80), { 0.0, 0.0, -128.0, 1.0}}, + + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), { 127.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x00, 0x00, 0x00), {-128.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), { 0.0, 127.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x80, 0x00, 0x00), { 0.0, -128.0, 0.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), { 0.0, 0.0, 127.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x80, 0x00), { 0.0, 0.0, -128.0, 0.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), { 0.0, 0.0, 0.0, 127.0}}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x80), { 0.0, 0.0, 0.0, -128.0}}, + + /* + * Standard 16-bit integer formats + */ + + {PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {1.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), {1.0, 1.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), {0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0xffff), {65535.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), {65535.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), { 0.0, 65535.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), {65535.0, 65535.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), {65535.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), { 0.0, 65535.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), { 0.0, 0.0, 65535.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), {65535.0, 65535.0, 65535.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), {65535.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), { 0.0, 65535.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), { 0.0, 0.0, 65535.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), { 0.0, 0.0, 0.0, 65535.0}}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), {65535.0, 65535.0, 65535.0, 65535.0}}, + + {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8001), { -1.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8001, 0x0000), { -1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8001), { 0.0, -1.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8001, 0x0000, 0x0000), { -1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8001, 0x0000), { 0.0, -1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8001), { 0.0, 0.0, -1.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), { 1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8001, 0x0000, 0x0000, 0x0000), { -1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), { 0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8001, 0x0000, 0x0000), { 0.0, -1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), { 0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8001, 0x0000), { 0.0, 0.0, -1.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8001), { 0.0, 0.0, 0.0, -1.0}}, + + {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), { 32767.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x8000), {-32768.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), { 32767.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8000, 0x0000), {-32768.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), { 0.0, 32767.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8000), { 0.0, -32768.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), { 32767.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8000, 0x0000, 0x0000), {-32768.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), { 0.0, 32767.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8000, 0x0000), { 0.0, -32768.0, 0.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 32767.0, 1.0}}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8000), { 0.0, 0.0, -32768.0, 1.0}}, + + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), { 32767.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8000, 0x0000, 0x0000, 0x0000), {-32768.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), { 0.0, 32767.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8000, 0x0000, 0x0000), { 0.0, -32768.0, 0.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), { 0.0, 0.0, 32767.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8000, 0x0000), { 0.0, 0.0, -32768.0, 0.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), { 0.0, 0.0, 0.0, 32767.0}}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8000), { 0.0, 0.0, 0.0, -32768.0}}, + + /* + * Standard 32-bit integer formats + * + * NOTE: We can't accurately represent integers larger than +/-0x1000000 + * with single precision floats, so that's as far as we test. + */ + + {PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), {1.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0x00000000), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xffffffff), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0xffffffff), {1.0, 1.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0x00000000, 0x00000000), {1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xffffffff, 0x00000000), {0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xffffffff), {0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0x00000000, 0x00000000, 0x00000000), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xffffffff, 0x00000000, 0x00000000), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xffffffff, 0x00000000), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xffffffff), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), {1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), {16777216.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), {16777216.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), { 0.0, 16777216.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x01000000), {16777216.0, 16777216.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), {16777216.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), { 0.0, 16777216.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 16777216.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x01000000, 0x01000000), {16777216.0, 16777216.0, 16777216.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), {16777216.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), { 0.0, 16777216.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), { 0.0, 0.0, 16777216.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 0.0, 16777216.0}}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x01000000, 0x01000000, 0x01000000), {16777216.0, 16777216.0, 16777216.0, 16777216.0}}, + + {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x7fffffff), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x80000001), { -1.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x7fffffff, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x80000001, 0x00000000), { -1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x7fffffff), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x80000001), { 0.0, -1.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x7fffffff, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x80000001, 0x00000000, 0x00000000), { -1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x7fffffff, 0x00000000), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x80000001, 0x00000000), { 0.0, -1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x7fffffff), { 0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x80000001), { 0.0, 0.0, -1.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x7fffffff, 0x00000000, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x80000001, 0x00000000, 0x00000000, 0x00000000), { -1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x7fffffff, 0x00000000, 0x00000000), { 0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x80000001, 0x00000000, 0x00000000), { 0.0, -1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x7fffffff, 0x00000000), { 0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x80000001, 0x00000000), { 0.0, 0.0, -1.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x7fffffff), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x80000001), { 0.0, 0.0, 0.0, -1.0}}, + + {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), { 16777216.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), {-16777216.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), { 16777216.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xff000000, 0x00000000), {-16777216.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), { 0.0, 16777216.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xff000000), { 0.0, -16777216.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), { 16777216.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xff000000, 0x00000000, 0x00000000), {-16777216.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), { 0.0, 16777216.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xff000000, 0x00000000), { 0.0, -16777216.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 16777216.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xff000000), { 0.0, 0.0, -16777216.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), { 16777216.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xff000000, 0x00000000, 0x00000000, 0x00000000), {-16777216.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), { 0.0, 16777216.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xff000000, 0x00000000, 0x00000000), { 0.0, -16777216.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), { 0.0, 0.0, 16777216.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xff000000, 0x00000000), { 0.0, 0.0, -16777216.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), { 0.0, 0.0, 0.0, 16777216.0}}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xff000000), { 0.0, 0.0, 0.0, -16777216.0}}, + + /* + * Standard 32-bit float formats + */ + + {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x3f800000), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0xbf800000), { -1.0, 0.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xbf800000, 0x00000000), {-1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x3f800000), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xbf800000), { 0.0, -1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x3f800000), { 1.0, 1.0, 0.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xbf800000, 0x00000000, 0x00000000), {-1.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x3f800000, 0x00000000), { 0.0, 1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xbf800000, 0x00000000), { 0.0, -1.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x3f800000), { 0.0, 0.0, 1.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xbf800000), { 0.0, 0.0, -1.0, 1.0}}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x3f800000, 0x3f800000), { 1.0, 1.0, 1.0, 1.0}}, + + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), { 0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x00000000, 0x00000000, 0x00000000), { 1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xbf800000, 0x00000000, 0x00000000, 0x00000000), {-1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x3f800000, 0x00000000, 0x00000000), { 0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xbf800000, 0x00000000, 0x00000000), { 0.0, -1.0, 0.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x3f800000, 0x00000000), { 0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xbf800000, 0x00000000), { 0.0, 0.0, -1.0, 0.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x3f800000), { 0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xbf800000), { 0.0, 0.0, 0.0, -1.0}}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000), { 1.0, 1.0, 1.0, 1.0}}, +}; + + +const unsigned util_format_nr_test_cases = Elements(util_format_test_cases); diff --git a/src/gallium/auxiliary/util/u_format_tests.h b/src/gallium/auxiliary/util/u_format_tests.h new file mode 100644 index 00000000000..2d4d9d5fa9d --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_tests.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#ifndef U_FORMAT_TESTS_H_ +#define U_FORMAT_TESTS_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + + +#define UTIL_FORMAT_MAX_PACKED_BYTES 16 + + +/** + * A (packed, unpacked) color pair. + */ +struct util_format_test_case +{ + enum pipe_format format; + + /** + * Mask of the bits that actually meaningful data. Used to mask out the + * "X" channels. + */ + uint8_t mask[UTIL_FORMAT_MAX_PACKED_BYTES]; + + uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; + + /** + * RGBA. + */ + double unpacked[4]; +}; + + +extern const struct util_format_test_case +util_format_test_cases[]; + + +extern const unsigned util_format_nr_test_cases; + + +#endif /* U_FORMAT_TESTS_H_ */ diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index fc027e48e4e..61d64cff6d4 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -62,6 +62,7 @@ struct gen_mipmap_state struct pipe_rasterizer_state rasterizer; struct pipe_sampler_state sampler; struct pipe_clip_state clip; + struct pipe_vertex_element velem[2]; void *vs; void *fs2d, *fsCube; @@ -1118,7 +1119,6 @@ make_1d_mipmap(struct gen_mipmap_state *ctx, uint face, uint baseLevel, uint lastLevel) { struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; const uint zslice = 0; uint dstLevel; @@ -1127,27 +1127,27 @@ make_1d_mipmap(struct gen_mipmap_state *ctx, struct pipe_transfer *srcTrans, *dstTrans; void *srcMap, *dstMap; - srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice, + srcTrans = pipe->get_tex_transfer(pipe, pt, face, srcLevel, zslice, PIPE_TRANSFER_READ, 0, 0, u_minify(pt->width0, srcLevel), u_minify(pt->height0, srcLevel)); - dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice, + dstTrans = pipe->get_tex_transfer(pipe, pt, face, dstLevel, zslice, PIPE_TRANSFER_WRITE, 0, 0, u_minify(pt->width0, dstLevel), u_minify(pt->height0, dstLevel)); - srcMap = (ubyte *) screen->transfer_map(screen, srcTrans); - dstMap = (ubyte *) screen->transfer_map(screen, dstTrans); + srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); + dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); reduce_1d(pt->format, srcTrans->width, srcMap, dstTrans->width, dstMap); - screen->transfer_unmap(screen, srcTrans); - screen->transfer_unmap(screen, dstTrans); + pipe->transfer_unmap(pipe, srcTrans); + pipe->transfer_unmap(pipe, dstTrans); - screen->tex_transfer_destroy(srcTrans); - screen->tex_transfer_destroy(dstTrans); + pipe->tex_transfer_destroy(pipe, srcTrans); + pipe->tex_transfer_destroy(pipe, dstTrans); } } @@ -1158,7 +1158,6 @@ make_2d_mipmap(struct gen_mipmap_state *ctx, uint face, uint baseLevel, uint lastLevel) { struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; const uint zslice = 0; uint dstLevel; @@ -1170,17 +1169,17 @@ make_2d_mipmap(struct gen_mipmap_state *ctx, struct pipe_transfer *srcTrans, *dstTrans; ubyte *srcMap, *dstMap; - srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice, + srcTrans = pipe->get_tex_transfer(pipe, pt, face, srcLevel, zslice, PIPE_TRANSFER_READ, 0, 0, u_minify(pt->width0, srcLevel), u_minify(pt->height0, srcLevel)); - dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice, + dstTrans = pipe->get_tex_transfer(pipe, pt, face, dstLevel, zslice, PIPE_TRANSFER_WRITE, 0, 0, u_minify(pt->width0, dstLevel), u_minify(pt->height0, dstLevel)); - srcMap = (ubyte *) screen->transfer_map(screen, srcTrans); - dstMap = (ubyte *) screen->transfer_map(screen, dstTrans); + srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); + dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); reduce_2d(pt->format, srcTrans->width, srcTrans->height, @@ -1188,11 +1187,11 @@ make_2d_mipmap(struct gen_mipmap_state *ctx, dstTrans->width, dstTrans->height, dstTrans->stride, dstMap); - screen->transfer_unmap(screen, srcTrans); - screen->transfer_unmap(screen, dstTrans); + pipe->transfer_unmap(pipe, srcTrans); + pipe->transfer_unmap(pipe, dstTrans); - screen->tex_transfer_destroy(srcTrans); - screen->tex_transfer_destroy(dstTrans); + pipe->tex_transfer_destroy(pipe, srcTrans); + pipe->tex_transfer_destroy(pipe, dstTrans); } } @@ -1215,17 +1214,17 @@ make_3d_mipmap(struct gen_mipmap_state *ctx, struct pipe_transfer *srcTrans, *dstTrans; ubyte *srcMap, *dstMap; - srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice, + srcTrans = pipe->get_tex_transfer(pipe, pt, face, srcLevel, zslice, PIPE_TRANSFER_READ, 0, 0, u_minify(pt->width0, srcLevel), u_minify(pt->height0, srcLevel)); - dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice, + dstTrans = pipe->get_tex_transfer(pipe, pt, face, dstLevel, zslice, PIPE_TRANSFER_WRITE, 0, 0, u_minify(pt->width0, dstLevel), u_minify(pt->height0, dstLevel)); - srcMap = (ubyte *) screen->transfer_map(screen, srcTrans); - dstMap = (ubyte *) screen->transfer_map(screen, dstTrans); + srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); + dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); reduce_3d(pt->format, srcTrans->width, srcTrans->height, @@ -1233,11 +1232,11 @@ make_3d_mipmap(struct gen_mipmap_state *ctx, dstTrans->width, dstTrans->height, dstTrans->stride, dstMap); - screen->transfer_unmap(screen, srcTrans); - screen->transfer_unmap(screen, dstTrans); + pipe->transfer_unmap(pipe, srcTrans); + pipe->transfer_unmap(pipe, dstTrans); - screen->tex_transfer_destroy(srcTrans); - screen->tex_transfer_destroy(dstTrans); + pipe->tex_transfer_destroy(pipe, srcTrans); + pipe->tex_transfer_destroy(pipe, dstTrans); } #else (void) reduce_3d; @@ -1307,6 +1306,15 @@ util_create_gen_mipmap(struct pipe_context *pipe, ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; ctx->sampler.normalized_coords = 1; + /* vertex elements state */ + memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2); + for (i = 0; i < 2; i++) { + ctx->velem[i].src_offset = i * 4 * sizeof(float); + ctx->velem[i].instance_divisor = 0; + ctx->velem[i].vertex_buffer_index = 0; + ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + /* vertex shader - still needed to specify mapping from fragment * shader input semantics to vertex elements */ @@ -1452,7 +1460,7 @@ void util_gen_mipmap_flush( struct gen_mipmap_state *ctx ) * Generate mipmap images. It's assumed all needed texture memory is * already allocated. * - * \param pt the texture to generate mipmap levels for + * \param psv the sampler view to the texture to generate mipmap levels for * \param face which cube face to generate mipmaps for (0 for non-cube maps) * \param baseLevel the first mipmap level to use as a src * \param lastLevel the last mipmap level to generate @@ -1461,12 +1469,13 @@ void util_gen_mipmap_flush( struct gen_mipmap_state *ctx ) */ void util_gen_mipmap(struct gen_mipmap_state *ctx, - struct pipe_texture *pt, + struct pipe_sampler_view *psv, uint face, uint baseLevel, uint lastLevel, uint filter) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_framebuffer_state fb; + struct pipe_texture *pt = psv->texture; void *fs = (pt->target == PIPE_TEXTURE_CUBE) ? ctx->fsCube : ctx->fs2d; uint dstLevel; uint zslice = 0; @@ -1484,7 +1493,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, filter == PIPE_TEX_FILTER_NEAREST); /* check if we can render in the texture's format */ - if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D, + if (!screen->is_format_supported(screen, psv->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel); return; @@ -1495,18 +1504,20 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_viewport(ctx->cso); cso_save_clip(ctx->cso); + cso_save_vertex_elements(ctx->cso); /* bind our state */ cso_set_blend(ctx->cso, &ctx->blend); cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); + cso_set_vertex_elements(ctx->cso, 2, ctx->velem); cso_set_fragment_shader_handle(ctx->cso, fs); cso_set_vertex_shader_handle(ctx->cso, ctx->vs); @@ -1562,7 +1573,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_single_sampler(ctx->cso, 0, &ctx->sampler); cso_single_sampler_done(ctx->cso); - cso_set_sampler_textures(ctx->cso, 1, &pt); + cso_set_fragment_sampler_views(ctx->cso, 1, &psv); /* quad coords in clip coords */ offset = set_vertex_data(ctx, @@ -1587,10 +1598,11 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_viewport(ctx->cso); cso_restore_clip(ctx->cso); + cso_restore_vertex_elements(ctx->cso); } diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h index 54608f9466d..35ac9daeaa2 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.h +++ b/src/gallium/auxiliary/util/u_gen_mipmap.h @@ -59,7 +59,7 @@ util_gen_mipmap_flush( struct gen_mipmap_state *ctx ); extern void util_gen_mipmap(struct gen_mipmap_state *ctx, - struct pipe_texture *pt, + struct pipe_sampler_view *psv, uint face, uint baseLevel, uint lastLevel, uint filter); diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h index 0cb3432c6e4..e22ab188e11 100644 --- a/src/gallium/auxiliary/util/u_inlines.h +++ b/src/gallium/auxiliary/util/u_inlines.h @@ -120,6 +120,16 @@ pipe_texture_reference(struct pipe_texture **ptr, struct pipe_texture *tex) *ptr = tex; } +static INLINE void +pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view) +{ + struct pipe_sampler_view *old_view = *ptr; + + if (pipe_reference(&(*ptr)->reference, &view->reference)) + old_view->context->sampler_view_destroy(old_view->context, old_view); + *ptr = view; +} + /* * Convenience wrappers for screen buffer functions. @@ -264,24 +274,24 @@ pipe_buffer_read(struct pipe_screen *screen, } static INLINE void * -pipe_transfer_map( struct pipe_transfer *transf ) +pipe_transfer_map( struct pipe_context *context, + struct pipe_transfer *transf ) { - struct pipe_screen *screen = transf->texture->screen; - return screen->transfer_map(screen, transf); + return context->transfer_map(context, transf); } static INLINE void -pipe_transfer_unmap( struct pipe_transfer *transf ) +pipe_transfer_unmap( struct pipe_context *context, + struct pipe_transfer *transf ) { - struct pipe_screen *screen = transf->texture->screen; - screen->transfer_unmap(screen, transf); + context->transfer_unmap(context, transf); } static INLINE void -pipe_transfer_destroy( struct pipe_transfer *transf ) +pipe_transfer_destroy( struct pipe_context *context, + struct pipe_transfer *transfer ) { - struct pipe_screen *screen = transf->texture->screen; - screen->tex_transfer_destroy(transf); + context->tex_transfer_destroy(context, transfer); } static INLINE unsigned diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c index 8479161c744..e73797f1b7e 100644 --- a/src/gallium/auxiliary/util/u_rect.c +++ b/src/gallium/auxiliary/util/u_rect.c @@ -169,7 +169,6 @@ util_surface_copy(struct pipe_context *pipe, unsigned src_x, unsigned src_y, unsigned w, unsigned h) { - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *src_trans, *dst_trans; void *dst_map; const void *src_map; @@ -182,7 +181,7 @@ util_surface_copy(struct pipe_context *pipe, src_format = src->texture->format; dst_format = dst->texture->format; - src_trans = screen->get_tex_transfer(screen, + src_trans = pipe->get_tex_transfer(pipe, src->texture, src->face, src->level, @@ -190,7 +189,7 @@ util_surface_copy(struct pipe_context *pipe, PIPE_TRANSFER_READ, src_x, src_y, w, h); - dst_trans = screen->get_tex_transfer(screen, + dst_trans = pipe->get_tex_transfer(pipe, dst->texture, dst->face, dst->level, @@ -202,8 +201,8 @@ util_surface_copy(struct pipe_context *pipe, assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); - src_map = pipe->screen->transfer_map(screen, src_trans); - dst_map = pipe->screen->transfer_map(screen, dst_trans); + src_map = pipe->transfer_map(pipe, src_trans); + dst_map = pipe->transfer_map(pipe, dst_trans); assert(src_map); assert(dst_map); @@ -221,11 +220,11 @@ util_surface_copy(struct pipe_context *pipe, do_flip ? h - 1 : 0); } - pipe->screen->transfer_unmap(pipe->screen, src_trans); - pipe->screen->transfer_unmap(pipe->screen, dst_trans); + pipe->transfer_unmap(pipe, src_trans); + pipe->transfer_unmap(pipe, dst_trans); - screen->tex_transfer_destroy(src_trans); - screen->tex_transfer_destroy(dst_trans); + pipe->tex_transfer_destroy(pipe, src_trans); + pipe->tex_transfer_destroy(pipe, dst_trans); } @@ -243,14 +242,13 @@ util_surface_fill(struct pipe_context *pipe, unsigned dstx, unsigned dsty, unsigned width, unsigned height, unsigned value) { - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *dst_trans; void *dst_map; assert(dst->texture); if (!dst->texture) return; - dst_trans = screen->get_tex_transfer(screen, + dst_trans = pipe->get_tex_transfer(pipe, dst->texture, dst->face, dst->level, @@ -258,7 +256,7 @@ util_surface_fill(struct pipe_context *pipe, PIPE_TRANSFER_WRITE, dstx, dsty, width, height); - dst_map = pipe->screen->transfer_map(screen, dst_trans); + dst_map = pipe->transfer_map(pipe, dst_trans); assert(dst_map); @@ -302,6 +300,6 @@ util_surface_fill(struct pipe_context *pipe, } } - pipe->screen->transfer_unmap(pipe->screen, dst_trans); - screen->tex_transfer_destroy(dst_trans); + pipe->transfer_unmap(pipe, dst_trans); + pipe->tex_transfer_destroy(pipe, dst_trans); } diff --git a/src/gallium/auxiliary/util/u_sampler.c b/src/gallium/auxiliary/util/u_sampler.c new file mode 100644 index 00000000000..4d8f861ce49 --- /dev/null +++ b/src/gallium/auxiliary/util/u_sampler.c @@ -0,0 +1,100 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "u_format.h" +#include "u_sampler.h" + + +static void +default_template(struct pipe_sampler_view *view, + const struct pipe_texture *texture, + enum pipe_format format, + unsigned expand_green_blue) +{ + /* XXX: Check if format is compatible with texture->format. + */ + + view->format = format; + view->first_level = 0; + view->last_level = texture->last_level; + view->swizzle_r = PIPE_SWIZZLE_RED; + view->swizzle_g = PIPE_SWIZZLE_GREEN; + view->swizzle_b = PIPE_SWIZZLE_BLUE; + view->swizzle_a = PIPE_SWIZZLE_ALPHA; + + /* Override default green and blue component expansion to the requested + * one. + * + * Gallium expands nonexistent components to (0,0,0,1), DX9 expands + * to (1,1,1,1). Since alpha is always expanded to 1, and red is + * always present, we only really care about green and blue + * components. + * + * To make it look less hackish, one would have to add + * UTIL_FORMAT_SWIZZLE_EXPAND to indicate components for expansion + * and then override without exceptions or favoring one component + * over another. + */ + if (format != PIPE_FORMAT_A8_UNORM) { + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (desc) { + if (desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_0) { + view->swizzle_g = expand_green_blue; + } + if (desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_0) { + view->swizzle_b = expand_green_blue; + } + } + } +} + +void +u_sampler_view_default_template(struct pipe_sampler_view *view, + const struct pipe_texture *texture, + enum pipe_format format) +{ + /* Expand to (0, 0, 0, 1) */ + default_template(view, + texture, + format, + PIPE_SWIZZLE_ZERO); +} + +void +u_sampler_view_default_dx9_template(struct pipe_sampler_view *view, + const struct pipe_texture *texture, + enum pipe_format format) +{ + /* Expand to (1, 1, 1, 1) */ + default_template(view, + texture, + format, + PIPE_SWIZZLE_ONE); +} diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/auxiliary/util/u_sampler.h index 6e3920c49b2..bdd061c851c 100644 --- a/src/gallium/drivers/softpipe/sp_winsys.h +++ b/src/gallium/auxiliary/util/u_sampler.h @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 2010 VMware, Inc. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,64 +10,48 @@ * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * **************************************************************************/ -/* This is the interface that softpipe requires any window system - * hosting it to implement. This is the only include file in softpipe - * which is public. - */ +#ifndef U_SAMPLER_H +#define U_SAMPLER_H -#ifndef SP_WINSYS_H -#define SP_WINSYS_H + +#include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "pipe/p_state.h" #ifdef __cplusplus extern "C" { #endif -#include "pipe/p_defines.h" - -struct pipe_screen; -struct pipe_winsys; -struct pipe_context; -struct pipe_texture; -struct pipe_buffer; - - - -/** - * Create a softpipe screen that uses the - * given winsys for allocating buffers. - */ -struct pipe_screen *softpipe_create_screen( struct pipe_winsys * ); -/** - * Create a softpipe screen that uses - * regular malloc to create all its buffers. - */ -struct pipe_screen *softpipe_create_screen_malloc(void); +void +u_sampler_view_default_template(struct pipe_sampler_view *view, + const struct pipe_texture *texture, + enum pipe_format format); -boolean -softpipe_get_texture_buffer( struct pipe_texture *texture, - struct pipe_buffer **buf, - unsigned *stride ); +void +u_sampler_view_default_dx9_template(struct pipe_sampler_view *view, + const struct pipe_texture *texture, + enum pipe_format format); #ifdef __cplusplus -} +} /* extern "C" { */ #endif -#endif /* SP_WINSYS_H */ +#endif /* U_SAMPLER_H */ diff --git a/src/gallium/auxiliary/util/u_simple_screen.c b/src/gallium/auxiliary/util/u_simple_screen.c index 53f3c16dbcc..9203cb6580c 100644 --- a/src/gallium/auxiliary/util/u_simple_screen.c +++ b/src/gallium/auxiliary/util/u_simple_screen.c @@ -59,22 +59,7 @@ pass_user_buffer_create(struct pipe_screen *screen, return buffer; } -static struct pipe_buffer * -pass_surface_buffer_create(struct pipe_screen *screen, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - struct pipe_buffer *buffer = - screen->winsys->surface_buffer_create(screen->winsys, width, height, - format, usage, tex_usage, stride); - buffer->screen = screen; - - return buffer; -} static void * pass_buffer_map(struct pipe_screen *screen, @@ -135,7 +120,6 @@ u_simple_screen_init(struct pipe_screen *screen) { screen->buffer_create = pass_buffer_create; screen->user_buffer_create = pass_user_buffer_create; - screen->surface_buffer_create = pass_surface_buffer_create; screen->buffer_map = pass_buffer_map; screen->buffer_unmap = pass_buffer_unmap; diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index 79481b710bf..82e44192aaf 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -45,11 +45,11 @@ * Move raw block of pixels from transfer object to user memory. */ void -pipe_get_tile_raw(struct pipe_transfer *pt, +pipe_get_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, void *dst, int dst_stride) { - struct pipe_screen *screen = pt->texture->screen; const void *src; if (dst_stride == 0) @@ -58,14 +58,14 @@ pipe_get_tile_raw(struct pipe_transfer *pt, if (pipe_clip_tile(x, y, &w, &h, pt)) return; - src = screen->transfer_map(screen, pt); + src = pipe->transfer_map(pipe, pt); assert(src); if(!src) return; util_copy_rect(dst, pt->texture->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y); - screen->transfer_unmap(screen, pt); + pipe->transfer_unmap(pipe, pt); } @@ -73,11 +73,11 @@ pipe_get_tile_raw(struct pipe_transfer *pt, * Move raw block of pixels from user memory to transfer object. */ void -pipe_put_tile_raw(struct pipe_transfer *pt, +pipe_put_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, const void *src, int src_stride) { - struct pipe_screen *screen = pt->texture->screen; void *dst; enum pipe_format format = pt->texture->format; @@ -87,14 +87,14 @@ pipe_put_tile_raw(struct pipe_transfer *pt, if (pipe_clip_tile(x, y, &w, &h, pt)) return; - dst = screen->transfer_map(screen, pt); + dst = pipe->transfer_map(pipe, pt); assert(dst); if(!dst) return; util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0); - screen->transfer_unmap(screen, pt); + pipe->transfer_unmap(pipe, pt); } @@ -1246,7 +1246,8 @@ pipe_tile_raw_to_rgba(enum pipe_format format, void -pipe_get_tile_rgba(struct pipe_transfer *pt, +pipe_get_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, float *p) { @@ -1265,7 +1266,7 @@ pipe_get_tile_rgba(struct pipe_transfer *pt, if(format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) assert((x & 1) == 0); - pipe_get_tile_raw(pt, x, y, w, h, packed, 0); + pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0); pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); @@ -1274,7 +1275,71 @@ pipe_get_tile_rgba(struct pipe_transfer *pt, void -pipe_put_tile_rgba(struct pipe_transfer *pt, +pipe_get_tile_swizzle(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, + uint y, + uint w, + uint h, + uint swizzle_r, + uint swizzle_g, + uint swizzle_b, + uint swizzle_a, + enum pipe_format format, + float *p) +{ + unsigned dst_stride = w * 4; + void *packed; + uint i; + float rgba01[6]; + + if (pipe_clip_tile(x, y, &w, &h, pt)) { + return; + } + + packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); + if (!packed) { + return; + } + + if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { + assert((x & 1) == 0); + } + + pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0); + + pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); + + FREE(packed); + + if (swizzle_r == PIPE_SWIZZLE_RED && + swizzle_g == PIPE_SWIZZLE_GREEN && + swizzle_b == PIPE_SWIZZLE_BLUE && + swizzle_a == PIPE_SWIZZLE_ALPHA) { + /* no-op, skip */ + return; + } + + rgba01[PIPE_SWIZZLE_ZERO] = 0.0f; + rgba01[PIPE_SWIZZLE_ONE] = 1.0f; + + for (i = 0; i < w * h; i++) { + rgba01[PIPE_SWIZZLE_RED] = p[0]; + rgba01[PIPE_SWIZZLE_GREEN] = p[1]; + rgba01[PIPE_SWIZZLE_BLUE] = p[2]; + rgba01[PIPE_SWIZZLE_ALPHA] = p[3]; + + *p++ = rgba01[swizzle_r]; + *p++ = rgba01[swizzle_g]; + *p++ = rgba01[swizzle_b]; + *p++ = rgba01[swizzle_a]; + } +} + + +void +pipe_put_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, const float *p) { @@ -1363,7 +1428,7 @@ pipe_put_tile_rgba(struct pipe_transfer *pt, 0, 0, w, h); } - pipe_put_tile_raw(pt, x, y, w, h, packed, 0); + pipe_put_tile_raw(pipe, pt, x, y, w, h, packed, 0); FREE(packed); } @@ -1373,11 +1438,11 @@ pipe_put_tile_rgba(struct pipe_transfer *pt, * Get a block of Z values, converted to 32-bit range. */ void -pipe_get_tile_z(struct pipe_transfer *pt, +pipe_get_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, uint *z) { - struct pipe_screen *screen = pt->texture->screen; const uint dstStride = w; ubyte *map; uint *pDest = z; @@ -1387,7 +1452,7 @@ pipe_get_tile_z(struct pipe_transfer *pt, if (pipe_clip_tile(x, y, &w, &h, pt)) return; - map = (ubyte *)screen->transfer_map(screen, pt); + map = (ubyte *)pipe->transfer_map(pipe, pt); if (!map) { assert(0); return; @@ -1453,16 +1518,16 @@ pipe_get_tile_z(struct pipe_transfer *pt, assert(0); } - screen->transfer_unmap(screen, pt); + pipe->transfer_unmap(pipe, pt); } void -pipe_put_tile_z(struct pipe_transfer *pt, +pipe_put_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, const uint *zSrc) { - struct pipe_screen *screen = pt->texture->screen; const uint srcStride = w; const uint *ptrc = zSrc; ubyte *map; @@ -1472,7 +1537,7 @@ pipe_put_tile_z(struct pipe_transfer *pt, if (pipe_clip_tile(x, y, &w, &h, pt)) return; - map = (ubyte *)screen->transfer_map(screen, pt); + map = (ubyte *)pipe->transfer_map(pipe, pt); if (!map) { assert(0); return; @@ -1560,7 +1625,7 @@ pipe_put_tile_z(struct pipe_transfer *pt, assert(0); } - screen->transfer_unmap(screen, pt); + pipe->transfer_unmap(pipe, pt); } diff --git a/src/gallium/auxiliary/util/u_tile.h b/src/gallium/auxiliary/util/u_tile.h index 1453af38b8a..1d8ce7d8cbc 100644 --- a/src/gallium/auxiliary/util/u_tile.h +++ b/src/gallium/auxiliary/util/u_tile.h @@ -56,34 +56,54 @@ extern "C" { #endif void -pipe_get_tile_raw(struct pipe_transfer *pt, +pipe_get_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, void *p, int dst_stride); void -pipe_put_tile_raw(struct pipe_transfer *pt, +pipe_put_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, const void *p, int src_stride); void -pipe_get_tile_rgba(struct pipe_transfer *pt, +pipe_get_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, float *p); void -pipe_put_tile_rgba(struct pipe_transfer *pt, +pipe_get_tile_swizzle(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, + uint y, + uint w, + uint h, + uint swizzle_r, + uint swizzle_g, + uint swizzle_b, + uint swizzle_a, + enum pipe_format format, + float *p); + +void +pipe_put_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, const float *p); void -pipe_get_tile_z(struct pipe_transfer *pt, +pipe_get_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, uint *z); void -pipe_put_tile_z(struct pipe_transfer *pt, +pipe_put_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, uint x, uint y, uint w, uint h, const uint *z); diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index ba23435f698..6d461cb8800 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.c +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -230,6 +230,7 @@ static bool init_pipe_state(struct vl_compositor *c) { struct pipe_sampler_state sampler; + struct pipe_vertex_element vertex_elems[2]; assert(c); @@ -251,15 +252,27 @@ init_pipe_state(struct vl_compositor *c) /*sampler.border_color[i] = ;*/ /*sampler.max_anisotropy = ;*/ c->sampler = c->pipe->create_sampler_state(c->pipe, &sampler); - + + vertex_elems[0].src_offset = 0; + vertex_elems[0].instance_divisor = 0; + vertex_elems[0].vertex_buffer_index = 0; + vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; + vertex_elems[1].src_offset = 0; + vertex_elems[1].instance_divisor = 0; + vertex_elems[1].vertex_buffer_index = 1; + vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; + c->vertex_elems = c->pipe->create_vertex_elements_state(c->pipe, 2, vertex_elems); + + return true; } static void cleanup_pipe_state(struct vl_compositor *c) { assert(c); - + c->pipe->delete_sampler_state(c->pipe, c->sampler); + c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems); } static bool @@ -314,12 +327,6 @@ init_buffers(struct vl_compositor *c) pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[0].buffer); - c->vertex_elems[0].src_offset = 0; - c->vertex_elems[0].instance_divisor = 0; - c->vertex_elems[0].vertex_buffer_index = 0; - c->vertex_elems[0].nr_components = 2; - c->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; - /* * Create our texcoord buffer and texcoord buffer element * Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices @@ -344,12 +351,6 @@ init_buffers(struct vl_compositor *c) pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[1].buffer); - c->vertex_elems[1].src_offset = 0; - c->vertex_elems[1].instance_divisor = 0; - c->vertex_elems[1].vertex_buffer_index = 1; - c->vertex_elems[1].nr_components = 2; - c->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; - /* * Create our vertex shader's constant buffer * Const buffer contains scaling and translation vectors @@ -483,7 +484,7 @@ void vl_compositor_render(struct vl_compositor *compositor, compositor->pipe->bind_vs_state(compositor->pipe, compositor->vertex_shader); compositor->pipe->bind_fs_state(compositor->pipe, compositor->fragment_shader); compositor->pipe->set_vertex_buffers(compositor->pipe, 2, compositor->vertex_bufs); - compositor->pipe->set_vertex_elements(compositor->pipe, 2, compositor->vertex_elems); + compositor->pipe->bind_vertex_elements_state(compositor->pipe, compositor->vertex_elems); compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_VERTEX, 0, compositor->vs_const_buf); compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, compositor->fs_const_buf); diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h index 6a9a3fd7af1..51755554da1 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.h +++ b/src/gallium/auxiliary/vl/vl_compositor.h @@ -43,10 +43,10 @@ struct vl_compositor void *sampler; void *vertex_shader; void *fragment_shader; + void *vertex_elems; struct pipe_viewport_state viewport; struct pipe_scissor_state scissor; struct pipe_vertex_buffer vertex_bufs[2]; - struct pipe_vertex_element vertex_elems[2]; struct pipe_buffer *vs_const_buf, *fs_const_buf; }; diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c index f323de0ea55..beb4722901e 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c @@ -680,14 +680,14 @@ xfer_buffers_map(struct vl_mpeg12_mc_renderer *r) assert(r); for (i = 0; i < 3; ++i) { - r->tex_transfer[i] = r->pipe->screen->get_tex_transfer + r->tex_transfer[i] = r->pipe->get_tex_transfer ( - r->pipe->screen, r->textures.all[i], + r->pipe, r->textures.all[i], 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, r->textures.all[i]->width0, r->textures.all[i]->height0 ); - r->texels[i] = r->pipe->screen->transfer_map(r->pipe->screen, r->tex_transfer[i]); + r->texels[i] = r->pipe->transfer_map(r->pipe, r->tex_transfer[i]); } } @@ -699,8 +699,8 @@ xfer_buffers_unmap(struct vl_mpeg12_mc_renderer *r) assert(r); for (i = 0; i < 3; ++i) { - r->pipe->screen->transfer_unmap(r->pipe->screen, r->tex_transfer[i]); - r->pipe->screen->tex_transfer_destroy(r->tex_transfer[i]); + r->pipe->transfer_unmap(r->pipe, r->tex_transfer[i]); + r->pipe->tex_transfer_destroy(r->pipe, r->tex_transfer[i]); } } @@ -708,6 +708,7 @@ static bool init_pipe_state(struct vl_mpeg12_mc_renderer *r) { struct pipe_sampler_state sampler; + struct pipe_vertex_element vertex_elems[8]; unsigned filters[5]; unsigned i; @@ -771,6 +772,59 @@ init_pipe_state(struct vl_mpeg12_mc_renderer *r) r->samplers.all[i] = r->pipe->create_sampler_state(r->pipe, &sampler); } + /* Position element */ + vertex_elems[0].src_offset = 0; + vertex_elems[0].instance_divisor = 0; + vertex_elems[0].vertex_buffer_index = 0; + vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Luma, texcoord element */ + vertex_elems[1].src_offset = sizeof(struct vertex2f); + vertex_elems[1].instance_divisor = 0; + vertex_elems[1].vertex_buffer_index = 0; + vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Chroma Cr texcoord element */ + vertex_elems[2].src_offset = sizeof(struct vertex2f) * 2; + vertex_elems[2].instance_divisor = 0; + vertex_elems[2].vertex_buffer_index = 0; + vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Chroma Cb texcoord element */ + vertex_elems[3].src_offset = sizeof(struct vertex2f) * 3; + vertex_elems[3].instance_divisor = 0; + vertex_elems[3].vertex_buffer_index = 0; + vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* First ref surface top field texcoord element */ + vertex_elems[4].src_offset = 0; + vertex_elems[4].instance_divisor = 0; + vertex_elems[4].vertex_buffer_index = 1; + vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* First ref surface bottom field texcoord element */ + vertex_elems[5].src_offset = sizeof(struct vertex2f); + vertex_elems[5].instance_divisor = 0; + vertex_elems[5].vertex_buffer_index = 1; + vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Second ref surface top field texcoord element */ + vertex_elems[6].src_offset = 0; + vertex_elems[6].instance_divisor = 0; + vertex_elems[6].vertex_buffer_index = 2; + vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Second ref surface bottom field texcoord element */ + vertex_elems[7].src_offset = sizeof(struct vertex2f); + vertex_elems[7].instance_divisor = 0; + vertex_elems[7].vertex_buffer_index = 2; + vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* need versions with 4,6 and 8 vertex elems */ + r->vertex_elems[0] = r->pipe->create_vertex_elements_state(r->pipe, 4, vertex_elems); + r->vertex_elems[1] = r->pipe->create_vertex_elements_state(r->pipe, 6, vertex_elems); + r->vertex_elems[2] = r->pipe->create_vertex_elements_state(r->pipe, 8, vertex_elems); + return true; } @@ -783,6 +837,8 @@ cleanup_pipe_state(struct vl_mpeg12_mc_renderer *r) for (i = 0; i < 5; ++i) r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]); + for (i = 0; i < 3; i++) + r->pipe->delete_vertex_elements_state(r->pipe, r->vertex_elems[i]); } static bool @@ -888,62 +944,6 @@ init_buffers(struct vl_mpeg12_mc_renderer *r) ); } - /* Position element */ - r->vertex_elems[0].src_offset = 0; - r->vertex_elems[0].instance_divisor = 0; - r->vertex_elems[0].vertex_buffer_index = 0; - r->vertex_elems[0].nr_components = 2; - r->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; - - /* Luma, texcoord element */ - r->vertex_elems[1].src_offset = sizeof(struct vertex2f); - r->vertex_elems[1].instance_divisor = 0; - r->vertex_elems[1].vertex_buffer_index = 0; - r->vertex_elems[1].nr_components = 2; - r->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; - - /* Chroma Cr texcoord element */ - r->vertex_elems[2].src_offset = sizeof(struct vertex2f) * 2; - r->vertex_elems[2].instance_divisor = 0; - r->vertex_elems[2].vertex_buffer_index = 0; - r->vertex_elems[2].nr_components = 2; - r->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT; - - /* Chroma Cb texcoord element */ - r->vertex_elems[3].src_offset = sizeof(struct vertex2f) * 3; - r->vertex_elems[3].instance_divisor = 0; - r->vertex_elems[3].vertex_buffer_index = 0; - r->vertex_elems[3].nr_components = 2; - r->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT; - - /* First ref surface top field texcoord element */ - r->vertex_elems[4].src_offset = 0; - r->vertex_elems[4].instance_divisor = 0; - r->vertex_elems[4].vertex_buffer_index = 1; - r->vertex_elems[4].nr_components = 2; - r->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT; - - /* First ref surface bottom field texcoord element */ - r->vertex_elems[5].src_offset = sizeof(struct vertex2f); - r->vertex_elems[5].instance_divisor = 0; - r->vertex_elems[5].vertex_buffer_index = 1; - r->vertex_elems[5].nr_components = 2; - r->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT; - - /* Second ref surface top field texcoord element */ - r->vertex_elems[6].src_offset = 0; - r->vertex_elems[6].instance_divisor = 0; - r->vertex_elems[6].vertex_buffer_index = 2; - r->vertex_elems[6].nr_components = 2; - r->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT; - - /* Second ref surface bottom field texcoord element */ - r->vertex_elems[7].src_offset = sizeof(struct vertex2f); - r->vertex_elems[7].instance_divisor = 0; - r->vertex_elems[7].vertex_buffer_index = 2; - r->vertex_elems[7].nr_components = 2; - r->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT; - r->vs_const_buf = pipe_buffer_create ( r->pipe->screen, @@ -1307,7 +1307,7 @@ flush(struct vl_mpeg12_mc_renderer *r) if (num_macroblocks[MACROBLOCK_TYPE_INTRA] > 0) { r->pipe->set_vertex_buffers(r->pipe, 1, r->vertex_bufs.all); - r->pipe->set_vertex_elements(r->pipe, 4, r->vertex_elems); + r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems[0]); r->pipe->set_fragment_sampler_textures(r->pipe, 3, r->textures.all); r->pipe->bind_fragment_sampler_states(r->pipe, 3, r->samplers.all); r->pipe->bind_vs_state(r->pipe, r->i_vs); @@ -1320,7 +1320,7 @@ flush(struct vl_mpeg12_mc_renderer *r) if (num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] > 0) { r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all); - r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems); + r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems[1]); r->textures.individual.ref[0] = r->past; r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all); r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all); @@ -1334,7 +1334,7 @@ flush(struct vl_mpeg12_mc_renderer *r) if (false /*num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] > 0 */ ) { r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all); - r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems); + r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems[1]); r->textures.individual.ref[0] = r->past; r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all); r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all); @@ -1348,7 +1348,7 @@ flush(struct vl_mpeg12_mc_renderer *r) if (num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] > 0) { r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all); - r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems); + r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems[1]); r->textures.individual.ref[0] = r->future; r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all); r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all); @@ -1362,7 +1362,7 @@ flush(struct vl_mpeg12_mc_renderer *r) if (false /*num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] > 0 */ ) { r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all); - r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems); + r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems[1]); r->textures.individual.ref[0] = r->future; r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all); r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all); @@ -1376,7 +1376,7 @@ flush(struct vl_mpeg12_mc_renderer *r) if (num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] > 0) { r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all); - r->pipe->set_vertex_elements(r->pipe, 8, r->vertex_elems); + r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems[2]); r->textures.individual.ref[0] = r->past; r->textures.individual.ref[1] = r->future; r->pipe->set_fragment_sampler_textures(r->pipe, 5, r->textures.all); @@ -1391,7 +1391,7 @@ flush(struct vl_mpeg12_mc_renderer *r) if (false /*num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] > 0 */ ) { r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all); - r->pipe->set_vertex_elements(r->pipe, 8, r->vertex_elems); + r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems[2]); r->textures.individual.ref[0] = r->past; r->textures.individual.ref[1] = r->future; r->pipe->set_fragment_sampler_textures(r->pipe, 5, r->textures.all); diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h index f00b8c7b8b1..a11a3e7307b 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h @@ -66,8 +66,8 @@ struct vl_mpeg12_mc_renderer struct pipe_buffer *vs_const_buf; struct pipe_buffer *fs_const_buf; struct pipe_framebuffer_state fb_state; - struct pipe_vertex_element vertex_elems[8]; - + void *vertex_elems[3]; + union { void *all[5]; diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst index 9080addba44..1f022570dbb 100644 --- a/src/gallium/docs/source/context.rst +++ b/src/gallium/docs/source/context.rst @@ -24,6 +24,7 @@ CSO objects handled by the context object: * :ref:`Depth, Stencil, & Alpha`: ``*_depth_stencil_alpha_state`` * :ref:`Shader`: These have two sets of methods. ``*_fs_state`` is for fragment shaders, and ``*_vs_state`` is for vertex shaders. +* :ref:`Vertex Elements`: ``*_vertex_elements_state`` Resource Binding State @@ -39,8 +40,7 @@ buffers, surfaces) are bound to the driver. are mostly restricted to the first one right now). * ``set_framebuffer_state`` -* ``set_fragment_sampler_textures`` -* ``set_vertex_sampler_textures`` + * ``set_vertex_buffers`` @@ -60,7 +60,41 @@ objects. They all follow simple, one-method binding calls, e.g. not have the scissor test enabled, then the scissor bounds never need to be set since they will not be used. * ``set_viewport_state`` -* ``set_vertex_elements`` + + +Sampler Views +^^^^^^^^^^^^^ + +These are the means to bind textures to shader stages. To create one, specify +its format, swizzle and LOD range in sampler view template. + +If texture format is different than template format, it is said the texture +is being cast to another format. Casting can be done only between compatible +formats, that is formats that have matching component order and sizes. + +Swizzle fields specify they way in which fetched texel components are placed +in the result register. For example, swizzle_r specifies what is going to be +placed in destination register x (AKA r). + +first_level and last_level fields of sampler view template specify the LOD +range the texture is going to be constrained to. + +* ``set_fragment_sampler_views`` binds an array of sampler views to + fragment shader stage. Every binding point acquires a reference + to a respective sampler view and releases a reference to the previous + sampler view. + +* ``set_vertex_sampler_views`` binds an array of sampler views to vertex + shader stage. Every binding point acquires a reference to a respective + sampler view and releases a reference to the previous sampler view. + +* ``create_sampler_view`` creates a new sampler view. texture is associated + with the sampler view which results in sampler view holding a reference + to the texture. Format specified in template must be compatible + with texture format. + +* ``sampler_view_destroy`` destroys a sampler view and releases its reference + to associated texture. Clearing diff --git a/src/gallium/docs/source/cso/velems.rst b/src/gallium/docs/source/cso/velems.rst new file mode 100644 index 00000000000..8e758fae103 --- /dev/null +++ b/src/gallium/docs/source/cso/velems.rst @@ -0,0 +1,24 @@ +.. _vertex,elements + +Vertex Elements +=============== + +This state controls format etc. of the input attributes contained +in the pipe_vertex_buffer(s). There's one pipe_vertex_element array member +for each input attribute. + +Members +------- + +src_offset + The byte offset of the attribute in the buffer given by + vertex_buffer_index for the first vertex. +instance_divisor + The instance data rate divisor, used for instancing. + 0 means this is per-vertex data, n means per-instance data used for + n consecutive instances (n > 0). +vertex_buffer_index + The vertex buffer this attribute lives in. Several attributes may + live in the same vertex buffer. +src_format + The format of the attribute data. One of the PIPE_FORMAT tokens. diff --git a/src/gallium/drivers/cell/ppu/Makefile b/src/gallium/drivers/cell/ppu/Makefile index c92f8e5cba2..8769b826b5f 100644 --- a/src/gallium/drivers/cell/ppu/Makefile +++ b/src/gallium/drivers/cell/ppu/Makefile @@ -21,6 +21,7 @@ SPU_CODE_MODULE = ../spu/g3d_spu.a SOURCES = \ cell_batch.c \ + cell_buffer.c \ cell_clear.c \ cell_context.c \ cell_draw_arrays.c \ diff --git a/src/gallium/drivers/cell/ppu/cell_buffer.c b/src/gallium/drivers/cell/ppu/cell_buffer.c new file mode 100644 index 00000000000..f56a28d62e2 --- /dev/null +++ b/src/gallium/drivers/cell/ppu/cell_buffer.c @@ -0,0 +1,118 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "cell_screen.h" +#include "cell_buffer.h" + + +static void * +cell_buffer_map(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned flags) +{ + struct cell_buffer *cell_buf = cell_buffer(buf); + return cell_buf->data; +} + + +static void +cell_buffer_unmap(struct pipe_screen *screen, + struct pipe_buffer *buf) +{ +} + + +static void +cell_buffer_destroy(struct pipe_buffer *buf) +{ + struct cell_buffer *sbuf = cell_buffer(buf); + + if (!sbuf->userBuffer) + align_free(sbuf->data); + + FREE(sbuf); +} + + +static struct pipe_buffer * +cell_buffer_create(struct pipe_screen *screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct cell_buffer *buffer = CALLOC_STRUCT(cell_buffer); + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.alignment = MAX2(alignment, 16); + buffer->base.usage = usage; + buffer->base.size = size; + + buffer->data = align_malloc(size, alignment); + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +cell_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes) +{ + struct cell_buffer *buffer; + + buffer = CALLOC_STRUCT(cell_buffer); + if(!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + +void +cell_init_screen_buffer_funcs(struct pipe_screen *screen) +{ + screen->buffer_create = cell_buffer_create; + screen->user_buffer_create = cell_user_buffer_create; + screen->buffer_map = cell_buffer_map; + screen->buffer_unmap = cell_buffer_unmap; + screen->buffer_destroy = cell_buffer_destroy; +} diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.h b/src/gallium/drivers/cell/ppu/cell_buffer.h index f96c5a14b0a..ef0a8a70e59 100644 --- a/src/gallium/state_trackers/egl/x11/sw_winsys.h +++ b/src/gallium/drivers/cell/ppu/cell_buffer.h @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 2009 VMware, Inc. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,31 +10,46 @@ * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * **************************************************************************/ +#ifndef SP_BUFFER_H +#define SP_BUFFER_H -#ifndef SW_WINSYS_H -#define SW_WINSYS_H +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" -struct pipe_winsys; +struct cell_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; +}; -extern struct pipe_winsys * -create_sw_winsys(void); +/** Cast wrapper */ +static INLINE struct cell_buffer * +cell_buffer( struct pipe_buffer *buf ) +{ + return (struct cell_buffer *)buf; +} -#endif /* SW_WINSYS_H */ +void +cell_init_screen_buffer_funcs(struct pipe_screen *screen); + + +#endif /* SP_BUFFER_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index 5bff9869fd0..f6cb1fc9be7 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -36,7 +36,6 @@ #include "pipe/p_defines.h" #include "pipe/p_format.h" #include "util/u_memory.h" -#include "util/u_simple_screen.h" #include "pipe/p_screen.h" #include "draw/draw_context.h" @@ -137,7 +136,7 @@ cell_create_context(struct pipe_screen *screen, memset(cell, 0, sizeof(*cell)); cell->winsys = NULL; /* XXX: fixme - get this from screen? */ - cell->pipe.winsys = screen->winsys; + cell->pipe.winsys = NULL; cell->pipe.screen = screen; cell->pipe.priv = priv; cell->pipe.destroy = cell_destroy_context; @@ -159,6 +158,7 @@ cell_create_context(struct pipe_screen *screen, cell_init_shader_functions(cell); cell_init_surface_functions(cell); cell_init_vertex_functions(cell); + cell_init_texture_transfer_funcs(cell); cell->draw = cell_draw_create(cell); diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index a77cc5b9067..f7e2284445d 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -34,7 +34,7 @@ #include "pipe/p_defines.h" #include "draw/draw_vertex.h" #include "draw/draw_vbuf.h" -#include "cell_winsys.h" +/*#include "cell_winsys.h"*/ #include "cell/common.h" #include "rtasm/rtasm_ppc_spe.h" #include "tgsi/tgsi_scan.h" @@ -93,6 +93,11 @@ struct cell_buffer_list struct cell_buffer_node *head; }; +struct cell_velems_state +{ + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; /** * Per-context state, subclass of pipe_context. @@ -110,6 +115,7 @@ struct cell_context const struct pipe_rasterizer_state *rasterizer; const struct cell_vertex_shader_state *vs; const struct cell_fragment_shader_state *fs; + const struct cell_velems_state *velems; struct spe_function logic_op; @@ -121,12 +127,11 @@ struct cell_context struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; struct cell_texture *texture[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; uint num_textures; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; uint num_vertex_buffers; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; - uint num_vertex_elements; ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS]; ubyte *zsbuf_map; diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index bffd0fac6fe..15d4e8338f4 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -33,48 +33,18 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" #include "cell_context.h" #include "cell_draw_arrays.h" #include "cell_state.h" #include "cell_flush.h" +#include "cell_buffer.h" #include "draw/draw_context.h" -static void -cell_map_constant_buffers(struct cell_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - for (i = 0; i < 2; i++) { - if (sp->constants[i] && sp->constants[i]->size) { - sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i], - PIPE_BUFFER_USAGE_CPU_READ); - cell_flush_buffer_range(sp, sp->mapped_constants[i], - sp->constants[i]->size); - } - } - - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, 0, - sp->mapped_constants[PIPE_SHADER_VERTEX], - sp->constants[PIPE_SHADER_VERTEX]->size); -} - -static void -cell_unmap_constant_buffers(struct cell_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - for (i = 0; i < 2; i++) { - if (sp->constants[i] && sp->constants[i]->size) - ws->buffer_unmap(ws, sp->constants[i]); - sp->mapped_constants[i] = NULL; - } -} @@ -93,33 +63,27 @@ cell_draw_range_elements(struct pipe_context *pipe, unsigned max_index, unsigned mode, unsigned start, unsigned count) { - struct cell_context *sp = cell_context(pipe); - struct draw_context *draw = sp->draw; + struct cell_context *cell = cell_context(pipe); + struct draw_context *draw = cell->draw; unsigned i; - if (sp->dirty) - cell_update_derived( sp ); + if (cell->dirty) + cell_update_derived( cell ); #if 0 - cell_map_surfaces(sp); + cell_map_surfaces(cell); #endif - cell_map_constant_buffers(sp); /* * Map vertex buffers */ - for (i = 0; i < sp->num_vertex_buffers; i++) { - void *buf = pipe_buffer_map(pipe->screen, - sp->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); - cell_flush_buffer_range(sp, buf, sp->vertex_buffer[i].buffer->size); + for (i = 0; i < cell->num_vertex_buffers; i++) { + void *buf = cell_buffer(cell->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { - void *mapped_indexes = pipe_buffer_map(pipe->screen, - indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *mapped_indexes = cell_buffer(indexBuffer)->data; draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { @@ -134,17 +98,19 @@ cell_draw_range_elements(struct pipe_context *pipe, /* * unmap vertex/index buffers - will cause draw module to flush */ - for (i = 0; i < sp->num_vertex_buffers; i++) { + for (i = 0; i < cell->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); - pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer); } if (indexBuffer) { draw_set_mapped_element_buffer(draw, 0, NULL); - pipe_buffer_unmap(pipe->screen, indexBuffer); } - /* Note: leave drawing surfaces mapped */ - cell_unmap_constant_buffers(sp); + /* + * TODO: Flush only when a user vertex/index buffer is present + * (or even better, modify draw module to do this + * internally when this condition is seen?) + */ + draw_flush(draw); } diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c index e10071529a8..035ef41b898 100644 --- a/src/gallium/drivers/cell/ppu/cell_fence.c +++ b/src/gallium/drivers/cell/ppu/cell_fence.c @@ -92,7 +92,6 @@ cell_add_buffer_to_list(struct cell_context *cell, struct cell_buffer_list *list, struct pipe_buffer *buffer) { - struct pipe_screen *ps = cell->pipe.screen; struct cell_buffer_node *node = CALLOC_STRUCT(cell_buffer_node); /* create new list node which references the buffer, insert at head */ if (node) { @@ -157,8 +156,13 @@ cell_add_fenced_textures(struct cell_context *cell) printf("Adding texture %p buffer %p to list\n", ct, ct->tiled_buffer[level]); #endif - if (ct->buffer) +#if 00 + /* XXX this needs to be fixed/restored! + * Maybe keep pointers to textures, not buffers. + */ + if (ct->base.buffer) cell_add_buffer_to_list(cell, list, ct->buffer); +#endif } } } diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index 3d8b4409c75..059ce8597bc 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -257,8 +257,9 @@ cell_delete_sampler_state(struct pipe_context *pipe, static void -cell_set_sampler_textures(struct pipe_context *pipe, - unsigned num, struct pipe_texture **texture) +cell_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct cell_context *cell = cell_context(pipe); uint i, changed = 0x0; @@ -266,10 +267,14 @@ cell_set_sampler_textures(struct pipe_context *pipe, assert(num <= CELL_MAX_SAMPLERS); for (i = 0; i < CELL_MAX_SAMPLERS; i++) { - struct cell_texture *new_tex = cell_texture(i < num ? texture[i] : NULL); - struct cell_texture *old_tex = cell->texture[i]; - if (old_tex != new_tex) { + struct pipe_sampler_view *new_view = i < num ? views[i] : NULL; + struct pipe_sampler_view *old_view = cell->fragment_sampler_views[i]; + if (old_view != new_view) { + struct pipe_texture *new_tex = new_view ? new_view->texture : NULL; + + pipe_sampler_view_reference(&cell->fragment_sampler_views[i], + views[i]); pipe_texture_reference((struct pipe_texture **) &cell->texture[i], (struct pipe_texture *) new_tex); @@ -286,23 +291,57 @@ cell_set_sampler_textures(struct pipe_context *pipe, } +static struct pipe_sampler_view * +cell_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +cell_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + + /** * Map color and z/stencil framebuffer surfaces. */ static void cell_map_surfaces(struct cell_context *cell) { +#if 0 struct pipe_screen *screen = cell->pipe.screen; +#endif uint i; for (i = 0; i < 1; i++) { struct pipe_surface *ps = cell->framebuffer.cbufs[i]; if (ps) { struct cell_texture *ct = cell_texture(ps->texture); +#if 0 cell->cbuf_map[i] = screen->buffer_map(screen, ct->buffer, (PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE)); +#else + cell->cbuf_map[i] = ct->data; +#endif } } @@ -310,10 +349,14 @@ cell_map_surfaces(struct cell_context *cell) struct pipe_surface *ps = cell->framebuffer.zsbuf; if (ps) { struct cell_texture *ct = cell_texture(ps->texture); +#if 0 cell->zsbuf_map = screen->buffer_map(screen, ct->buffer, (PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE)); +#else + cell->zsbuf_map = ct->data; +#endif } } } @@ -325,17 +368,17 @@ cell_map_surfaces(struct cell_context *cell) static void cell_unmap_surfaces(struct cell_context *cell) { - struct pipe_screen *screen = cell->pipe.screen; + /*struct pipe_screen *screen = cell->pipe.screen;*/ uint i; for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { struct pipe_surface *ps = cell->framebuffer.cbufs[i]; if (ps && cell->cbuf_map[i]) { - struct cell_texture *ct = cell_texture(ps->texture); + /*struct cell_texture *ct = cell_texture(ps->texture);*/ assert(ps->texture); - assert(ct->buffer); + /*assert(ct->buffer);*/ - screen->buffer_unmap(screen, ct->buffer); + /*screen->buffer_unmap(screen, ct->buffer);*/ cell->cbuf_map[i] = NULL; } } @@ -343,8 +386,8 @@ cell_unmap_surfaces(struct cell_context *cell) { struct pipe_surface *ps = cell->framebuffer.zsbuf; if (ps && cell->zsbuf_map) { - struct cell_texture *ct = cell_texture(ps->texture); - screen->buffer_unmap(screen, ct->buffer); + /*struct cell_texture *ct = cell_texture(ps->texture);*/ + /*screen->buffer_unmap(screen, ct->buffer);*/ cell->zsbuf_map = NULL; } } @@ -399,7 +442,9 @@ cell_init_state_functions(struct cell_context *cell) cell->pipe.bind_fragment_sampler_states = cell_bind_sampler_states; cell->pipe.delete_sampler_state = cell_delete_sampler_state; - cell->pipe.set_fragment_sampler_textures = cell_set_sampler_textures; + cell->pipe.set_fragment_sampler_views = cell_set_fragment_sampler_views; + cell->pipe.create_sampler_view = cell_create_sampler_view; + cell->pipe.sampler_view_destroy = cell_sampler_view_destroy; cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state; cell->pipe.bind_depth_stencil_alpha_state = cell_bind_depth_stencil_alpha_state; diff --git a/src/gallium/drivers/cell/ppu/cell_public.h b/src/gallium/drivers/cell/ppu/cell_public.h new file mode 100644 index 00000000000..7e2e093565d --- /dev/null +++ b/src/gallium/drivers/cell/ppu/cell_public.h @@ -0,0 +1,10 @@ +#ifndef CELL_PUBLIC_H +#define CELL_PUBLIC_H + +struct pipe_screen; +struct sw_winsys; + +struct pipe_screen * +cell_create_screen(struct sw_winsys *winsys); + +#endif diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c index a43f8638dcd..f5528a7ec6b 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.c +++ b/src/gallium/drivers/cell/ppu/cell_screen.c @@ -28,7 +28,6 @@ #include "util/u_memory.h" #include "util/u_simple_screen.h" -#include "util/u_simple_screen.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -36,7 +35,10 @@ #include "cell_context.h" #include "cell_screen.h" #include "cell_texture.h" -#include "cell_winsys.h" +#include "cell_buffer.h" +#include "cell_public.h" + +#include "state_tracker/sw_winsys.h" static const char * @@ -134,19 +136,30 @@ cell_is_format_supported( struct pipe_screen *screen, unsigned tex_usage, unsigned geom_flags ) { - /* cell supports most formats, XXX for now anyway */ + struct sw_winsys *winsys = cell_screen(screen)->winsys; + if (format == PIPE_FORMAT_DXT5_RGBA || format == PIPE_FORMAT_A8B8G8R8_SRGB) return FALSE; - else - return TRUE; + + if (tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if (!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) + return FALSE; + } + + /* This is often a lie. Pull in logic from llvmpipe to fix. + */ + return TRUE; } static void cell_destroy_screen( struct pipe_screen *screen ) { - struct pipe_winsys *winsys = screen->winsys; + struct cell_screen *sp_screen = cell_screen(screen); + struct sw_winsys *winsys = sp_screen->winsys; if(winsys->destroy) winsys->destroy(winsys); @@ -155,32 +168,34 @@ cell_destroy_screen( struct pipe_screen *screen ) } + /** * Create a new pipe_screen object * Note: we're not presently subclassing pipe_screen (no cell_screen) but * that would be the place to put SPU thread/context info... */ struct pipe_screen * -cell_create_screen(struct pipe_winsys *winsys) +cell_create_screen(struct sw_winsys *winsys) { - struct pipe_screen *screen = CALLOC_STRUCT(pipe_screen); + struct cell_screen *screen = CALLOC_STRUCT(cell_screen); if (!screen) return NULL; screen->winsys = winsys; + screen->base.winsys = NULL; - screen->destroy = cell_destroy_screen; + screen->base.destroy = cell_destroy_screen; - screen->get_name = cell_get_name; - screen->get_vendor = cell_get_vendor; - screen->get_param = cell_get_param; - screen->get_paramf = cell_get_paramf; - screen->is_format_supported = cell_is_format_supported; - screen->context_create = cell_create_context; + screen->base.get_name = cell_get_name; + screen->base.get_vendor = cell_get_vendor; + screen->base.get_param = cell_get_param; + screen->base.get_paramf = cell_get_paramf; + screen->base.is_format_supported = cell_is_format_supported; + screen->base.context_create = cell_create_context; - cell_init_screen_texture_funcs(screen); - u_simple_screen_init(screen); + cell_init_screen_texture_funcs(&screen->base); + cell_init_screen_buffer_funcs(&screen->base); - return screen; + return &screen->base; } diff --git a/src/gallium/drivers/cell/ppu/cell_screen.h b/src/gallium/drivers/cell/ppu/cell_screen.h index c7e15889d66..baff9d3b7d4 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.h +++ b/src/gallium/drivers/cell/ppu/cell_screen.h @@ -30,12 +30,26 @@ #define CELL_SCREEN_H -struct pipe_screen; -struct pipe_winsys; +#include "pipe/p_screen.h" +struct sw_winsys; -extern struct pipe_screen * -cell_create_screen(struct pipe_winsys *winsys); +struct cell_screen { + struct pipe_screen base; + + struct sw_winsys *winsys; + + /* Increments whenever textures are modified. Contexts can track + * this. + */ + unsigned timestamp; +}; + +static INLINE struct cell_screen * +cell_screen( struct pipe_screen *pipe ) +{ + return (struct cell_screen *)pipe; +} #endif /* CELL_SCREEN_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index a59c7828ac3..424e2628a95 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -245,16 +245,13 @@ cell_emit_state(struct cell_context *cell) uint i, j; float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float))); uint32_t *ibuf = (uint32_t *) buf; - const float *constants = pipe_buffer_map(cell->pipe.screen, - cell->constants[shader], - PIPE_BUFFER_USAGE_CPU_READ); + const float *constants = cell->mapped_constants[shader]; ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS; ibuf[4] = num_const; j = 8; for (i = 0; i < num_const; i++) { buf[j++] = constants[i]; } - pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader]); } if (cell->dirty & (CELL_NEW_FRAMEBUFFER | diff --git a/src/gallium/drivers/cell/ppu/cell_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c index 9b2f86fdfba..9e29ddc2d45 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c @@ -28,13 +28,13 @@ #include "pipe/p_defines.h" #include "util/u_memory.h" #include "util/u_inlines.h" -#include "util/u_simple_screen.h" #include "draw/draw_context.h" #include "tgsi/tgsi_parse.h" #include "cell_context.h" #include "cell_state.h" #include "cell_gen_fp.h" +#include "cell_buffer.h" /** cast wrapper */ @@ -183,17 +183,29 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs) static void cell_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_buffer *constants) { struct cell_context *cell = cell_context(pipe); + unsigned size = constants ? constants->size : 0; + const void *data = constants ? cell_buffer(constants)->data : NULL; assert(shader < PIPE_SHADER_TYPES); assert(index == 0); + if (cell->constants[shader] == constants) + return; + draw_flush(cell->draw); /* note: reference counting */ - pipe_buffer_reference(&cell->constants[shader], buf); + pipe_buffer_reference(&cell->constants[shader], constants); + + if(shader == PIPE_SHADER_VERTEX) { + draw_set_mapped_constant_buffer(cell->draw, PIPE_SHADER_VERTEX, 0, + data, size); + } + + cell->mapped_constants[shader] = data; if (shader == PIPE_SHADER_VERTEX) cell->dirty |= CELL_NEW_VS_CONSTANTS; diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c index fbe55c84721..9510ea9ac2b 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c +++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c @@ -32,24 +32,44 @@ #include "cell_context.h" #include "cell_state.h" +#include "util/u_memory.h" #include "draw/draw_context.h" -static void -cell_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements) +void * +cell_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) { - struct cell_context *cell = cell_context(pipe); - + struct cell_velems_state *velems; assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct cell_velems_state *) MALLOC(sizeof(struct cell_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + +void +cell_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + struct cell_context *cell = cell_context(pipe); + struct cell_velems_state *cell_velems = (struct cell_velems_state *) velems; - memcpy(cell->vertex_element, elements, count * sizeof(elements[0])); - cell->num_vertex_elements = count; + cell->velems = cell_velems; cell->dirty |= CELL_NEW_VERTEX; - draw_set_vertex_elements(cell->draw, count, elements); + if (cell_velems) + draw_set_vertex_elements(cell->draw, cell_velems->count, cell_velems->velem); +} + +void +cell_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); } @@ -75,5 +95,7 @@ void cell_init_vertex_functions(struct cell_context *cell) { cell->pipe.set_vertex_buffers = cell_set_vertex_buffers; - cell->pipe.set_vertex_elements = cell_set_vertex_elements; + cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state; + cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state; + cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state; } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index fad290dfa0e..5b169afaf88 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -34,20 +34,23 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" -#include "util/u_simple_screen.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "cell_context.h" +#include "cell_screen.h" #include "cell_state.h" #include "cell_texture.h" +#include "state_tracker/sw_winsys.h" -static void -cell_texture_layout(struct cell_texture *ct) + +static boolean +cell_texture_layout(struct pipe_screen *screen, + struct cell_texture *ct) { struct pipe_texture *pt = &ct->base; unsigned level; @@ -83,9 +86,35 @@ cell_texture_layout(struct cell_texture *ct) height = u_minify(height, 1); depth = u_minify(depth, 1); } + + ct->data = align_malloc(ct->buffer_size, 16); + + return ct->data != NULL; } +/** + * Texture layout for simple color buffers. + */ +static boolean +cell_displaytarget_layout(struct pipe_screen *screen, + struct cell_texture * ct) +{ + struct sw_winsys *winsys = cell_screen(screen)->winsys; + + /* Round up the surface size to a multiple of the tile size? + */ + ct->dt = winsys->displaytarget_create(winsys, + ct->base->tex_usage, + ct->base.format, + ct->base.width0, + ct->base.height0, + 16, + &ct->dt_stride ); + + return ct->dt != NULL; +} + static struct pipe_texture * cell_texture_create(struct pipe_screen *screen, const struct pipe_texture *templat) @@ -98,31 +127,46 @@ cell_texture_create(struct pipe_screen *screen, pipe_reference_init(&ct->base.reference, 1); ct->base.screen = screen; - cell_texture_layout(ct); + /* Create both a displaytarget (linear) and regular texture + * (twiddled). Convert twiddled->linear at flush_frontbuffer time. + */ + if (ct->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if (!cell_displaytarget_layout(screen, ct)) + goto fail; + } - ct->buffer = screen->buffer_create(screen, 32, PIPE_BUFFER_USAGE_PIXEL, - ct->buffer_size); + if (!cell_texture_layout(screen, ct)) + goto fail; - if (!ct->buffer) { - FREE(ct); - return NULL; + return &ct->base; + +fail: + if (ct->dt) { + struct sw_winsys *winsys = cell_screen(screen)->winsys; + winsys->displaytarget_destroy(winsys, ct->dt); } - return &ct->base; + FREE(ct); + + return NULL; } static void cell_texture_destroy(struct pipe_texture *pt) { + struct cell_screen *screen = cell_screen(pt->screen); + struct sw_winsys *winsys = screen->winsys; struct cell_texture *ct = cell_texture(pt); - if (ct->mapped) { - pipe_buffer_unmap(ct->buffer->screen, ct->buffer); - ct->mapped = NULL; + if (ct->dt) { + /* display target */ + winsys->displaytarget_destroy(winsys, ct->dt); } - pipe_buffer_reference(&ct->buffer, NULL); + align_free(ct->data); FREE(ct); } @@ -312,7 +356,7 @@ cell_tex_surface_destroy(struct pipe_surface *surf) * back out for glGetTexImage). */ static struct pipe_transfer * -cell_get_tex_transfer(struct pipe_screen *screen, +cell_get_tex_transfer(struct pipe_context *ctx, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, @@ -359,7 +403,7 @@ cell_get_tex_transfer(struct pipe_screen *screen, static void -cell_tex_transfer_destroy(struct pipe_transfer *t) +cell_tex_transfer_destroy(struct pipe_context *ctx, struct pipe_transfer *t) { struct cell_transfer *transfer = cell_transfer(t); /* Effectively do the texture_update work here - if texture images @@ -376,7 +420,7 @@ cell_tex_transfer_destroy(struct pipe_transfer *t) * Return pointer to texture image data in linear layout. */ static void * -cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer) +cell_transfer_map(struct pipe_context *ctx, struct pipe_transfer *transfer) { struct cell_transfer *ctrans = cell_transfer(transfer); struct pipe_texture *pt = transfer->texture; @@ -389,10 +433,8 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer) assert(transfer->texture); - if (!ct->mapped) { - /* map now */ - ct->mapped = pipe_buffer_map(screen, ct->buffer, - pipe_transfer_buffer_flags(transfer)); + if (ct->mapped == NULL) { + ct->mapped = ct->data; } /* @@ -430,7 +472,7 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer) * to tiled data. */ static void -cell_transfer_unmap(struct pipe_screen *screen, +cell_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer *transfer) { struct cell_transfer *ctrans = cell_transfer(transfer); @@ -442,9 +484,8 @@ cell_transfer_unmap(struct pipe_screen *screen, const uint stride = ct->stride[level]; if (!ct->mapped) { - /* map now */ - ct->mapped = pipe_buffer_map(screen, ct->buffer, - PIPE_BUFFER_USAGE_CPU_READ); + assert(0); + return; } if (transfer->usage & PIPE_TRANSFER_WRITE) { @@ -467,6 +508,50 @@ cell_transfer_unmap(struct pipe_screen *screen, } + +/* This used to be overriden by the co-state tracker, but really needs + * to be active with sw_winsys. + * + * Contrasting with llvmpipe and softpipe, this is the only place + * where we use the ct->dt display target in any real sense. + * + * Basically just untwiddle our local data into the linear + * displaytarget. + */ +static void +cell_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *surface, + void *context_private) +{ + struct cell_screen *screen = cell_screen(_screen); + struct sw_winsys *winsys = screen->winsys; + struct cell_texture *ct = cell_texture(surface->texture); + + if (!ct->dt) + return; + + /* Need to untwiddle from our internal representation here: + */ + { + unsigned *map = winsys->displaytarget_map(winsys, ct->dt, + (PIPE_BUFFER_USAGE_CPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE)); + unsigned *src = (unsigned *)(ct->data + ct->level_offset[surface->level]); + + untwiddle_image_uint(surface->width, + surface->height, + TILE_SIZE, + map, + ct->dt_stride, + src); + + winsys->displaytarget_unmap(winsys, ct->dt); + } + + winsys->displaytarget_display(winsys, ct->dt, context_private); +} + + void cell_init_screen_texture_funcs(struct pipe_screen *screen) { @@ -476,9 +561,14 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen) screen->get_tex_surface = cell_get_tex_surface; screen->tex_surface_destroy = cell_tex_surface_destroy; - screen->get_tex_transfer = cell_get_tex_transfer; - screen->tex_transfer_destroy = cell_tex_transfer_destroy; + screen->flush_frontbuffer = cell_flush_frontbuffer; +} - screen->transfer_map = cell_transfer_map; - screen->transfer_unmap = cell_transfer_unmap; +void +cell_init_texture_transfer_funcs(struct cell_context *cell) +{ + cell->pipe.get_tex_transfer = cell_get_tex_transfer; + cell->pipe.tex_transfer_destroy = cell_tex_transfer_destroy; + cell->pipe.transfer_map = cell_transfer_map; + cell->pipe.transfer_unmap = cell_transfer_unmap; } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h index 3ffc0bfdb51..ac0b9167750 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.h +++ b/src/gallium/drivers/cell/ppu/cell_texture.h @@ -28,6 +28,7 @@ #ifndef CELL_TEXTURE_H #define CELL_TEXTURE_H +#include "cell/common.h" struct cell_context; struct pipe_texture; @@ -43,8 +44,20 @@ struct cell_texture unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS]; unsigned long stride[CELL_MAX_TEXTURE_LEVELS]; - /** The tiled texture data is held in this buffer */ - struct pipe_buffer *buffer; + /** + * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET + * usage. + */ + struct sw_displaytarget *dt; + unsigned dt_stride; + + /** + * Malloc'ed data for regular textures, or a mapping to dt above. + */ + void *data; + + /* Size of the linear buffer?? + */ unsigned long buffer_size; /** The buffer above, mapped. This is the memory from which the @@ -82,5 +95,7 @@ cell_transfer(struct pipe_transfer *pt) extern void cell_init_screen_texture_funcs(struct pipe_screen *screen); +extern void +cell_init_texture_transfer_funcs(struct cell_context *cell); #endif /* CELL_TEXTURE_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c index cf8cd411598..3d389d6ea36 100644 --- a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c @@ -31,7 +31,6 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "util/u_simple_screen.h" #include "util/u_math.h" #include "cell_context.h" diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c index 2ccc5d3e605..659e40cbf03 100644 --- a/src/gallium/drivers/failover/fo_context.c +++ b/src/gallium/drivers/failover/fo_context.c @@ -27,7 +27,6 @@ #include "pipe/p_defines.h" -#include "util/u_simple_screen.h" #include "util/u_memory.h" #include "pipe/p_context.h" diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h index bb1a168ea7a..73031321d98 100644 --- a/src/gallium/drivers/failover/fo_context.h +++ b/src/gallium/drivers/failover/fo_context.h @@ -47,7 +47,7 @@ #define FO_NEW_ALPHA_TEST 0x100 #define FO_NEW_DEPTH_STENCIL 0x200 #define FO_NEW_SAMPLER 0x400 -#define FO_NEW_TEXTURE 0x800 +#define FO_NEW_SAMPLER_VIEW 0x800 #define FO_NEW_VERTEX 0x2000 #define FO_NEW_VERTEX_SHADER 0x4000 #define FO_NEW_BLEND_COLOR 0x8000 @@ -65,6 +65,13 @@ struct fo_state { void *sw_state; void *hw_state; }; + +struct fo_sampler_view { + struct pipe_sampler_view base; + struct pipe_sampler_view *sw; + struct pipe_sampler_view *hw; +}; + struct failover_context { struct pipe_context pipe; /**< base class */ @@ -78,6 +85,7 @@ struct failover_context { const struct fo_state *rasterizer; const struct fo_state *fragment_shader; const struct fo_state *vertex_shader; + const struct fo_state *vertex_elements; struct pipe_blend_color blend_color; struct pipe_stencil_ref stencil_ref; @@ -85,26 +93,25 @@ struct failover_context { struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; - struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; - struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_elements[PIPE_MAX_ATTRIBS]; uint num_vertex_buffers; - uint num_vertex_elements; void *sw_sampler_state[PIPE_MAX_SAMPLERS]; void *hw_sampler_state[PIPE_MAX_SAMPLERS]; void *sw_vertex_sampler_state[PIPE_MAX_VERTEX_SAMPLERS]; void *hw_vertex_sampler_state[PIPE_MAX_VERTEX_SAMPLERS]; + struct fo_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + struct fo_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; + unsigned num_fragment_sampler_views; + unsigned num_vertex_sampler_views; + unsigned dirty; unsigned num_samplers; unsigned num_vertex_samplers; - unsigned num_textures; - unsigned num_vertex_textures; unsigned mode; struct pipe_context *hw; diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c index 970606a3f50..25c62735705 100644 --- a/src/gallium/drivers/failover/fo_state.c +++ b/src/gallium/drivers/failover/fo_state.c @@ -255,9 +255,52 @@ failover_delete_vs_state(struct pipe_context *pipe, free(state); } + + +static void * +failover_create_vertex_elements_state( struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *velems ) +{ + struct fo_state *state = malloc(sizeof(struct fo_state)); + struct failover_context *failover = failover_context(pipe); + + state->sw_state = failover->sw->create_vertex_elements_state(failover->sw, count, velems); + state->hw_state = failover->hw->create_vertex_elements_state(failover->hw, count, velems); + + return state; +} + +static void +failover_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems ) +{ + struct failover_context *failover = failover_context(pipe); + struct fo_state *state = (struct fo_state*)velems; + + failover->vertex_elements = state; + failover->dirty |= FO_NEW_VERTEX_ELEMENT; + failover->sw->bind_vertex_elements_state( failover->sw, velems ); + failover->hw->bind_vertex_elements_state( failover->hw, velems ); +} + +static void +failover_delete_vertex_elements_state( struct pipe_context *pipe, + void *velems ) +{ + struct fo_state *state = (struct fo_state*)velems; + struct failover_context *failover = failover_context(pipe); + + failover->sw->delete_vertex_elements_state(failover->sw, state->sw_state); + failover->hw->delete_vertex_elements_state(failover->hw, state->hw_state); + state->sw_state = 0; + state->hw_state = 0; + free(state); +} + static void failover_set_polygon_stipple( struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple ) + const struct pipe_poly_stipple *stipple ) { struct failover_context *failover = failover_context(pipe); @@ -404,60 +447,96 @@ failover_delete_sampler_state(struct pipe_context *pipe, void *sampler) } +static struct pipe_sampler_view * +failover_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct fo_sampler_view *view = malloc(sizeof(struct fo_sampler_view)); + struct failover_context *failover = failover_context(pipe); + + view->sw = failover->sw->create_sampler_view(failover->sw, texture, templ); + view->hw = failover->hw->create_sampler_view(failover->hw, texture, templ); + + view->base = *templ; + view->base.reference.count = 1; + view->base.texture = NULL; + pipe_texture_reference(&view->base.texture, texture); + view->base.context = pipe; + + return &view->base; +} + +static void +failover_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + struct fo_sampler_view *fo_view = (struct fo_sampler_view *)view; + struct failover_context *failover = failover_context(pipe); + + failover->sw->sampler_view_destroy(failover->sw, fo_view->sw); + failover->hw->sampler_view_destroy(failover->hw, fo_view->hw); + + pipe_texture_reference(&fo_view->base.texture, NULL); + free(fo_view); +} + static void -failover_set_fragment_sampler_textures(struct pipe_context *pipe, - unsigned num, - struct pipe_texture **texture) +failover_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct failover_context *failover = failover_context(pipe); + struct pipe_sampler_view *hw_views[PIPE_MAX_SAMPLERS]; uint i; assert(num <= PIPE_MAX_SAMPLERS); /* Check for no-op */ - if (num == failover->num_textures && - !memcmp(failover->texture, texture, num * sizeof(struct pipe_texture *))) + if (num == failover->num_fragment_sampler_views && + !memcmp(failover->fragment_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) return; - for (i = 0; i < num; i++) - pipe_texture_reference((struct pipe_texture **) &failover->texture[i], - texture[i]); - for (i = num; i < failover->num_textures; i++) - pipe_texture_reference((struct pipe_texture **) &failover->texture[i], - NULL); - failover->dirty |= FO_NEW_TEXTURE; - failover->num_textures = num; - failover->sw->set_fragment_sampler_textures( failover->sw, num, texture ); - failover->hw->set_fragment_sampler_textures( failover->hw, num, texture ); + for (i = 0; i < num; i++) { + struct fo_sampler_view *fo_view = (struct fo_sampler_view *)views[i]; + + pipe_sampler_view_reference((struct pipe_sampler_view **)&failover->fragment_sampler_views[i], views[i]); + hw_views[i] = fo_view->hw; + } + for (i = num; i < failover->num_fragment_sampler_views; i++) + pipe_sampler_view_reference((struct pipe_sampler_view **)&failover->fragment_sampler_views[i], NULL); + failover->dirty |= FO_NEW_SAMPLER_VIEW; + failover->num_fragment_sampler_views = num; + failover->hw->set_fragment_sampler_views(failover->hw, num, hw_views); } static void -failover_set_vertex_sampler_textures(struct pipe_context *pipe, - unsigned num_textures, - struct pipe_texture **textures) +failover_set_vertex_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct failover_context *failover = failover_context(pipe); + struct pipe_sampler_view *hw_views[PIPE_MAX_VERTEX_SAMPLERS]; uint i; - assert(num_textures <= PIPE_MAX_VERTEX_SAMPLERS); + assert(num <= PIPE_MAX_VERTEX_SAMPLERS); /* Check for no-op */ - if (num_textures == failover->num_vertex_textures && - !memcmp(failover->vertex_textures, textures, num_textures * sizeof(struct pipe_texture *))) { + if (num == failover->num_vertex_sampler_views && + !memcmp(failover->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) { return; } - for (i = 0; i < num_textures; i++) { - pipe_texture_reference((struct pipe_texture **)&failover->vertex_textures[i], - textures[i]); - } - for (i = num_textures; i < failover->num_vertex_textures; i++) { - pipe_texture_reference((struct pipe_texture **)&failover->vertex_textures[i], - NULL); + for (i = 0; i < num; i++) { + struct fo_sampler_view *fo_view = (struct fo_sampler_view *)views[i]; + + pipe_sampler_view_reference((struct pipe_sampler_view **)&failover->vertex_sampler_views[i], views[i]); + hw_views[i] = fo_view->hw; } - failover->dirty |= FO_NEW_TEXTURE; - failover->num_vertex_textures = num_textures; - failover->sw->set_vertex_sampler_textures(failover->sw, num_textures, textures); - failover->hw->set_vertex_sampler_textures(failover->hw, num_textures, textures); + for (i = num; i < failover->num_vertex_sampler_views; i++) + pipe_sampler_view_reference((struct pipe_sampler_view **)&failover->vertex_sampler_views[i], NULL); + failover->dirty |= FO_NEW_SAMPLER_VIEW; + failover->num_vertex_sampler_views = num; + failover->hw->set_vertex_sampler_views(failover->hw, num, hw_views); } @@ -490,22 +569,6 @@ failover_set_vertex_buffers(struct pipe_context *pipe, } -static void -failover_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *vertex_elements) -{ - struct failover_context *failover = failover_context(pipe); - - memcpy(failover->vertex_elements, vertex_elements, - count * sizeof(vertex_elements[0])); - - failover->dirty |= FO_NEW_VERTEX_ELEMENT; - failover->num_vertex_elements = count; - failover->sw->set_vertex_elements( failover->sw, count, vertex_elements ); - failover->hw->set_vertex_elements( failover->hw, count, vertex_elements ); -} - void failover_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, @@ -543,6 +606,9 @@ failover_init_state_functions( struct failover_context *failover ) failover->pipe.create_vs_state = failover_create_vs_state; failover->pipe.bind_vs_state = failover_bind_vs_state; failover->pipe.delete_vs_state = failover_delete_vs_state; + failover->pipe.create_vertex_elements_state = failover_create_vertex_elements_state; + failover->pipe.bind_vertex_elements_state = failover_bind_vertex_elements_state; + failover->pipe.delete_vertex_elements_state = failover_delete_vertex_elements_state; failover->pipe.set_blend_color = failover_set_blend_color; failover->pipe.set_stencil_ref = failover_set_stencil_ref; @@ -550,10 +616,11 @@ failover_init_state_functions( struct failover_context *failover ) failover->pipe.set_framebuffer_state = failover_set_framebuffer_state; failover->pipe.set_polygon_stipple = failover_set_polygon_stipple; failover->pipe.set_scissor_state = failover_set_scissor_state; - failover->pipe.set_fragment_sampler_textures = failover_set_fragment_sampler_textures; - failover->pipe.set_vertex_sampler_textures = failover_set_vertex_sampler_textures; + failover->pipe.set_fragment_sampler_views = failover_set_fragment_sampler_views; + failover->pipe.set_vertex_sampler_views = failover_set_vertex_sampler_views; failover->pipe.set_viewport_state = failover_set_viewport_state; failover->pipe.set_vertex_buffers = failover_set_vertex_buffers; - failover->pipe.set_vertex_elements = failover_set_vertex_elements; failover->pipe.set_constant_buffer = failover_set_constant_buffer; + failover->pipe.create_sampler_view = failover_create_sampler_view; + failover->pipe.sampler_view_destroy = failover_sampler_view_destroy; } diff --git a/src/gallium/drivers/failover/fo_state_emit.c b/src/gallium/drivers/failover/fo_state_emit.c index 5c000808425..42bd6929a7f 100644 --- a/src/gallium/drivers/failover/fo_state_emit.c +++ b/src/gallium/drivers/failover/fo_state_emit.c @@ -81,6 +81,10 @@ failover_state_emit( struct failover_context *failover ) failover->sw->bind_vs_state( failover->sw, failover->vertex_shader->sw_state ); + if (failover->dirty & FO_NEW_VERTEX_ELEMENT) + failover->sw->bind_vertex_elements_state( failover->sw, + failover->vertex_elements->sw_state ); + if (failover->dirty & FO_NEW_STIPPLE) failover->sw->set_polygon_stipple( failover->sw, &failover->poly_stipple ); @@ -102,12 +106,24 @@ failover_state_emit( struct failover_context *failover ) failover->sw_vertex_sampler_state); } - if (failover->dirty & FO_NEW_TEXTURE) { - failover->sw->set_fragment_sampler_textures( failover->sw, failover->num_textures, - failover->texture ); - failover->sw->set_vertex_sampler_textures(failover->sw, - failover->num_vertex_textures, - failover->vertex_textures); + if (failover->dirty & FO_NEW_SAMPLER_VIEW) { + struct pipe_sampler_view *fragment_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *vertex_views[PIPE_MAX_VERTEX_SAMPLERS]; + uint i; + + for (i = 0; i < failover->num_fragment_sampler_views; i++) { + fragment_views[i] = failover->fragment_sampler_views[i]->sw; + } + failover->sw->set_fragment_sampler_views(failover->sw, + failover->num_fragment_sampler_views, + fragment_views); + + for (i = 0; i < failover->num_vertex_sampler_views; i++) { + vertex_views[i] = failover->vertex_sampler_views[i]->sw; + } + failover->sw->set_vertex_sampler_views(failover->sw, + failover->num_vertex_sampler_views, + vertex_views); } if (failover->dirty & FO_NEW_VERTEX_BUFFER) { @@ -116,11 +132,5 @@ failover_state_emit( struct failover_context *failover ) failover->vertex_buffers ); } - if (failover->dirty & FO_NEW_VERTEX_ELEMENT) { - failover->sw->set_vertex_elements( failover->sw, - failover->num_vertex_elements, - failover->vertex_elements ); - } - failover->dirty = 0; } diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 3d45a22b7e7..130519ffa50 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -221,6 +221,7 @@ i915_create_context(struct pipe_screen *screen, void *priv) i915_init_surface_functions(i915); i915_init_state_functions(i915); i915_init_flush_functions(i915); + i915_init_texture_functions(i915); draw_install_aaline_stage(i915->draw, &i915->base); draw_install_aapoint_stage(i915->draw, &i915->base); diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index da769e7b290..5348f62ca74 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -148,7 +148,7 @@ struct i915_state /** Describes the current hardware vertex layout */ struct vertex_info vertex_info; - + unsigned id; /* track lost context events */ }; @@ -187,6 +187,14 @@ struct i915_sampler_state { unsigned maxlod; }; +struct i915_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; + +#define I915_MAX_TEXTURE_2D_LEVELS 11 /* max 1024x1024 */ +#define I915_MAX_TEXTURE_3D_LEVELS 8 /* max 128x128x128 */ + struct i915_texture { struct pipe_texture base; @@ -199,7 +207,7 @@ struct i915_texture { unsigned sw_tiled; /**< tiled with software flags */ unsigned hw_tiled; /**< tiled with hardware fences */ - unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS]; + unsigned nr_images[I915_MAX_TEXTURE_2D_LEVELS]; /* Explicitly store the offset of each image for each cube face or * depth value. Pretty much have to accept that hardware formats @@ -207,7 +215,7 @@ struct i915_texture { * compute the offsets of depth/cube images within a mipmap level, * so have to store them as a lookup table: */ - unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; /**< array [depth] of offsets */ + unsigned *image_offset[I915_MAX_TEXTURE_2D_LEVELS]; /**< array [depth] of offsets */ /* The data is held here: */ @@ -239,15 +247,14 @@ struct i915_context struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; - struct i915_texture *texture[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; unsigned dirty; unsigned num_samplers; - unsigned num_textures; - unsigned num_vertex_elements; + unsigned num_fragment_sampler_views; unsigned num_vertex_buffers; struct intel_batchbuffer *batch; @@ -276,7 +283,7 @@ struct i915_context #define I915_NEW_ALPHA_TEST 0x100 #define I915_NEW_DEPTH_STENCIL 0x200 #define I915_NEW_SAMPLER 0x400 -#define I915_NEW_TEXTURE 0x800 +#define I915_NEW_SAMPLER_VIEW 0x800 #define I915_NEW_CONSTANTS 0x1000 #define I915_NEW_VBO 0x2000 #define I915_NEW_VS 0x4000 @@ -343,6 +350,12 @@ struct pipe_context *i915_create_context(struct pipe_screen *screen, /*********************************************************************** + * i915_texture.c + */ +void i915_init_texture_functions(struct i915_context *i915 ); + + +/*********************************************************************** * Inline conversion functions. These are better-typed than the * macros used previously: */ diff --git a/src/gallium/drivers/i915/i915_debug_fp.c b/src/gallium/drivers/i915/i915_debug_fp.c index 066e7392d18..f41c51f2991 100644 --- a/src/gallium/drivers/i915/i915_debug_fp.c +++ b/src/gallium/drivers/i915/i915_debug_fp.c @@ -28,7 +28,6 @@ #include "i915_reg.h" #include "i915_debug.h" -#include "util/u_simple_screen.h" #include "util/u_debug.h" diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index 72bd2635506..e5bf4a20bd0 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -116,11 +116,11 @@ i915_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 11; /* max 1024x1024 */ + return I915_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 8; /* max 128x128x128 */ + return I915_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 11; /* max 1024x1024 */ + return I915_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 62169918e2b..0f7395246cc 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -560,9 +560,9 @@ static void i915_set_constant_buffer(struct pipe_context *pipe, } -static void i915_set_sampler_textures(struct pipe_context *pipe, - unsigned num, - struct pipe_texture **texture) +static void i915_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct i915_context *i915 = i915_context(pipe); uint i; @@ -570,27 +570,54 @@ static void i915_set_sampler_textures(struct pipe_context *pipe, assert(num <= PIPE_MAX_SAMPLERS); /* Check for no-op */ - if (num == i915->num_textures && - !memcmp(i915->texture, texture, num * sizeof(struct pipe_texture *))) + if (num == i915->num_fragment_sampler_views && + !memcmp(i915->fragment_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) return; /* Fixes wrong texture in texobj with VBUF */ draw_flush(i915->draw); for (i = 0; i < num; i++) - pipe_texture_reference((struct pipe_texture **) &i915->texture[i], - texture[i]); + pipe_sampler_view_reference(&i915->fragment_sampler_views[i], + views[i]); - for (i = num; i < i915->num_textures; i++) - pipe_texture_reference((struct pipe_texture **) &i915->texture[i], - NULL); + for (i = num; i < i915->num_fragment_sampler_views; i++) + pipe_sampler_view_reference(&i915->fragment_sampler_views[i], + NULL); - i915->num_textures = num; + i915->num_fragment_sampler_views = num; - i915->dirty |= I915_NEW_TEXTURE; + i915->dirty |= I915_NEW_SAMPLER_VIEW; } +static struct pipe_sampler_view * +i915_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +i915_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + static void i915_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) @@ -742,21 +769,45 @@ static void i915_set_vertex_buffers(struct pipe_context *pipe, draw_set_vertex_buffers(i915->draw, count, buffers); } -static void i915_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements) +static void * +i915_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) +{ + struct i915_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct i915_velems_state *) MALLOC(sizeof(struct i915_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + +static void +i915_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) { struct i915_context *i915 = i915_context(pipe); + struct i915_velems_state *i915_velems = (struct i915_velems_state *) velems; + /* Because we change state before the draw_set_vertex_buffers call * we need a flush here, just to be sure. */ draw_flush(i915->draw); - i915->num_vertex_elements = count; /* pass-through to draw module */ - draw_set_vertex_elements(i915->draw, count, elements); + if (i915_velems) { + draw_set_vertex_elements(i915->draw, + i915_velems->count, i915_velems->velem); + } } +static void +i915_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} void i915_init_state_functions( struct i915_context *i915 ) @@ -782,6 +833,9 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.create_vs_state = i915_create_vs_state; i915->base.bind_vs_state = i915_bind_vs_state; i915->base.delete_vs_state = i915_delete_vs_state; + i915->base.create_vertex_elements_state = i915_create_vertex_elements_state; + i915->base.bind_vertex_elements_state = i915_bind_vertex_elements_state; + i915->base.delete_vertex_elements_state = i915_delete_vertex_elements_state; i915->base.set_blend_color = i915_set_blend_color; i915->base.set_stencil_ref = i915_set_stencil_ref; @@ -791,8 +845,9 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.set_polygon_stipple = i915_set_polygon_stipple; i915->base.set_scissor_state = i915_set_scissor_state; - i915->base.set_fragment_sampler_textures = i915_set_sampler_textures; + i915->base.set_fragment_sampler_views = i915_set_fragment_sampler_views; + i915->base.create_sampler_view = i915_create_sampler_view; + i915->base.sampler_view_destroy = i915_sampler_view_destroy; i915->base.set_viewport_state = i915_set_viewport_state; i915->base.set_vertex_buffers = i915_set_vertex_buffers; - i915->base.set_vertex_elements = i915_set_vertex_elements; } diff --git a/src/gallium/drivers/i915/i915_state_derived.c b/src/gallium/drivers/i915/i915_state_derived.c index f5b0e9f011e..0eb1e3f91a4 100644 --- a/src/gallium/drivers/i915/i915_state_derived.c +++ b/src/gallium/drivers/i915/i915_state_derived.c @@ -157,10 +157,10 @@ void i915_update_derived( struct i915_context *i915 ) if (i915->dirty & (I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS)) calculate_vertex_layout( i915 ); - if (i915->dirty & (I915_NEW_SAMPLER | I915_NEW_TEXTURE)) + if (i915->dirty & (I915_NEW_SAMPLER | I915_NEW_SAMPLER_VIEW)) i915_update_samplers(i915); - if (i915->dirty & I915_NEW_TEXTURE) + if (i915->dirty & I915_NEW_SAMPLER_VIEW) i915_update_textures(i915); if (i915->dirty) diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index 51f0ef12baf..d79c1ca0b2c 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -290,7 +290,8 @@ i915_emit_hardware_state(struct i915_context *i915 ) OUT_BATCH(enabled); for (unit = 0; unit < I915_TEX_UNITS; unit++) { if (enabled & (1 << unit)) { - struct intel_buffer *buf = i915->texture[unit]->buffer; + struct i915_texture *texture = (struct i915_texture *)i915->fragment_sampler_views[unit]->texture; + struct intel_buffer *buf = texture->buffer; uint offset = 0; assert(buf); diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index 9813290b51b..d6da8225490 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -144,20 +144,22 @@ void i915_update_samplers( struct i915_context *i915 ) i915->current.sampler_enable_nr = 0; i915->current.sampler_enable_flags = 0x0; - for (unit = 0; unit < i915->num_textures && unit < i915->num_samplers; + for (unit = 0; unit < i915->num_fragment_sampler_views && unit < i915->num_samplers; unit++) { /* determine unit enable/disable by looking for a bound texture */ /* could also examine the fragment program? */ - if (i915->texture[unit]) { + if (i915->fragment_sampler_views[unit]) { + struct i915_texture *texture = (struct i915_texture *)i915->fragment_sampler_views[unit]->texture; + update_sampler( i915, unit, i915->sampler[unit], /* sampler state */ - i915->texture[unit], /* texture */ + texture, /* texture */ i915->current.sampler[unit] /* the result */ ); i915_update_texture( i915, unit, - i915->texture[unit], /* texture */ + texture, /* texture */ i915->sampler[unit], /* sampler state */ i915->current.texbuffer[unit] ); @@ -281,14 +283,16 @@ i915_update_textures(struct i915_context *i915) { uint unit; - for (unit = 0; unit < i915->num_textures && unit < i915->num_samplers; + for (unit = 0; unit < i915->num_fragment_sampler_views && unit < i915->num_samplers; unit++) { /* determine unit enable/disable by looking for a bound texture */ /* could also examine the fragment program? */ - if (i915->texture[unit]) { + if (i915->fragment_sampler_views[unit]) { + struct i915_texture *texture = (struct i915_texture *)i915->fragment_sampler_views[unit]->texture; + i915_update_texture( i915, unit, - i915->texture[unit], /* texture */ + texture, /* texture */ i915->sampler[unit], /* sampler state */ i915->current.texbuffer[unit] ); } diff --git a/src/gallium/drivers/i915/i915_texture.c b/src/gallium/drivers/i915/i915_texture.c index 7ba222c78b7..b252fb5330c 100644 --- a/src/gallium/drivers/i915/i915_texture.c +++ b/src/gallium/drivers/i915/i915_texture.c @@ -96,7 +96,7 @@ i915_miptree_set_level_info(struct i915_texture *tex, unsigned nr_images, unsigned w, unsigned h, unsigned d) { - assert(level < PIPE_MAX_TEXTURE_LEVELS); + assert(level < Elements(tex->nr_images)); tex->nr_images[level] = nr_images; @@ -219,12 +219,12 @@ i915_miptree_layout_2d(struct i915_texture *tex) unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->width0); /* used for scanouts that need special layouts */ - if (pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + if (pt->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) if (i915_scanout_layout(tex)) return; - /* for shared buffers we use something very like scanout */ - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) + /* shared buffers needs to be compatible with X servers */ + if (pt->tex_usage & PIPE_TEXTURE_USAGE_SHARED) if (i915_display_target_layout(tex)) return; @@ -369,12 +369,12 @@ i945_miptree_layout_2d(struct i915_texture *tex) unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->height0); /* used for scanouts that need special layouts */ - if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) if (i915_scanout_layout(tex)) return; - /* for shared buffers we use some very like scanout */ - if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) + /* shared buffers needs to be compatible with X servers */ + if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_SHARED) if (i915_display_target_layout(tex)) return; @@ -642,7 +642,7 @@ i915_texture_create(struct pipe_screen *screen, /* for scanouts and cursors, cursors arn't scanouts */ - if (templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY && templat->width0 != 64) + if (templat->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT && templat->width0 != 64) buf_usage = INTEL_NEW_SCANOUT; else buf_usage = INTEL_NEW_TEXTURE; @@ -673,19 +673,24 @@ fail: } static struct pipe_texture * -i915_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) +i915_texture_from_handle(struct pipe_screen * screen, + const struct pipe_texture *templat, + struct winsys_handle *whandle) { -#if 0 + struct i915_screen *is = i915_screen(screen); struct i915_texture *tex; + struct intel_winsys *iws = is->iws; + struct intel_buffer *buffer; + unsigned stride; + assert(screen); + buffer = iws->buffer_from_handle(iws, whandle, &stride); + /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { + if (templat->target != PIPE_TEXTURE_2D || + templat->last_level != 0 || + templat->depth0 != 1) { return NULL; } @@ -693,23 +698,33 @@ i915_texture_blanket(struct pipe_screen * screen, if (!tex) return NULL; - tex->base = *base; + tex->base = *templat; pipe_reference_init(&tex->base.reference, 1); tex->base.screen = screen; - tex->stride = stride[0]; + tex->stride = stride; - i915_miptree_set_level_info(tex, 0, 1, base->width0, base->height0, 1); + i915_miptree_set_level_info(tex, 0, 1, templat->width0, templat->height0, 1); i915_miptree_set_image_offset(tex, 0, 0, 0, 0); - pipe_buffer_reference(&tex->buffer, buffer); + tex->buffer = buffer; return &tex->base; -#else - return NULL; -#endif } +static boolean +i915_texture_get_handle(struct pipe_screen * screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct i915_screen *is = i915_screen(screen); + struct i915_texture *tex = (struct i915_texture *)texture; + struct intel_winsys *iws = is->iws; + + return iws->buffer_get_handle(iws, tex->buffer, whandle, tex->stride); +} + + static void i915_texture_destroy(struct pipe_texture *pt) { @@ -723,7 +738,7 @@ i915_texture_destroy(struct pipe_texture *pt) iws->buffer_destroy(iws, tex->buffer); - for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++) + for (i = 0; i < Elements(tex->image_offset); i++) if (tex->image_offset[i]) FREE(tex->image_offset[i]); @@ -780,12 +795,12 @@ i915_tex_surface_destroy(struct pipe_surface *surf) /* - * Screen transfer functions + * Texture transfer functions */ -static struct pipe_transfer* -i915_get_tex_transfer(struct pipe_screen *screen, +static struct pipe_transfer * +i915_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, @@ -822,7 +837,7 @@ i915_get_tex_transfer(struct pipe_screen *screen, } static void * -i915_transfer_map(struct pipe_screen *screen, +i915_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct i915_texture *tex = (struct i915_texture *)transfer->texture; @@ -844,7 +859,7 @@ i915_transfer_map(struct pipe_screen *screen, } static void -i915_transfer_unmap(struct pipe_screen *screen, +i915_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct i915_texture *tex = (struct i915_texture *)transfer->texture; @@ -853,7 +868,8 @@ i915_transfer_unmap(struct pipe_screen *screen, } static void -i915_tex_transfer_destroy(struct pipe_transfer *trans) +i915_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *trans) { pipe_texture_reference(&trans->texture, NULL); FREE(trans); @@ -864,67 +880,22 @@ i915_tex_transfer_destroy(struct pipe_transfer *trans) * Other texture functions */ +void +i915_init_texture_functions(struct i915_context *i915 ) +{ + i915->base.get_tex_transfer = i915_get_tex_transfer; + i915->base.transfer_map = i915_transfer_map; + i915->base.transfer_unmap = i915_transfer_unmap; + i915->base.tex_transfer_destroy = i915_tex_transfer_destroy; +} void i915_init_screen_texture_functions(struct i915_screen *is) { is->base.texture_create = i915_texture_create; - is->base.texture_blanket = i915_texture_blanket; + is->base.texture_from_handle = i915_texture_from_handle; + is->base.texture_get_handle = i915_texture_get_handle; is->base.texture_destroy = i915_texture_destroy; is->base.get_tex_surface = i915_get_tex_surface; is->base.tex_surface_destroy = i915_tex_surface_destroy; - is->base.get_tex_transfer = i915_get_tex_transfer; - is->base.transfer_map = i915_transfer_map; - is->base.transfer_unmap = i915_transfer_unmap; - is->base.tex_transfer_destroy = i915_tex_transfer_destroy; -} - -struct pipe_texture * -i915_texture_blanket_intel(struct pipe_screen *screen, - struct pipe_texture *base, - unsigned stride, - struct intel_buffer *buffer) -{ - struct i915_texture *tex; - assert(screen); - - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; - } - - tex = CALLOC_STRUCT(i915_texture); - if (!tex) - return NULL; - - tex->base = *base; - pipe_reference_init(&tex->base.reference, 1); - tex->base.screen = screen; - - tex->stride = stride; - - i915_miptree_set_level_info(tex, 0, 1, base->width0, base->height0, 1); - i915_miptree_set_image_offset(tex, 0, 0, 0, 0); - - tex->buffer = buffer; - - return &tex->base; -} - -boolean -i915_get_texture_buffer_intel(struct pipe_texture *texture, - struct intel_buffer **buffer, - unsigned *stride) -{ - struct i915_texture *tex = (struct i915_texture *)texture; - - if (!texture) - return FALSE; - - *stride = tex->stride; - *buffer = tex->buffer; - - return TRUE; } diff --git a/src/gallium/drivers/i915/intel_winsys.h b/src/gallium/drivers/i915/intel_winsys.h index b3a802b0e29..00fd0c1efea 100644 --- a/src/gallium/drivers/i915/intel_winsys.h +++ b/src/gallium/drivers/i915/intel_winsys.h @@ -33,6 +33,7 @@ struct intel_buffer; struct intel_batchbuffer; struct pipe_texture; struct pipe_fence_handle; +struct winsys_handle; enum intel_buffer_usage { @@ -129,6 +130,25 @@ struct intel_winsys { enum intel_buffer_type type); /** + * Creates a buffer from a handle. + * Used to implement pipe_screen::texture_from_handle. + * Also provides the stride information needed for the + * texture via the stride argument. + */ + struct intel_buffer *(*buffer_from_handle)(struct intel_winsys *iws, + struct winsys_handle *whandle, + unsigned *stride); + + /** + * Used to implement pipe_screen::texture_get_handle. + * The winsys might need the stride information. + */ + boolean (*buffer_get_handle)(struct intel_winsys *iws, + struct intel_buffer *buffer, + struct winsys_handle *whandle, + unsigned stride); + + /** * Fence a buffer with a fence reg. * Not to be confused with pipe_fence_handle. */ @@ -204,23 +224,4 @@ struct intel_winsys { struct pipe_screen *i915_create_screen(struct intel_winsys *iws, unsigned pci_id); -/** - * Get the intel_winsys buffer backing the texture. - * - * TODO UGLY - */ -boolean i915_get_texture_buffer_intel(struct pipe_texture *texture, - struct intel_buffer **buffer, - unsigned *stride); - -/** - * Wrap a intel_winsys buffer with a texture blanket. - * - * TODO UGLY - */ -struct pipe_texture * i915_texture_blanket_intel(struct pipe_screen *screen, - struct pipe_texture *tmplt, - unsigned pitch, - struct intel_buffer *buffer); - #endif diff --git a/src/gallium/drivers/i965/brw_context.c b/src/gallium/drivers/i965/brw_context.c index 3dbe2b91308..4bcdcdd17eb 100644 --- a/src/gallium/drivers/i965/brw_context.c +++ b/src/gallium/drivers/i965/brw_context.c @@ -118,6 +118,7 @@ struct pipe_context *brw_create_context(struct pipe_screen *screen, brw->sws = brw_screen(screen)->sws; brw->chipset = brw_screen(screen)->chipset; + brw_tex_init( brw ); brw_pipe_blend_init( brw ); brw_pipe_depth_stencil_init( brw ); brw_pipe_framebuffer_init( brw ); diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h index 12cfa7b049c..dab881fea24 100644 --- a/src/gallium/drivers/i965/brw_context.h +++ b/src/gallium/drivers/i965/brw_context.h @@ -351,7 +351,7 @@ struct brw_vs_prog_data { /* Size == 0 if output either not written, or always [0,0,0,1] */ -struct brw_vs_ouput_sizes { +struct brw_vs_output_sizes { GLubyte output_size[PIPE_MAX_SHADER_OUTPUTS]; }; @@ -546,15 +546,14 @@ struct brw_context const struct brw_blend_state *blend; const struct brw_rasterizer_state *rast; const struct brw_depth_stencil_state *zstencil; + const struct brw_vertex_element_packet *velems; const struct brw_sampler *sampler[PIPE_MAX_SAMPLERS]; unsigned num_samplers; - struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; - unsigned num_vertex_elements; - unsigned num_textures; + unsigned num_fragment_sampler_views; unsigned num_vertex_buffers; struct pipe_scissor_state scissor; diff --git a/src/gallium/drivers/i965/brw_draw_upload.c b/src/gallium/drivers/i965/brw_draw_upload.c index 9f136eec71c..0820ba20a08 100644 --- a/src/gallium/drivers/i965/brw_draw_upload.c +++ b/src/gallium/drivers/i965/brw_draw_upload.c @@ -42,141 +42,6 @@ -static unsigned brw_translate_surface_format( unsigned id ) -{ - switch (id) { - case PIPE_FORMAT_R64_FLOAT: - return BRW_SURFACEFORMAT_R64_FLOAT; - case PIPE_FORMAT_R64G64_FLOAT: - return BRW_SURFACEFORMAT_R64G64_FLOAT; - case PIPE_FORMAT_R64G64B64_FLOAT: - return BRW_SURFACEFORMAT_R64G64B64_FLOAT; - case PIPE_FORMAT_R64G64B64A64_FLOAT: - return BRW_SURFACEFORMAT_R64G64B64A64_FLOAT; - - case PIPE_FORMAT_R32_FLOAT: - return BRW_SURFACEFORMAT_R32_FLOAT; - case PIPE_FORMAT_R32G32_FLOAT: - return BRW_SURFACEFORMAT_R32G32_FLOAT; - case PIPE_FORMAT_R32G32B32_FLOAT: - return BRW_SURFACEFORMAT_R32G32B32_FLOAT; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - return BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; - - case PIPE_FORMAT_R32_UNORM: - return BRW_SURFACEFORMAT_R32_UNORM; - case PIPE_FORMAT_R32G32_UNORM: - return BRW_SURFACEFORMAT_R32G32_UNORM; - case PIPE_FORMAT_R32G32B32_UNORM: - return BRW_SURFACEFORMAT_R32G32B32_UNORM; - case PIPE_FORMAT_R32G32B32A32_UNORM: - return BRW_SURFACEFORMAT_R32G32B32A32_UNORM; - - case PIPE_FORMAT_R32_USCALED: - return BRW_SURFACEFORMAT_R32_USCALED; - case PIPE_FORMAT_R32G32_USCALED: - return BRW_SURFACEFORMAT_R32G32_USCALED; - case PIPE_FORMAT_R32G32B32_USCALED: - return BRW_SURFACEFORMAT_R32G32B32_USCALED; - case PIPE_FORMAT_R32G32B32A32_USCALED: - return BRW_SURFACEFORMAT_R32G32B32A32_USCALED; - - case PIPE_FORMAT_R32_SNORM: - return BRW_SURFACEFORMAT_R32_SNORM; - case PIPE_FORMAT_R32G32_SNORM: - return BRW_SURFACEFORMAT_R32G32_SNORM; - case PIPE_FORMAT_R32G32B32_SNORM: - return BRW_SURFACEFORMAT_R32G32B32_SNORM; - case PIPE_FORMAT_R32G32B32A32_SNORM: - return BRW_SURFACEFORMAT_R32G32B32A32_SNORM; - - case PIPE_FORMAT_R32_SSCALED: - return BRW_SURFACEFORMAT_R32_SSCALED; - case PIPE_FORMAT_R32G32_SSCALED: - return BRW_SURFACEFORMAT_R32G32_SSCALED; - case PIPE_FORMAT_R32G32B32_SSCALED: - return BRW_SURFACEFORMAT_R32G32B32_SSCALED; - case PIPE_FORMAT_R32G32B32A32_SSCALED: - return BRW_SURFACEFORMAT_R32G32B32A32_SSCALED; - - case PIPE_FORMAT_R16_UNORM: - return BRW_SURFACEFORMAT_R16_UNORM; - case PIPE_FORMAT_R16G16_UNORM: - return BRW_SURFACEFORMAT_R16G16_UNORM; - case PIPE_FORMAT_R16G16B16_UNORM: - return BRW_SURFACEFORMAT_R16G16B16_UNORM; - case PIPE_FORMAT_R16G16B16A16_UNORM: - return BRW_SURFACEFORMAT_R16G16B16A16_UNORM; - - case PIPE_FORMAT_R16_USCALED: - return BRW_SURFACEFORMAT_R16_USCALED; - case PIPE_FORMAT_R16G16_USCALED: - return BRW_SURFACEFORMAT_R16G16_USCALED; - case PIPE_FORMAT_R16G16B16_USCALED: - return BRW_SURFACEFORMAT_R16G16B16_USCALED; - case PIPE_FORMAT_R16G16B16A16_USCALED: - return BRW_SURFACEFORMAT_R16G16B16A16_USCALED; - - case PIPE_FORMAT_R16_SNORM: - return BRW_SURFACEFORMAT_R16_SNORM; - case PIPE_FORMAT_R16G16_SNORM: - return BRW_SURFACEFORMAT_R16G16_SNORM; - case PIPE_FORMAT_R16G16B16_SNORM: - return BRW_SURFACEFORMAT_R16G16B16_SNORM; - case PIPE_FORMAT_R16G16B16A16_SNORM: - return BRW_SURFACEFORMAT_R16G16B16A16_SNORM; - - case PIPE_FORMAT_R16_SSCALED: - return BRW_SURFACEFORMAT_R16_SSCALED; - case PIPE_FORMAT_R16G16_SSCALED: - return BRW_SURFACEFORMAT_R16G16_SSCALED; - case PIPE_FORMAT_R16G16B16_SSCALED: - return BRW_SURFACEFORMAT_R16G16B16_SSCALED; - case PIPE_FORMAT_R16G16B16A16_SSCALED: - return BRW_SURFACEFORMAT_R16G16B16A16_SSCALED; - - case PIPE_FORMAT_R8_UNORM: - return BRW_SURFACEFORMAT_R8_UNORM; - case PIPE_FORMAT_R8G8_UNORM: - return BRW_SURFACEFORMAT_R8G8_UNORM; - case PIPE_FORMAT_R8G8B8_UNORM: - return BRW_SURFACEFORMAT_R8G8B8_UNORM; - case PIPE_FORMAT_R8G8B8A8_UNORM: - return BRW_SURFACEFORMAT_R8G8B8A8_UNORM; - - case PIPE_FORMAT_R8_USCALED: - return BRW_SURFACEFORMAT_R8_USCALED; - case PIPE_FORMAT_R8G8_USCALED: - return BRW_SURFACEFORMAT_R8G8_USCALED; - case PIPE_FORMAT_R8G8B8_USCALED: - return BRW_SURFACEFORMAT_R8G8B8_USCALED; - case PIPE_FORMAT_R8G8B8A8_USCALED: - return BRW_SURFACEFORMAT_R8G8B8A8_USCALED; - - case PIPE_FORMAT_R8_SNORM: - return BRW_SURFACEFORMAT_R8_SNORM; - case PIPE_FORMAT_R8G8_SNORM: - return BRW_SURFACEFORMAT_R8G8_SNORM; - case PIPE_FORMAT_R8G8B8_SNORM: - return BRW_SURFACEFORMAT_R8G8B8_SNORM; - case PIPE_FORMAT_R8G8B8A8_SNORM: - return BRW_SURFACEFORMAT_R8G8B8A8_SNORM; - - case PIPE_FORMAT_R8_SSCALED: - return BRW_SURFACEFORMAT_R8_SSCALED; - case PIPE_FORMAT_R8G8_SSCALED: - return BRW_SURFACEFORMAT_R8G8_SSCALED; - case PIPE_FORMAT_R8G8B8_SSCALED: - return BRW_SURFACEFORMAT_R8G8B8_SSCALED; - case PIPE_FORMAT_R8G8B8A8_SSCALED: - return BRW_SURFACEFORMAT_R8G8B8A8_SSCALED; - - default: - assert(0); - return 0; - } -} - static unsigned get_index_type(int type) { switch (type) { @@ -315,75 +180,16 @@ static int brw_emit_vertex_buffers( struct brw_context *brw ) - static int brw_emit_vertex_elements(struct brw_context *brw) { - GLuint nr = brw->curr.num_vertex_elements; - GLuint i; + const struct brw_vertex_element_packet *brw_velems = brw->curr.velems; + unsigned size = brw_velems->header.length + 2; + /* why is this here */ brw_emit_query_begin(brw); - /* If the VS doesn't read any inputs (calculating vertex position from - * a state variable for some reason, for example), emit a single pad - * VERTEX_ELEMENT struct and bail. - * - * The stale VB state stays in place, but they don't do anything unless - * a VE loads from them. - */ - if (nr == 0) { - BEGIN_BATCH(3, IGNORE_CLIPRECTS); - OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1); - OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) | - BRW_VE0_VALID | - (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) | - (0 << BRW_VE0_SRC_OFFSET_SHIFT)); - OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) | - (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | - (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | - (BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT)); - ADVANCE_BATCH(); - return 0; - } - - /* Now emit vertex element (VEP) state packets. - * - */ - BEGIN_BATCH(1 + nr * 2, IGNORE_CLIPRECTS); - OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + nr * 2) - 2)); - for (i = 0; i < nr; i++) { - const struct pipe_vertex_element *input = &brw->curr.vertex_element[i]; - uint32_t format = brw_translate_surface_format( input->src_format ); - uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC; - uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC; - uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC; - uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC; - - switch (input->nr_components) { - case 0: comp0 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ - case 1: comp1 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ - case 2: comp2 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ - case 3: comp3 = BRW_VE1_COMPONENT_STORE_1_FLT; - break; - } - - OUT_BATCH((input->vertex_buffer_index << BRW_VE0_INDEX_SHIFT) | - BRW_VE0_VALID | - (format << BRW_VE0_FORMAT_SHIFT) | - (input->src_offset << BRW_VE0_SRC_OFFSET_SHIFT)); + brw_batchbuffer_data(brw->batch, brw_velems, size * 4, IGNORE_CLIPRECTS); - if (BRW_IS_IGDNG(brw)) - OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) | - (comp1 << BRW_VE1_COMPONENT_1_SHIFT) | - (comp2 << BRW_VE1_COMPONENT_2_SHIFT) | - (comp3 << BRW_VE1_COMPONENT_3_SHIFT)); - else - OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) | - (comp1 << BRW_VE1_COMPONENT_1_SHIFT) | - (comp2 << BRW_VE1_COMPONENT_2_SHIFT) | - (comp3 << BRW_VE1_COMPONENT_3_SHIFT) | - ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT)); - } - ADVANCE_BATCH(); return 0; } @@ -396,10 +202,11 @@ static int brw_emit_vertices( struct brw_context *brw ) if (ret) return ret; + /* XXX should separate this? */ ret = brw_emit_vertex_elements( brw ); if (ret) return ret; - + return 0; } @@ -407,7 +214,8 @@ static int brw_emit_vertices( struct brw_context *brw ) const struct brw_tracked_state brw_vertices = { .dirty = { .mesa = (PIPE_NEW_INDEX_RANGE | - PIPE_NEW_VERTEX_BUFFER), + PIPE_NEW_VERTEX_BUFFER | + PIPE_NEW_VERTEX_ELEMENT), .brw = BRW_NEW_BATCH, .cache = 0, }, diff --git a/src/gallium/drivers/i965/brw_pipe_sampler.c b/src/gallium/drivers/i965/brw_pipe_sampler.c index c7c0e2ae95e..d2aa2bc9f35 100644 --- a/src/gallium/drivers/i965/brw_pipe_sampler.c +++ b/src/gallium/drivers/i965/brw_pipe_sampler.c @@ -183,26 +183,26 @@ static void brw_delete_sampler_state(struct pipe_context *pipe, FREE(cso); } -static void brw_set_sampler_textures(struct pipe_context *pipe, - unsigned num, - struct pipe_texture **texture) +static void brw_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct brw_context *brw = brw_context(pipe); int i; for (i = 0; i < num; i++) - pipe_texture_reference(&brw->curr.texture[i], texture[i]); + pipe_sampler_view_reference(&brw->curr.fragment_sampler_views[i], views[i]); - for (i = num; i < brw->curr.num_textures; i++) - pipe_texture_reference(&brw->curr.texture[i], NULL); + for (i = num; i < brw->curr.num_fragment_sampler_views; i++) + pipe_sampler_view_reference(&brw->curr.fragment_sampler_views[i], NULL); - brw->curr.num_textures = num; + brw->curr.num_fragment_sampler_views = num; brw->state.dirty.mesa |= PIPE_NEW_BOUND_TEXTURES; } -static void brw_set_vertex_sampler_textures(struct pipe_context *pipe, - unsigned num, - struct pipe_texture **texture) +static void brw_set_vertex_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { } @@ -212,17 +212,47 @@ static void brw_bind_vertex_sampler_state(struct pipe_context *pipe, } +static struct pipe_sampler_view * +brw_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +brw_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + + void brw_pipe_sampler_init( struct brw_context *brw ) { brw->base.create_sampler_state = brw_create_sampler_state; brw->base.delete_sampler_state = brw_delete_sampler_state; - brw->base.set_fragment_sampler_textures = brw_set_sampler_textures; + brw->base.set_fragment_sampler_views = brw_set_fragment_sampler_views; brw->base.bind_fragment_sampler_states = brw_bind_sampler_state; - brw->base.set_vertex_sampler_textures = brw_set_vertex_sampler_textures; + brw->base.set_vertex_sampler_views = brw_set_vertex_sampler_views; brw->base.bind_vertex_sampler_states = brw_bind_vertex_sampler_state; + brw->base.create_sampler_view = brw_create_sampler_view; + brw->base.sampler_view_destroy = brw_sampler_view_destroy; } void brw_pipe_sampler_cleanup( struct brw_context *brw ) { diff --git a/src/gallium/drivers/i965/brw_pipe_vertex.c b/src/gallium/drivers/i965/brw_pipe_vertex.c index e3c48e31493..d6a840857ec 100644 --- a/src/gallium/drivers/i965/brw_pipe_vertex.c +++ b/src/gallium/drivers/i965/brw_pipe_vertex.c @@ -1,22 +1,251 @@ #include "brw_context.h" +#include "brw_defines.h" +#include "brw_structs.h" +#include "util/u_memory.h" +#include "util/u_format.h" -static void brw_set_vertex_elements( struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements ) + +static unsigned brw_translate_surface_format( unsigned id ) +{ + switch (id) { + case PIPE_FORMAT_R64_FLOAT: + return BRW_SURFACEFORMAT_R64_FLOAT; + case PIPE_FORMAT_R64G64_FLOAT: + return BRW_SURFACEFORMAT_R64G64_FLOAT; + case PIPE_FORMAT_R64G64B64_FLOAT: + return BRW_SURFACEFORMAT_R64G64B64_FLOAT; + case PIPE_FORMAT_R64G64B64A64_FLOAT: + return BRW_SURFACEFORMAT_R64G64B64A64_FLOAT; + + case PIPE_FORMAT_R32_FLOAT: + return BRW_SURFACEFORMAT_R32_FLOAT; + case PIPE_FORMAT_R32G32_FLOAT: + return BRW_SURFACEFORMAT_R32G32_FLOAT; + case PIPE_FORMAT_R32G32B32_FLOAT: + return BRW_SURFACEFORMAT_R32G32B32_FLOAT; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + + case PIPE_FORMAT_R32_UNORM: + return BRW_SURFACEFORMAT_R32_UNORM; + case PIPE_FORMAT_R32G32_UNORM: + return BRW_SURFACEFORMAT_R32G32_UNORM; + case PIPE_FORMAT_R32G32B32_UNORM: + return BRW_SURFACEFORMAT_R32G32B32_UNORM; + case PIPE_FORMAT_R32G32B32A32_UNORM: + return BRW_SURFACEFORMAT_R32G32B32A32_UNORM; + + case PIPE_FORMAT_R32_USCALED: + return BRW_SURFACEFORMAT_R32_USCALED; + case PIPE_FORMAT_R32G32_USCALED: + return BRW_SURFACEFORMAT_R32G32_USCALED; + case PIPE_FORMAT_R32G32B32_USCALED: + return BRW_SURFACEFORMAT_R32G32B32_USCALED; + case PIPE_FORMAT_R32G32B32A32_USCALED: + return BRW_SURFACEFORMAT_R32G32B32A32_USCALED; + + case PIPE_FORMAT_R32_SNORM: + return BRW_SURFACEFORMAT_R32_SNORM; + case PIPE_FORMAT_R32G32_SNORM: + return BRW_SURFACEFORMAT_R32G32_SNORM; + case PIPE_FORMAT_R32G32B32_SNORM: + return BRW_SURFACEFORMAT_R32G32B32_SNORM; + case PIPE_FORMAT_R32G32B32A32_SNORM: + return BRW_SURFACEFORMAT_R32G32B32A32_SNORM; + + case PIPE_FORMAT_R32_SSCALED: + return BRW_SURFACEFORMAT_R32_SSCALED; + case PIPE_FORMAT_R32G32_SSCALED: + return BRW_SURFACEFORMAT_R32G32_SSCALED; + case PIPE_FORMAT_R32G32B32_SSCALED: + return BRW_SURFACEFORMAT_R32G32B32_SSCALED; + case PIPE_FORMAT_R32G32B32A32_SSCALED: + return BRW_SURFACEFORMAT_R32G32B32A32_SSCALED; + + case PIPE_FORMAT_R16_UNORM: + return BRW_SURFACEFORMAT_R16_UNORM; + case PIPE_FORMAT_R16G16_UNORM: + return BRW_SURFACEFORMAT_R16G16_UNORM; + case PIPE_FORMAT_R16G16B16_UNORM: + return BRW_SURFACEFORMAT_R16G16B16_UNORM; + case PIPE_FORMAT_R16G16B16A16_UNORM: + return BRW_SURFACEFORMAT_R16G16B16A16_UNORM; + + case PIPE_FORMAT_R16_USCALED: + return BRW_SURFACEFORMAT_R16_USCALED; + case PIPE_FORMAT_R16G16_USCALED: + return BRW_SURFACEFORMAT_R16G16_USCALED; + case PIPE_FORMAT_R16G16B16_USCALED: + return BRW_SURFACEFORMAT_R16G16B16_USCALED; + case PIPE_FORMAT_R16G16B16A16_USCALED: + return BRW_SURFACEFORMAT_R16G16B16A16_USCALED; + + case PIPE_FORMAT_R16_SNORM: + return BRW_SURFACEFORMAT_R16_SNORM; + case PIPE_FORMAT_R16G16_SNORM: + return BRW_SURFACEFORMAT_R16G16_SNORM; + case PIPE_FORMAT_R16G16B16_SNORM: + return BRW_SURFACEFORMAT_R16G16B16_SNORM; + case PIPE_FORMAT_R16G16B16A16_SNORM: + return BRW_SURFACEFORMAT_R16G16B16A16_SNORM; + + case PIPE_FORMAT_R16_SSCALED: + return BRW_SURFACEFORMAT_R16_SSCALED; + case PIPE_FORMAT_R16G16_SSCALED: + return BRW_SURFACEFORMAT_R16G16_SSCALED; + case PIPE_FORMAT_R16G16B16_SSCALED: + return BRW_SURFACEFORMAT_R16G16B16_SSCALED; + case PIPE_FORMAT_R16G16B16A16_SSCALED: + return BRW_SURFACEFORMAT_R16G16B16A16_SSCALED; + + case PIPE_FORMAT_R8_UNORM: + return BRW_SURFACEFORMAT_R8_UNORM; + case PIPE_FORMAT_R8G8_UNORM: + return BRW_SURFACEFORMAT_R8G8_UNORM; + case PIPE_FORMAT_R8G8B8_UNORM: + return BRW_SURFACEFORMAT_R8G8B8_UNORM; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return BRW_SURFACEFORMAT_R8G8B8A8_UNORM; + + case PIPE_FORMAT_R8_USCALED: + return BRW_SURFACEFORMAT_R8_USCALED; + case PIPE_FORMAT_R8G8_USCALED: + return BRW_SURFACEFORMAT_R8G8_USCALED; + case PIPE_FORMAT_R8G8B8_USCALED: + return BRW_SURFACEFORMAT_R8G8B8_USCALED; + case PIPE_FORMAT_R8G8B8A8_USCALED: + return BRW_SURFACEFORMAT_R8G8B8A8_USCALED; + + case PIPE_FORMAT_R8_SNORM: + return BRW_SURFACEFORMAT_R8_SNORM; + case PIPE_FORMAT_R8G8_SNORM: + return BRW_SURFACEFORMAT_R8G8_SNORM; + case PIPE_FORMAT_R8G8B8_SNORM: + return BRW_SURFACEFORMAT_R8G8B8_SNORM; + case PIPE_FORMAT_R8G8B8A8_SNORM: + return BRW_SURFACEFORMAT_R8G8B8A8_SNORM; + + case PIPE_FORMAT_R8_SSCALED: + return BRW_SURFACEFORMAT_R8_SSCALED; + case PIPE_FORMAT_R8G8_SSCALED: + return BRW_SURFACEFORMAT_R8G8_SSCALED; + case PIPE_FORMAT_R8G8B8_SSCALED: + return BRW_SURFACEFORMAT_R8G8B8_SSCALED; + case PIPE_FORMAT_R8G8B8A8_SSCALED: + return BRW_SURFACEFORMAT_R8G8B8A8_SSCALED; + + default: + assert(0); + return 0; + } +} + +static void brw_translate_vertex_elements(struct brw_context *brw, + struct brw_vertex_element_packet *brw_velems, + const struct pipe_vertex_element *attribs, + unsigned count) +{ + unsigned i; + + /* If the VS doesn't read any inputs (calculating vertex position from + * a state variable for some reason, for example), emit a single pad + * VERTEX_ELEMENT struct and bail. + * + * The stale VB state stays in place, but they don't do anything unless + * a VE loads from them. + */ + brw_velems->header.opcode = CMD_VERTEX_ELEMENT; + + if (count == 0) { + brw_velems->header.length = 1; + brw_velems->ve[0].ve0.src_offset = 0; + brw_velems->ve[0].ve0.src_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + brw_velems->ve[0].ve0.valid = 1; + brw_velems->ve[0].ve0.vertex_buffer_index = 0; + brw_velems->ve[0].ve1.dst_offset = 0; + brw_velems->ve[0].ve1.vfcomponent0 = BRW_VE1_COMPONENT_STORE_0; + brw_velems->ve[0].ve1.vfcomponent1 = BRW_VE1_COMPONENT_STORE_0; + brw_velems->ve[0].ve1.vfcomponent2 = BRW_VE1_COMPONENT_STORE_0; + brw_velems->ve[0].ve1.vfcomponent3 = BRW_VE1_COMPONENT_STORE_1_FLT; + return; + } + + + /* Now emit vertex element (VEP) state packets. + * + */ + brw_velems->header.length = (1 + count * 2) - 2; + for (i = 0; i < count; i++) { + const struct pipe_vertex_element *input = &attribs[i]; + unsigned nr_components = util_format_get_nr_components(input->src_format); + + uint32_t format = brw_translate_surface_format( input->src_format ); + uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC; + uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC; + uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC; + uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC; + + switch (nr_components) { + case 0: comp0 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ + case 1: comp1 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ + case 2: comp2 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ + case 3: comp3 = BRW_VE1_COMPONENT_STORE_1_FLT; + break; + } + + brw_velems->ve[i].ve0.src_offset = input->src_offset; + brw_velems->ve[i].ve0.src_format = format; + brw_velems->ve[i].ve0.valid = 1; + brw_velems->ve[i].ve0.vertex_buffer_index = input->vertex_buffer_index; + brw_velems->ve[i].ve1.vfcomponent0 = comp0; + brw_velems->ve[i].ve1.vfcomponent1 = comp1; + brw_velems->ve[i].ve1.vfcomponent2 = comp2; + brw_velems->ve[i].ve1.vfcomponent3 = comp3; + + if (BRW_IS_IGDNG(brw)) + brw_velems->ve[i].ve1.dst_offset = 0; + else + brw_velems->ve[i].ve1.dst_offset = i * 4; + } +} + +static void* brw_create_vertex_elements_state( struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs ) { + /* note: for the brw_swtnl.c code (if ever we need draw fallback) we'd also need + to store the original data */ struct brw_context *brw = brw_context(pipe); + struct brw_vertex_element_packet *velems; + assert(count <= BRW_VEP_MAX); + velems = (struct brw_vertex_element_packet *) MALLOC(sizeof(struct brw_vertex_element_packet)); + if (velems) { + brw_translate_vertex_elements(brw, velems, attribs, count); + } + return velems; +} - memcpy(brw->curr.vertex_element, elements, count * sizeof(elements[0])); - brw->curr.num_vertex_elements = count; +static void brw_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + struct brw_context *brw = brw_context(pipe); + struct brw_vertex_element_packet *brw_velems = (struct brw_vertex_element_packet *) velems; + + brw->curr.velems = brw_velems; brw->state.dirty.mesa |= PIPE_NEW_VERTEX_ELEMENT; } +static void brw_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} + static void brw_set_vertex_buffers(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_buffer *buffers) + unsigned count, + const struct pipe_vertex_buffer *buffers) { struct brw_context *brw = brw_context(pipe); unsigned i; @@ -49,7 +278,9 @@ void brw_pipe_vertex_init( struct brw_context *brw ) { brw->base.set_vertex_buffers = brw_set_vertex_buffers; - brw->base.set_vertex_elements = brw_set_vertex_elements; + brw->base.create_vertex_elements_state = brw_create_vertex_elements_state; + brw->base.bind_vertex_elements_state = brw_bind_vertex_elements_state; + brw->base.delete_vertex_elements_state = brw_delete_vertex_elements_state; } diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c index 66f3aad8b21..cef83ffea80 100644 --- a/src/gallium/drivers/i965/brw_screen.c +++ b/src/gallium/drivers/i965/brw_screen.c @@ -174,11 +174,11 @@ brw_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 11; /* max 1024x1024 */ + return BRW_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 8; /* max 128x128x128 */ + return BRW_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 11; /* max 1024x1024 */ + return BRW_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; diff --git a/src/gallium/drivers/i965/brw_screen.h b/src/gallium/drivers/i965/brw_screen.h index 7226d9228b7..e3a7c64d489 100644 --- a/src/gallium/drivers/i965/brw_screen.h +++ b/src/gallium/drivers/i965/brw_screen.h @@ -100,6 +100,9 @@ struct brw_surface }; +#define BRW_MAX_TEXTURE_2D_LEVELS 11 /* max 1024x1024 */ +#define BRW_MAX_TEXTURE_3D_LEVELS 8 /* max 128x128x128 */ + struct brw_texture { @@ -107,9 +110,9 @@ struct brw_texture struct brw_winsys_buffer *bo; struct brw_surface_state ss; - unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; - unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS]; - unsigned level_offset[PIPE_MAX_TEXTURE_LEVELS]; + unsigned *image_offset[BRW_MAX_TEXTURE_2D_LEVELS]; + unsigned nr_images[BRW_MAX_TEXTURE_2D_LEVELS]; + unsigned level_offset[BRW_MAX_TEXTURE_2D_LEVELS]; boolean compressed; unsigned brw_target; @@ -178,6 +181,10 @@ void brw_update_texture( struct brw_screen *brw_screen, struct brw_texture *tex ); +/* brw_screen_texture.h + */ +struct brw_context; +void brw_tex_init( struct brw_context *brw ); void brw_screen_tex_init( struct brw_screen *brw_screen ); void brw_screen_tex_surface_init( struct brw_screen *brw_screen ); diff --git a/src/gallium/drivers/i965/brw_screen_texture.c b/src/gallium/drivers/i965/brw_screen_texture.c index e38fdf1869b..cadcb7cee2a 100644 --- a/src/gallium/drivers/i965/brw_screen_texture.c +++ b/src/gallium/drivers/i965/brw_screen_texture.c @@ -37,6 +37,8 @@ #include "brw_defines.h" #include "brw_structs.h" #include "brw_winsys.h" +#include "brw_context.h" + @@ -231,8 +233,8 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen, goto fail; - if (templ->tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) { + if (templ->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { buffer_type = BRW_BUFFER_TYPE_SCANOUT; } else { @@ -303,14 +305,121 @@ fail: return NULL; } -static struct pipe_texture *brw_texture_blanket(struct pipe_screen *screen, - const struct pipe_texture *templ, - const unsigned *stride, - struct pipe_buffer *buffer) +static struct pipe_texture * +brw_texture_from_handle(struct pipe_screen *screen, + const struct pipe_texture *templ, + struct winsys_handle *whandle) { + struct brw_screen *bscreen = brw_screen(screen); + struct brw_texture *tex; + struct brw_winsys_buffer *buffer; + unsigned tiling; + unsigned pitch; + + if (templ->target != PIPE_TEXTURE_2D || + templ->last_level != 0 || + templ->depth0 != 1) + return NULL; + + if (util_format_is_compressed(templ->format)) + return NULL; + + tex = CALLOC_STRUCT(brw_texture); + if (!tex) + return NULL; + + if (bscreen->sws->bo_from_handle(bscreen->sws, whandle, &pitch, &tiling, &buffer) != PIPE_OK) + goto fail; + + memcpy(&tex->base, templ, sizeof *templ); + pipe_reference_init(&tex->base.reference, 1); + tex->base.screen = screen; + + /* XXX: cpp vs. blocksize + */ + tex->cpp = util_format_get_blocksize(tex->base.format); + tex->tiling = tiling; + + make_empty_list(&tex->views[0]); + make_empty_list(&tex->views[1]); + + if (!brw_texture_layout(bscreen, tex)) + goto fail; + + /* XXX Maybe some more checks? */ + if ((pitch / tex->cpp) < tex->pitch) + goto fail; + + tex->pitch = pitch / tex->cpp; + + tex->bo = buffer; + + /* fix this warning */ +#if 0 + if (tex->size > buffer->size) + goto fail; +#endif + + tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + tex->ss.ss0.surface_type = translate_tex_target(tex->base.target); + tex->ss.ss0.surface_format = translate_tex_format(tex->base.format); + assert(tex->ss.ss0.surface_format != BRW_SURFACEFORMAT_INVALID); + + /* This is ok for all textures with channel width 8bit or less: + */ +/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ + + + /* XXX: what happens when tex->bo->offset changes??? + */ + tex->ss.ss1.base_addr = 0; /* reloc */ + tex->ss.ss2.mip_count = tex->base.last_level; + tex->ss.ss2.width = tex->base.width0 - 1; + tex->ss.ss2.height = tex->base.height0 - 1; + + switch (tex->tiling) { + case BRW_TILING_NONE: + tex->ss.ss3.tiled_surface = 0; + tex->ss.ss3.tile_walk = 0; + break; + case BRW_TILING_X: + tex->ss.ss3.tiled_surface = 1; + tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR; + break; + case BRW_TILING_Y: + tex->ss.ss3.tiled_surface = 1; + tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR; + break; + } + + tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1; + tex->ss.ss3.depth = tex->base.depth0 - 1; + + tex->ss.ss4.min_lod = 0; + + return &tex->base; + +fail: + FREE(tex); return NULL; } +static boolean +brw_texture_get_handle(struct pipe_screen *screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct brw_screen *bscreen = brw_screen(screen); + struct brw_texture *tex = brw_texture(texture); + unsigned stride; + + stride = tex->pitch * tex->cpp; + + return bscreen->sws->bo_get_handle(tex->bo, whandle, stride); +} + + + static void brw_texture_destroy(struct pipe_texture *pt) { struct brw_texture *tex = brw_texture(pt); @@ -372,7 +481,7 @@ boolean brw_is_texture_referenced_by_bo( struct brw_screen *brw_screen, */ static struct pipe_transfer* -brw_get_tex_transfer(struct pipe_screen *screen, +brw_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, @@ -407,11 +516,11 @@ brw_get_tex_transfer(struct pipe_screen *screen, } static void * -brw_transfer_map(struct pipe_screen *screen, +brw_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct brw_texture *tex = brw_texture(transfer->texture); - struct brw_winsys_screen *sws = brw_screen(screen)->sws; + struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws; char *map; unsigned usage = transfer->usage; @@ -434,146 +543,37 @@ brw_transfer_map(struct pipe_screen *screen, } static void -brw_transfer_unmap(struct pipe_screen *screen, +brw_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct brw_texture *tex = brw_texture(transfer->texture); - struct brw_winsys_screen *sws = brw_screen(screen)->sws; + struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws; sws->bo_unmap(tex->bo); } static void -brw_tex_transfer_destroy(struct pipe_transfer *trans) +brw_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *trans) { pipe_texture_reference(&trans->texture, NULL); FREE(trans); } -/* - * Functions exported to the winsys - */ - -boolean brw_texture_get_winsys_buffer(struct pipe_texture *texture, - struct brw_winsys_buffer **buffer, - unsigned *stride) -{ - struct brw_texture *tex = brw_texture(texture); - - *buffer = tex->bo; - if (stride) - *stride = tex->pitch * tex->cpp; - - return TRUE; -} - -struct pipe_texture * -brw_texture_blanket_winsys_buffer(struct pipe_screen *screen, - const struct pipe_texture *templ, - unsigned pitch, - unsigned tiling, - struct brw_winsys_buffer *buffer) +void brw_tex_init( struct brw_context *brw ) { - struct brw_screen *bscreen = brw_screen(screen); - struct brw_texture *tex; - GLuint format; - - if (templ->target != PIPE_TEXTURE_2D || - templ->last_level != 0 || - templ->depth0 != 1) - return NULL; - - if (util_format_is_compressed(templ->format)) - return NULL; - - tex = CALLOC_STRUCT(brw_texture); - if (!tex) - return NULL; - - memcpy(&tex->base, templ, sizeof *templ); - pipe_reference_init(&tex->base.reference, 1); - tex->base.screen = screen; - - /* XXX: cpp vs. blocksize - */ - tex->cpp = util_format_get_blocksize(tex->base.format); - tex->tiling = tiling; - - make_empty_list(&tex->views[0]); - make_empty_list(&tex->views[1]); - - if (!brw_texture_layout(bscreen, tex)) - goto fail; - - /* XXX Maybe some more checks? */ - if ((pitch / tex->cpp) < tex->pitch) - goto fail; - - tex->pitch = pitch / tex->cpp; - - tex->bo = buffer; - - /* fix this warning */ -#if 0 - if (tex->size > buffer->size) - goto fail; -#endif - - tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - tex->ss.ss0.surface_type = translate_tex_target(tex->base.target); - - format = translate_tex_format(tex->base.format); - assert(format != BRW_SURFACEFORMAT_INVALID); - tex->ss.ss0.surface_format = format; - - /* This is ok for all textures with channel width 8bit or less: - */ -/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ - - - /* XXX: what happens when tex->bo->offset changes??? - */ - tex->ss.ss1.base_addr = 0; /* reloc */ - tex->ss.ss2.mip_count = tex->base.last_level; - tex->ss.ss2.width = tex->base.width0 - 1; - tex->ss.ss2.height = tex->base.height0 - 1; - - switch (tex->tiling) { - case BRW_TILING_NONE: - tex->ss.ss3.tiled_surface = 0; - tex->ss.ss3.tile_walk = 0; - break; - case BRW_TILING_X: - tex->ss.ss3.tiled_surface = 1; - tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR; - break; - case BRW_TILING_Y: - tex->ss.ss3.tiled_surface = 1; - tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR; - break; - } - - tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1; - tex->ss.ss3.depth = tex->base.depth0 - 1; - - tex->ss.ss4.min_lod = 0; - - return &tex->base; - -fail: - FREE(tex); - return NULL; + brw->base.get_tex_transfer = brw_get_tex_transfer; + brw->base.transfer_map = brw_transfer_map; + brw->base.transfer_unmap = brw_transfer_unmap; + brw->base.tex_transfer_destroy = brw_tex_transfer_destroy; } void brw_screen_tex_init( struct brw_screen *brw_screen ) { brw_screen->base.is_format_supported = brw_is_format_supported; brw_screen->base.texture_create = brw_texture_create; + brw_screen->base.texture_from_handle = brw_texture_from_handle; + brw_screen->base.texture_get_handle = brw_texture_get_handle; brw_screen->base.texture_destroy = brw_texture_destroy; - brw_screen->base.texture_blanket = brw_texture_blanket; - brw_screen->base.get_tex_transfer = brw_get_tex_transfer; - brw_screen->base.transfer_map = brw_transfer_map; - brw_screen->base.transfer_unmap = brw_transfer_unmap; - brw_screen->base.tex_transfer_destroy = brw_tex_transfer_destroy; } diff --git a/src/gallium/drivers/i965/brw_structs.h b/src/gallium/drivers/i965/brw_structs.h index bf10bc04de7..e97ddeb5e1c 100644 --- a/src/gallium/drivers/i965/brw_structs.h +++ b/src/gallium/drivers/i965/brw_structs.h @@ -28,7 +28,7 @@ * Authors: * Keith Whitwell <[email protected]> */ - + #ifndef BRW_STRUCTS_H #define BRW_STRUCTS_H @@ -1149,7 +1149,7 @@ struct brw_vertex_element_state GLuint valid:1; GLuint vertex_buffer_index:5; } ve0; - + struct { GLuint dst_offset:8; diff --git a/src/gallium/drivers/i965/brw_winsys.h b/src/gallium/drivers/i965/brw_winsys.h index c82d00f4a47..f30c7f18132 100644 --- a/src/gallium/drivers/i965/brw_winsys.h +++ b/src/gallium/drivers/i965/brw_winsys.h @@ -162,6 +162,16 @@ struct brw_winsys_screen { unsigned alignment, struct brw_winsys_buffer **bo_out); + enum pipe_error (*bo_from_handle)(struct brw_winsys_screen *sws, + struct winsys_handle *whandle, + unsigned *stride, + unsigned *tiling, + struct brw_winsys_buffer **bo_out); + + enum pipe_error (*bo_get_handle)(struct brw_winsys_buffer *buffer, + struct winsys_handle *whandle, + unsigned stride); + /* Destroy a buffer when our refcount goes to zero: */ void (*bo_destroy)(struct brw_winsys_buffer *buffer); @@ -257,28 +267,6 @@ bo_reference(struct brw_winsys_buffer **ptr, struct brw_winsys_buffer *buf) struct pipe_screen *brw_create_screen(struct brw_winsys_screen *iws, unsigned pci_id); -/** - * Get the brw_winsys buffer backing the texture. - * - * TODO UGLY - */ -struct pipe_texture; -boolean brw_texture_get_winsys_buffer(struct pipe_texture *texture, - struct brw_winsys_buffer **buffer, - unsigned *stride); - -/** - * Wrap a brw_winsys buffer with a texture blanket. - * - * TODO UGLY - */ -struct pipe_texture * -brw_texture_blanket_winsys_buffer(struct pipe_screen *screen, - const struct pipe_texture *template, - unsigned pitch, - unsigned tiling, - struct brw_winsys_buffer *buffer); - /************************************************************************* * Cooperative dumping between winsys and driver. TODO: make this diff --git a/src/gallium/drivers/i965/brw_wm.c b/src/gallium/drivers/i965/brw_wm.c index dfb718e64fe..7ed2378ec04 100644 --- a/src/gallium/drivers/i965/brw_wm.c +++ b/src/gallium/drivers/i965/brw_wm.c @@ -251,8 +251,8 @@ static void brw_wm_populate_key( struct brw_context *brw, /* PIPE_NEW_BOUND_TEXTURES */ - for (i = 0; i < brw->curr.num_textures; i++) { - const struct brw_texture *tex = brw_texture(brw->curr.texture[i]); + for (i = 0; i < brw->curr.num_fragment_sampler_views; i++) { + const struct brw_texture *tex = brw_texture(brw->curr.fragment_sampler_views[i]->texture); if (tex->base.format == PIPE_FORMAT_UYVY) key->yuvtex_mask |= 1 << i; diff --git a/src/gallium/drivers/i965/brw_wm_sampler_state.c b/src/gallium/drivers/i965/brw_wm_sampler_state.c index 6a6086fc51b..3f18062c584 100644 --- a/src/gallium/drivers/i965/brw_wm_sampler_state.c +++ b/src/gallium/drivers/i965/brw_wm_sampler_state.c @@ -78,11 +78,11 @@ brw_wm_sampler_populate_key(struct brw_context *brw, memset(key, 0, sizeof(*key)); - key->sampler_count = MIN2(brw->curr.num_textures, + key->sampler_count = MIN2(brw->curr.num_fragment_sampler_views, brw->curr.num_samplers); for (i = 0; i < key->sampler_count; i++) { - const struct brw_texture *tex = brw_texture(brw->curr.texture[i]); + const struct brw_texture *tex = brw_texture(brw->curr.fragment_sampler_views[i]->texture); const struct brw_sampler *sampler = brw->curr.sampler[i]; struct brw_sampler_state *entry = &key->sampler[i]; @@ -122,12 +122,12 @@ static enum pipe_error brw_wm_sampler_update_default_colors(struct brw_context *brw) { enum pipe_error ret; - int nr = MIN2(brw->curr.num_textures, + int nr = MIN2(brw->curr.num_fragment_sampler_views, brw->curr.num_samplers); int i; for (i = 0; i < nr; i++) { - const struct brw_texture *tex = brw_texture(brw->curr.texture[i]); + const struct brw_texture *tex = brw_texture(brw->curr.fragment_sampler_views[i]->texture); const struct brw_sampler *sampler = brw->curr.sampler[i]; const float *bc; float bordercolor[4] = { diff --git a/src/gallium/drivers/i965/brw_wm_surface_state.c b/src/gallium/drivers/i965/brw_wm_surface_state.c index b01a7f194b7..2368ae3f808 100644 --- a/src/gallium/drivers/i965/brw_wm_surface_state.c +++ b/src/gallium/drivers/i965/brw_wm_surface_state.c @@ -242,9 +242,9 @@ static enum pipe_error prepare_wm_surfaces(struct brw_context *brw ) /* PIPE_NEW_TEXTURE */ - for (i = 0; i < brw->curr.num_textures; i++) { + for (i = 0; i < brw->curr.num_fragment_sampler_views; i++) { ret = brw_update_texture_surface(brw, - brw_texture(brw->curr.texture[i]), + brw_texture(brw->curr.fragment_sampler_views[i]->texture), &brw->wm.surf_bo[BTI_TEXTURE(i)]); if (ret) return ret; @@ -261,7 +261,7 @@ static enum pipe_error prepare_wm_surfaces(struct brw_context *brw ) bo_reference(&brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS], NULL); /* XXX: no pipe_max_textures define?? */ - for (i = brw->curr.num_textures; i < PIPE_MAX_SAMPLERS; i++) + for (i = brw->curr.num_fragment_sampler_views; i < PIPE_MAX_SAMPLERS; i++) bo_reference(&brw->wm.surf_bo[BTI_TEXTURE(i)], NULL); if (brw->wm.nr_surfaces != nr_surfaces) { diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index 8248b2a4132..00a542215ad 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -377,6 +377,42 @@ identity_delete_vs_state(struct pipe_context *_pipe, vs); } + +static void * +identity_create_vertex_elements_state(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *vertex_elements) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_vertex_elements_state(pipe, + num_elements, + vertex_elements); +} + +static void +identity_bind_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_vertex_elements_state(pipe, + velems); +} + +static void +identity_delete_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_vertex_elements_state(pipe, + velems); +} + static void identity_set_blend_color(struct pipe_context *_pipe, const struct pipe_blend_color *blend_color) @@ -492,53 +528,49 @@ identity_set_viewport_state(struct pipe_context *_pipe, } static void -identity_set_fragment_sampler_textures(struct pipe_context *_pipe, - unsigned num_textures, - struct pipe_texture **_textures) +identity_set_fragment_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **_views) { struct identity_context *id_pipe = identity_context(_pipe); struct pipe_context *pipe = id_pipe->pipe; - struct pipe_texture *unwrapped_textures[PIPE_MAX_SAMPLERS]; - struct pipe_texture **textures = NULL; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view **views = NULL; unsigned i; - if (_textures) { - for (i = 0; i < num_textures; i++) - unwrapped_textures[i] = identity_texture_unwrap(_textures[i]); + if (_views) { + for (i = 0; i < num; i++) + unwrapped_views[i] = identity_sampler_view_unwrap(_views[i]); for (; i < PIPE_MAX_SAMPLERS; i++) - unwrapped_textures[i] = NULL; + unwrapped_views[i] = NULL; - textures = unwrapped_textures; + views = unwrapped_views; } - pipe->set_fragment_sampler_textures(pipe, - num_textures, - textures); + pipe->set_fragment_sampler_views(pipe, num, views); } static void -identity_set_vertex_sampler_textures(struct pipe_context *_pipe, - unsigned num_textures, - struct pipe_texture **_textures) +identity_set_vertex_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **_views) { struct identity_context *id_pipe = identity_context(_pipe); struct pipe_context *pipe = id_pipe->pipe; - struct pipe_texture *unwrapped_textures[PIPE_MAX_VERTEX_SAMPLERS]; - struct pipe_texture **textures = NULL; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view **views = NULL; unsigned i; - if (_textures) { - for (i = 0; i < num_textures; i++) - unwrapped_textures[i] = identity_texture_unwrap(_textures[i]); + if (_views) { + for (i = 0; i < num; i++) + unwrapped_views[i] = identity_sampler_view_unwrap(_views[i]); for (; i < PIPE_MAX_VERTEX_SAMPLERS; i++) - unwrapped_textures[i] = NULL; + unwrapped_views[i] = NULL; - textures = unwrapped_textures; + views = unwrapped_views; } - pipe->set_vertex_sampler_textures(pipe, - num_textures, - textures); + pipe->set_vertex_sampler_views(pipe, num, views); } static void @@ -563,20 +595,6 @@ identity_set_vertex_buffers(struct pipe_context *_pipe, num_buffers, buffers); } - -static void -identity_set_vertex_elements(struct pipe_context *_pipe, - unsigned num_elements, - const struct pipe_vertex_element *vertex_elements) -{ - struct identity_context *id_pipe = identity_context(_pipe); - struct pipe_context *pipe = id_pipe->pipe; - - pipe->set_vertex_elements(pipe, - num_elements, - vertex_elements); -} - static void identity_surface_copy(struct pipe_context *_pipe, struct pipe_surface *_dst, @@ -689,6 +707,115 @@ identity_is_buffer_referenced(struct pipe_context *_pipe, buffer); } +static struct pipe_sampler_view * +identity_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct identity_context *id_pipe = identity_context(pipe); + struct identity_texture *id_texture = identity_texture(texture); + struct pipe_context *pipe_unwrapped = id_pipe->pipe; + struct pipe_texture *texture_unwrapped = id_texture->texture; + struct identity_sampler_view *view = malloc(sizeof(struct identity_sampler_view)); + + view->sampler_view = pipe_unwrapped->create_sampler_view(pipe_unwrapped, + texture_unwrapped, + templ); + + view->base = *templ; + view->base.reference.count = 1; + view->base.texture = NULL; + pipe_texture_reference(&view->base.texture, texture); + view->base.context = pipe; + + return &view->base; +} + +static void +identity_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + struct identity_context *id_pipe = identity_context(pipe); + struct identity_sampler_view *id_view = identity_sampler_view(view); + struct pipe_context *pipe_unwrapped = id_pipe->pipe; + struct pipe_sampler_view *view_unwrapped = id_view->sampler_view; + + pipe_unwrapped->sampler_view_destroy(pipe_unwrapped, + view_unwrapped); + + pipe_texture_reference(&view->texture, NULL); + free(view); +} + + +static struct pipe_transfer * +identity_context_get_tex_transfer(struct pipe_context *_context, + struct pipe_texture *_texture, + unsigned face, + unsigned level, + unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, + unsigned y, + unsigned w, + unsigned h) +{ + struct identity_context *id_context = identity_context(_context); + struct identity_texture *id_texture = identity_texture(_texture); + struct pipe_context *context = id_context->pipe; + struct pipe_texture *texture = id_texture->texture; + struct pipe_transfer *result; + + result = context->get_tex_transfer(context, + texture, + face, + level, + zslice, + usage, + x, + y, + w, + h); + + if (result) + return identity_transfer_create(id_context, id_texture, result); + return NULL; +} + +static void +identity_context_tex_transfer_destroy(struct pipe_context *_pipe, + struct pipe_transfer *_transfer) +{ + identity_transfer_destroy(identity_context(_pipe), + identity_transfer(_transfer)); +} + +static void * +identity_context_transfer_map(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct identity_context *id_context = identity_context(_context); + struct identity_transfer *id_transfer = identity_transfer(_transfer); + struct pipe_context *context = id_context->pipe; + struct pipe_transfer *transfer = id_transfer->transfer; + + return context->transfer_map(context, + transfer); +} + +static void +identity_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct identity_context *id_context = identity_context(_context); + struct identity_transfer *id_transfer = identity_transfer(_transfer); + struct pipe_context *context = id_context->pipe; + struct pipe_transfer *transfer = id_transfer->transfer; + + context->transfer_unmap(context, + transfer); +} + struct pipe_context * identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) { @@ -733,6 +860,9 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.create_vs_state = identity_create_vs_state; id_pipe->base.bind_vs_state = identity_bind_vs_state; id_pipe->base.delete_vs_state = identity_delete_vs_state; + id_pipe->base.create_vertex_elements_state = identity_create_vertex_elements_state; + id_pipe->base.bind_vertex_elements_state = identity_bind_vertex_elements_state; + id_pipe->base.delete_vertex_elements_state = identity_delete_vertex_elements_state; id_pipe->base.set_blend_color = identity_set_blend_color; id_pipe->base.set_stencil_ref = identity_set_stencil_ref; id_pipe->base.set_clip_state = identity_set_clip_state; @@ -741,16 +871,21 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.set_polygon_stipple = identity_set_polygon_stipple; id_pipe->base.set_scissor_state = identity_set_scissor_state; id_pipe->base.set_viewport_state = identity_set_viewport_state; - id_pipe->base.set_fragment_sampler_textures = identity_set_fragment_sampler_textures; - id_pipe->base.set_vertex_sampler_textures = identity_set_vertex_sampler_textures; + id_pipe->base.set_fragment_sampler_views = identity_set_fragment_sampler_views; + id_pipe->base.set_vertex_sampler_views = identity_set_vertex_sampler_views; id_pipe->base.set_vertex_buffers = identity_set_vertex_buffers; - id_pipe->base.set_vertex_elements = identity_set_vertex_elements; id_pipe->base.surface_copy = identity_surface_copy; id_pipe->base.surface_fill = identity_surface_fill; id_pipe->base.clear = identity_clear; id_pipe->base.flush = identity_flush; id_pipe->base.is_texture_referenced = identity_is_texture_referenced; id_pipe->base.is_buffer_referenced = identity_is_buffer_referenced; + id_pipe->base.create_sampler_view = identity_create_sampler_view; + id_pipe->base.sampler_view_destroy = identity_sampler_view_destroy; + id_pipe->base.get_tex_transfer = identity_context_get_tex_transfer; + id_pipe->base.tex_transfer_destroy = identity_context_tex_transfer_destroy; + id_pipe->base.transfer_map = identity_context_transfer_map; + id_pipe->base.transfer_unmap = identity_context_transfer_unmap; id_pipe->pipe = pipe; diff --git a/src/gallium/drivers/identity/id_drm.c b/src/gallium/drivers/identity/id_drm.c index f258c38cd71..936ccc444a8 100644 --- a/src/gallium/drivers/identity/id_drm.c +++ b/src/gallium/drivers/identity/id_drm.c @@ -63,62 +63,6 @@ identity_drm_create_screen(struct drm_api *_api, int fd, return identity_screen_create(screen); } - -static struct pipe_texture * -identity_drm_texture_from_shared_handle(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *templ, - const char *name, - unsigned stride, - unsigned handle) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_drm_api *id_api = identity_drm_api(_api); - struct pipe_screen *screen = id_screen->screen; - struct drm_api *api = id_api->api; - struct pipe_texture *result; - - result = api->texture_from_shared_handle(api, screen, templ, name, stride, handle); - - result = identity_texture_create(identity_screen(_screen), result); - - return result; -} - -static boolean -identity_drm_shared_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_texture *id_texture = identity_texture(_texture); - struct identity_drm_api *id_api = identity_drm_api(_api); - struct pipe_screen *screen = id_screen->screen; - struct pipe_texture *texture = id_texture->texture; - struct drm_api *api = id_api->api; - - return api->shared_handle_from_texture(api, screen, texture, stride, handle); -} - -static boolean -identity_drm_local_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_texture *id_texture = identity_texture(_texture); - struct identity_drm_api *id_api = identity_drm_api(_api); - struct pipe_screen *screen = id_screen->screen; - struct pipe_texture *texture = id_texture->texture; - struct drm_api *api = id_api->api; - - return api->local_handle_from_texture(api, screen, texture, stride, handle); -} - static void identity_drm_destroy(struct drm_api *_api) { @@ -145,9 +89,6 @@ identity_drm_create(struct drm_api *api) id_api->base.name = api->name; id_api->base.driver_name = api->driver_name; id_api->base.create_screen = identity_drm_create_screen; - id_api->base.texture_from_shared_handle = identity_drm_texture_from_shared_handle; - id_api->base.shared_handle_from_texture = identity_drm_shared_handle_from_texture; - id_api->base.local_handle_from_texture = identity_drm_local_handle_from_texture; id_api->base.destroy = identity_drm_destroy; id_api->api = api; diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c index 2b1a60c1bf1..d37fb0042e5 100644 --- a/src/gallium/drivers/identity/id_objects.c +++ b/src/gallium/drivers/identity/id_objects.c @@ -30,6 +30,7 @@ #include "id_screen.h" #include "id_objects.h" +#include "id_context.h" struct pipe_buffer * identity_buffer_create(struct identity_screen *id_screen, @@ -142,7 +143,8 @@ identity_surface_destroy(struct identity_surface *id_surface) struct pipe_transfer * -identity_transfer_create(struct identity_texture *id_texture, +identity_transfer_create(struct identity_context *id_context, + struct identity_texture *id_texture, struct pipe_transfer *transfer) { struct identity_transfer *id_transfer; @@ -159,25 +161,25 @@ identity_transfer_create(struct identity_texture *id_texture, memcpy(&id_transfer->base, transfer, sizeof(struct pipe_transfer)); id_transfer->base.texture = NULL; - pipe_texture_reference(&id_transfer->base.texture, &id_texture->base); id_transfer->transfer = transfer; + + pipe_texture_reference(&id_transfer->base.texture, &id_texture->base); assert(id_transfer->base.texture == &id_texture->base); return &id_transfer->base; error: - transfer->texture->screen->tex_transfer_destroy(transfer); + id_context->pipe->tex_transfer_destroy(id_context->pipe, transfer); return NULL; } void -identity_transfer_destroy(struct identity_transfer *id_transfer) +identity_transfer_destroy(struct identity_context *id_context, + struct identity_transfer *id_transfer) { - struct identity_screen *id_screen = identity_screen(id_transfer->base.texture->screen); - struct pipe_screen *screen = id_screen->screen; - pipe_texture_reference(&id_transfer->base.texture, NULL); - screen->tex_transfer_destroy(id_transfer->transfer); + id_context->pipe->tex_transfer_destroy(id_context->pipe, + id_transfer->transfer); FREE(id_transfer); } diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h index 77cc7190798..9a07ebe8d72 100644 --- a/src/gallium/drivers/identity/id_objects.h +++ b/src/gallium/drivers/identity/id_objects.h @@ -35,6 +35,7 @@ #include "id_screen.h" +struct identity_context; struct identity_buffer { @@ -52,6 +53,14 @@ struct identity_texture }; +struct identity_sampler_view +{ + struct pipe_sampler_view base; + + struct pipe_sampler_view *sampler_view; +}; + + struct identity_surface { struct pipe_surface base; @@ -64,6 +73,7 @@ struct identity_transfer { struct pipe_transfer base; + struct pipe_context *pipe; struct pipe_transfer *transfer; }; @@ -94,6 +104,15 @@ identity_texture(struct pipe_texture *_texture) return (struct identity_texture *)_texture; } +static INLINE struct identity_sampler_view * +identity_sampler_view(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) { + return NULL; + } + return (struct identity_sampler_view *)_sampler_view; +} + static INLINE struct identity_surface * identity_surface(struct pipe_surface *_surface) { @@ -138,6 +157,15 @@ identity_texture_unwrap(struct pipe_texture *_texture) return identity_texture(_texture)->texture; } +static INLINE struct pipe_sampler_view * +identity_sampler_view_unwrap(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) { + return NULL; + } + return identity_sampler_view(_sampler_view)->sampler_view; +} + static INLINE struct pipe_surface * identity_surface_unwrap(struct pipe_surface *_surface) { @@ -177,11 +205,13 @@ void identity_surface_destroy(struct identity_surface *id_surface); struct pipe_transfer * -identity_transfer_create(struct identity_texture *id_texture, +identity_transfer_create(struct identity_context *id_context, + struct identity_texture *id_texture, struct pipe_transfer *transfer); void -identity_transfer_destroy(struct identity_transfer *id_transfer); +identity_transfer_destroy(struct identity_context *id_context, + struct identity_transfer *id_transfer); struct pipe_video_surface * identity_video_surface_create(struct identity_screen *id_screen, diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c index b85492114a3..419b1465787 100644 --- a/src/gallium/drivers/identity/id_screen.c +++ b/src/gallium/drivers/identity/id_screen.c @@ -135,27 +135,40 @@ identity_screen_texture_create(struct pipe_screen *_screen, } static struct pipe_texture * -identity_screen_texture_blanket(struct pipe_screen *_screen, - const struct pipe_texture *templat, - const unsigned *stride, - struct pipe_buffer *_buffer) +identity_screen_texture_from_handle(struct pipe_screen *_screen, + const struct pipe_texture *templ, + struct winsys_handle *handle) { struct identity_screen *id_screen = identity_screen(_screen); - struct identity_buffer *id_buffer = identity_buffer(_buffer); struct pipe_screen *screen = id_screen->screen; - struct pipe_buffer *buffer = id_buffer->buffer; struct pipe_texture *result; - result = screen->texture_blanket(screen, - templat, - stride, - buffer); + /* TODO trace call */ - if (result) - return identity_texture_create(id_screen, result); - return NULL; + result = screen->texture_from_handle(screen, templ, handle); + + result = identity_texture_create(identity_screen(_screen), result); + + return result; } +static boolean +identity_screen_texture_get_handle(struct pipe_screen *_screen, + struct pipe_texture *_texture, + struct winsys_handle *handle) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_texture *id_texture = identity_texture(_texture); + struct pipe_screen *screen = id_screen->screen; + struct pipe_texture *texture = id_texture->texture; + + /* TODO trace call */ + + return screen->texture_get_handle(screen, texture, handle); +} + + + static void identity_screen_texture_destroy(struct pipe_texture *_texture) { @@ -194,71 +207,6 @@ identity_screen_tex_surface_destroy(struct pipe_surface *_surface) identity_surface_destroy(identity_surface(_surface)); } -static struct pipe_transfer * -identity_screen_get_tex_transfer(struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned face, - unsigned level, - unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, - unsigned y, - unsigned w, - unsigned h) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_texture *id_texture = identity_texture(_texture); - struct pipe_screen *screen = id_screen->screen; - struct pipe_texture *texture = id_texture->texture; - struct pipe_transfer *result; - - result = screen->get_tex_transfer(screen, - texture, - face, - level, - zslice, - usage, - x, - y, - w, - h); - - if (result) - return identity_transfer_create(id_texture, result); - return NULL; -} - -static void -identity_screen_tex_transfer_destroy(struct pipe_transfer *_transfer) -{ - identity_transfer_destroy(identity_transfer(_transfer)); -} - -static void * -identity_screen_transfer_map(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_transfer *id_transfer = identity_transfer(_transfer); - struct pipe_screen *screen = id_screen->screen; - struct pipe_transfer *transfer = id_transfer->transfer; - - return screen->transfer_map(screen, - transfer); -} - -static void -identity_screen_transfer_unmap(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_transfer *id_transfer = identity_transfer(_transfer); - struct pipe_screen *screen = id_screen->screen; - struct pipe_transfer *transfer = id_transfer->transfer; - - screen->transfer_unmap(screen, - transfer); -} static struct pipe_buffer * identity_screen_buffer_create(struct pipe_screen *_screen, @@ -298,31 +246,6 @@ identity_screen_user_buffer_create(struct pipe_screen *_screen, return NULL; } -static struct pipe_buffer * -identity_screen_surface_buffer_create(struct pipe_screen *_screen, - unsigned width, - unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct pipe_screen *screen = id_screen->screen; - struct pipe_buffer *result; - - result = screen->surface_buffer_create(screen, - width, - height, - format, - usage, - tex_usage, - stride); - - if (result) - return identity_buffer_create(id_screen, result); - return NULL; -} static void * identity_screen_buffer_map(struct pipe_screen *_screen, @@ -495,17 +418,13 @@ identity_screen_create(struct pipe_screen *screen) id_screen->base.is_format_supported = identity_screen_is_format_supported; id_screen->base.context_create = identity_screen_context_create; id_screen->base.texture_create = identity_screen_texture_create; - id_screen->base.texture_blanket = identity_screen_texture_blanket; + id_screen->base.texture_from_handle = identity_screen_texture_from_handle; + id_screen->base.texture_get_handle = identity_screen_texture_get_handle; id_screen->base.texture_destroy = identity_screen_texture_destroy; id_screen->base.get_tex_surface = identity_screen_get_tex_surface; id_screen->base.tex_surface_destroy = identity_screen_tex_surface_destroy; - id_screen->base.get_tex_transfer = identity_screen_get_tex_transfer; - id_screen->base.tex_transfer_destroy = identity_screen_tex_transfer_destroy; - id_screen->base.transfer_map = identity_screen_transfer_map; - id_screen->base.transfer_unmap = identity_screen_transfer_unmap; id_screen->base.buffer_create = identity_screen_buffer_create; id_screen->base.user_buffer_create = identity_screen_user_buffer_create; - id_screen->base.surface_buffer_create = identity_screen_surface_buffer_create; if (screen->buffer_map) id_screen->base.buffer_map = identity_screen_buffer_map; if (screen->buffer_map_range) diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile index 41ac1cee72d..89c06ea3ad7 100644 --- a/src/gallium/drivers/llvmpipe/Makefile +++ b/src/gallium/drivers/llvmpipe/Makefile @@ -55,7 +55,7 @@ testprogs := lp_test_format \ LIBS += $(GL_LIB_DEPS) -L. -lllvmpipe -L../../auxiliary/ -lgallium -$(testprogs): lp_test_% : lp_test_%.o lp_test_main.o libllvmpipe.a - $(LD) $(filter %.o,$^) -o $@ -Wl,--start-group $(LIBS) -Wl,--end-group +#$(testprogs): lp_test_% : lp_test_%.o lp_test_main.o libllvmpipe.a +# $(LD) $(filter %.o,$^) -o $@ -Wl,--start-group $(LIBS) -Wl,--end-group -default: $(testprogs) +#default: $(testprogs) diff --git a/src/gallium/drivers/llvmpipe/README b/src/gallium/drivers/llvmpipe/README index bf4c9a5727c..3c3fd386b52 100644 --- a/src/gallium/drivers/llvmpipe/README +++ b/src/gallium/drivers/llvmpipe/README @@ -12,7 +12,11 @@ Done so far is: - depth testing - - texture sampling (not all state/formats are supported) + - texture sampling + - 1D/2D/3D/cube maps supported + - all texture wrap modes supported + - all texture filtering modes supported + - perhaps not all texture formats yet supported - fragment shader TGSI translation - same level of support as the TGSI SSE2 exec machine, with the exception @@ -37,8 +41,6 @@ To do (probably by this order): - code generate stipple and stencil testing - - translate the remaining bits of texture sampling state - - translate TGSI control flow instructions, and all other remaining opcodes - integrate with the draw module for VS code generation @@ -57,7 +59,7 @@ Requirements See /proc/cpuinfo to know what your CPU supports. - - LLVM 2.6. + - LLVM 2.6 (or later) For Linux, on a recent Debian based distribution do: @@ -67,6 +69,9 @@ Requirements http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment variable to the extracted path. + The version of LLVM from SVN ("2.7svn") from mid-March 2010 seems pretty + stable and has some features not in version 2.6. + - scons (optional) - udis86, http://udis86.sourceforge.net/ (optional): @@ -140,11 +145,13 @@ Development Notes then skim through the lp_bld_* functions called in there, and the comments at the top of the lp_bld_*.c functions. -- All lp_bld_*.[ch] are isolated from the rest of the driver, and could/may be - put in a stand-alone Gallium state -> LLVM IR translation module. +- The driver-independent parts of the LLVM / Gallium code are found in + src/gallium/auxiliary/gallivm/. The filenames and function prefixes + need to be renamed from "lp_bld_" to something else though. - We use LLVM-C bindings for now. They are not documented, but follow the C++ interfaces very closely, and appear to be complete enough for code generation. See http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html for a stand-alone example. + See the llvm-c/Core.h file for reference. diff --git a/src/gallium/drivers/llvmpipe/lp_buffer.c b/src/gallium/drivers/llvmpipe/lp_buffer.c index 9eda9720818..6e0f37393e9 100644 --- a/src/gallium/drivers/llvmpipe/lp_buffer.c +++ b/src/gallium/drivers/llvmpipe/lp_buffer.c @@ -30,7 +30,6 @@ #include "util/u_memory.h" #include "util/u_math.h" -#include "lp_winsys.h" #include "lp_screen.h" #include "lp_buffer.h" diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index e31ae6a3fc1..951a695f964 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -68,11 +68,11 @@ static void llvmpipe_destroy( struct pipe_context *pipe ) pipe_surface_reference(&llvmpipe->framebuffer.zsbuf, NULL); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - pipe_texture_reference(&llvmpipe->texture[i], NULL); + pipe_sampler_view_reference(&llvmpipe->fragment_sampler_views[i], NULL); } for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - pipe_texture_reference(&llvmpipe->vertex_textures[i], NULL); + pipe_sampler_view_reference(&llvmpipe->vertex_sampler_views[i], NULL); } for (i = 0; i < Elements(llvmpipe->constants); i++) { @@ -145,6 +145,10 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe->pipe.bind_vs_state = llvmpipe_bind_vs_state; llvmpipe->pipe.delete_vs_state = llvmpipe_delete_vs_state; + llvmpipe->pipe.create_vertex_elements_state = llvmpipe_create_vertex_elements_state; + llvmpipe->pipe.bind_vertex_elements_state = llvmpipe_bind_vertex_elements_state; + llvmpipe->pipe.delete_vertex_elements_state = llvmpipe_delete_vertex_elements_state; + llvmpipe->pipe.set_blend_color = llvmpipe_set_blend_color; llvmpipe->pipe.set_stencil_ref = llvmpipe_set_stencil_ref; llvmpipe->pipe.set_clip_state = llvmpipe_set_clip_state; @@ -152,12 +156,13 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe->pipe.set_framebuffer_state = llvmpipe_set_framebuffer_state; llvmpipe->pipe.set_polygon_stipple = llvmpipe_set_polygon_stipple; llvmpipe->pipe.set_scissor_state = llvmpipe_set_scissor_state; - llvmpipe->pipe.set_fragment_sampler_textures = llvmpipe_set_sampler_textures; - llvmpipe->pipe.set_vertex_sampler_textures = llvmpipe_set_vertex_sampler_textures; + llvmpipe->pipe.set_fragment_sampler_views = llvmpipe_set_fragment_sampler_views; + llvmpipe->pipe.set_vertex_sampler_views = llvmpipe_set_vertex_sampler_views; + llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view; + llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy; llvmpipe->pipe.set_viewport_state = llvmpipe_set_viewport_state; llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers; - llvmpipe->pipe.set_vertex_elements = llvmpipe_set_vertex_elements; llvmpipe->pipe.draw_arrays = llvmpipe_draw_arrays; llvmpipe->pipe.draw_elements = llvmpipe_draw_elements; @@ -170,6 +175,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe->pipe.is_buffer_referenced = llvmpipe_is_buffer_referenced; llvmpipe_init_query_funcs( llvmpipe ); + llvmpipe_init_context_texture_funcs( &llvmpipe->pipe ); /* * Create drawing context and plug our rendering stage into it. diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 955c7eb8e0e..71f991049e5 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -45,7 +45,8 @@ struct draw_stage; struct lp_fragment_shader; struct lp_vertex_shader; struct lp_blend_state; -struct setup_context; +struct lp_setup_context; +struct lp_velems_state; struct llvmpipe_context { struct pipe_context pipe; /**< base class */ @@ -58,6 +59,7 @@ struct llvmpipe_context { const struct pipe_rasterizer_state *rasterizer; struct lp_fragment_shader *fs; const struct lp_vertex_shader *vs; + const struct lp_velems_state *velems; /** Other rendering state */ struct pipe_blend_color blend_color; @@ -67,17 +69,15 @@ struct llvmpipe_context { struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; - struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; - struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; unsigned num_samplers; - unsigned num_textures; + unsigned num_fragment_sampler_views; unsigned num_vertex_samplers; - unsigned num_vertex_textures; - unsigned num_vertex_elements; + unsigned num_vertex_sampler_views; unsigned num_vertex_buffers; unsigned dirty; /**< Mask of LP_NEW_x flags */ @@ -98,7 +98,7 @@ struct llvmpipe_context { int psize_slot; /** The tiling engine */ - struct setup_context *setup; + struct lp_setup_context *setup; /** The primitive drawing context */ struct draw_context *draw; diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index bf832433be1..636d72a9bb8 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -79,12 +79,12 @@ llvmpipe_flush( struct pipe_context *pipe, for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { util_snprintf(filename, sizeof(filename), "cbuf%u_%u", i, frame_no); - debug_dump_surface(filename, llvmpipe->framebuffer.cbufs[i]); + debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[0]); } if (0) { util_snprintf(filename, sizeof(filename), "zsbuf_%u", frame_no); - debug_dump_surface(filename, llvmpipe->framebuffer.zsbuf); + debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.zsbuf); } ++frame_no; @@ -92,3 +92,68 @@ llvmpipe_flush( struct pipe_context *pipe, #endif } + +/** + * Flush context if necessary. + * + * TODO: move this logic to an auxiliary library? + * + * FIXME: We must implement DISCARD/DONTBLOCK/UNSYNCHRONIZED/etc for + * textures to avoid blocking. + */ +boolean +llvmpipe_flush_texture(struct pipe_context *pipe, + struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned flush_flags, + boolean read_only, + boolean cpu_access, + boolean do_not_flush) +{ + struct pipe_fence_handle *last_fence = NULL; + unsigned referenced; + + referenced = pipe->is_texture_referenced(pipe, texture, face, level); + + if ((referenced & PIPE_REFERENCED_FOR_WRITE) || + ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) { + + if (do_not_flush) + return FALSE; + + /* + * TODO: The semantics of these flush flags are too obtuse. They should + * disappear and the pipe driver should just ensure that all visible + * side-effects happen when they need to happen. + */ + if (referenced & PIPE_REFERENCED_FOR_WRITE) + flush_flags |= PIPE_FLUSH_RENDER_CACHE; + + if (referenced & PIPE_REFERENCED_FOR_READ) + flush_flags |= PIPE_FLUSH_TEXTURE_CACHE; + + if (cpu_access) { + /* + * Flush and wait. + */ + + struct pipe_fence_handle *fence = NULL; + + pipe->flush(pipe, flush_flags, &fence); + + if (last_fence) { + pipe->screen->fence_finish(pipe->screen, fence, 0); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); + } + } else { + /* + * Just flush. + */ + + pipe->flush(pipe, flush_flags, NULL); + } + } + + return TRUE; +} diff --git a/src/gallium/drivers/llvmpipe/lp_flush.h b/src/gallium/drivers/llvmpipe/lp_flush.h index 10b2b525836..e13f57ccec5 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.h +++ b/src/gallium/drivers/llvmpipe/lp_flush.h @@ -28,10 +28,22 @@ #ifndef LP_FLUSH_H #define LP_FLUSH_H +#include "pipe/p_compiler.h" + struct pipe_context; struct pipe_fence_handle; void llvmpipe_flush(struct pipe_context *pipe, unsigned flags, struct pipe_fence_handle **fence); +boolean +llvmpipe_flush_texture(struct pipe_context *pipe, + struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned flush_flags, + boolean read_only, + boolean cpu_access, + boolean do_not_flush); + #endif diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index bacff500d63..5887613120d 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -57,8 +57,11 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) elem_types[LP_JIT_TEXTURE_HEIGHT] = LLVMInt32Type(); elem_types[LP_JIT_TEXTURE_DEPTH] = LLVMInt32Type(); elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type(); - elem_types[LP_JIT_TEXTURE_STRIDE] = LLVMInt32Type(); - elem_types[LP_JIT_TEXTURE_DATA] = LLVMPointerType(LLVMInt8Type(), 0); + elem_types[LP_JIT_TEXTURE_ROW_STRIDE] = + LLVMArrayType(LLVMInt32Type(), LP_MAX_TEXTURE_2D_LEVELS); + elem_types[LP_JIT_TEXTURE_DATA] = + LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0), + LP_MAX_TEXTURE_2D_LEVELS); texture_type = LLVMStructType(elem_types, Elements(elem_types), 0); @@ -74,9 +77,9 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, last_level, screen->target, texture_type, LP_JIT_TEXTURE_LAST_LEVEL); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, stride, + LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, row_stride, screen->target, texture_type, - LP_JIT_TEXTURE_STRIDE); + LP_JIT_TEXTURE_ROW_STRIDE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, data, screen->target, texture_type, LP_JIT_TEXTURE_DATA); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 0ebb2826fa2..13167ae3bf4 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -39,6 +39,7 @@ #include "gallivm/lp_bld_struct.h" #include "pipe/p_state.h" +#include "lp_texture.h" struct llvmpipe_screen; @@ -50,8 +51,8 @@ struct lp_jit_texture uint32_t height; uint32_t depth; uint32_t last_level; - uint32_t stride; - const void *data; + uint32_t row_stride[LP_MAX_TEXTURE_2D_LEVELS]; + const void *data[LP_MAX_TEXTURE_2D_LEVELS]; }; @@ -60,7 +61,7 @@ enum { LP_JIT_TEXTURE_HEIGHT, LP_JIT_TEXTURE_DEPTH, LP_JIT_TEXTURE_LAST_LEVEL, - LP_JIT_TEXTURE_STRIDE, + LP_JIT_TEXTURE_ROW_STRIDE, LP_JIT_TEXTURE_DATA }; diff --git a/src/gallium/drivers/llvmpipe/lp_public.h b/src/gallium/drivers/llvmpipe/lp_public.h new file mode 100644 index 00000000000..ec6b660b48e --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_public.h @@ -0,0 +1,10 @@ +#ifndef LP_PUBLIC_H +#define LP_PUBLIC_H + +struct pipe_screen; +struct sw_winsys; + +struct pipe_screen * +llvmpipe_create_screen(struct sw_winsys *winsys); + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index dd9a8e8856f..81ea11a16b6 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -62,18 +62,20 @@ lp_rast_begin( struct lp_rasterizer *rast, rast->state.write_color = write_color; for (i = 0; i < rast->state.nr_cbufs; i++) { + struct pipe_surface *cbuf = scene->fb.cbufs[i]; rast->cbuf[i].map = scene->cbuf_map[i]; - rast->cbuf[i].format = scene->cbuf_transfer[i]->texture->format; - rast->cbuf[i].width = scene->cbuf_transfer[i]->width; - rast->cbuf[i].height = scene->cbuf_transfer[i]->height; - rast->cbuf[i].stride = scene->cbuf_transfer[i]->stride; + rast->cbuf[i].format = cbuf->texture->format; + rast->cbuf[i].width = cbuf->width; + rast->cbuf[i].height = cbuf->height; + rast->cbuf[i].stride = llvmpipe_texture_stride(cbuf->texture, cbuf->level); } if (write_zstencil) { + struct pipe_surface *zsbuf = scene->fb.zsbuf; rast->zsbuf.map = scene->zsbuf_map; - rast->zsbuf.stride = scene->zsbuf_transfer->stride; + rast->zsbuf.stride = llvmpipe_texture_stride(zsbuf->texture, zsbuf->level); rast->zsbuf.blocksize = - util_format_get_blocksize(scene->zsbuf_transfer->texture->format); + util_format_get_blocksize(zsbuf->texture->format); } lp_scene_bin_iter_begin( scene ); diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index dc5fc5fc7d6..303f6e3f7e4 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -95,7 +95,7 @@ struct lp_rast_shader_inputs { * Rasterization information for a triangle known to be in this bin, * plus inputs to run the shader: * These fields are tile- and bin-independent. - * Objects of this type are put into the setup_context::data buffer. + * Objects of this type are put into the lp_setup_context::data buffer. */ struct lp_rast_triangle { #ifdef DEBUG diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 72492c0f0ca..681ce674d49 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -397,7 +397,6 @@ end: static boolean lp_scene_map_buffers( struct lp_scene *scene ) { - struct pipe_screen *screen = scene->pipe->screen; struct pipe_surface *cbuf, *zsbuf; int i; @@ -409,20 +408,10 @@ lp_scene_map_buffers( struct lp_scene *scene ) for (i = 0; i < scene->fb.nr_cbufs; i++) { cbuf = scene->fb.cbufs[i]; if (cbuf) { - scene->cbuf_transfer[i] = screen->get_tex_transfer(screen, - cbuf->texture, - cbuf->face, - cbuf->level, - cbuf->zslice, - PIPE_TRANSFER_READ_WRITE, - 0, 0, - cbuf->width, - cbuf->height); - if (!scene->cbuf_transfer[i]) - goto fail; - - scene->cbuf_map[i] = screen->transfer_map(screen, - scene->cbuf_transfer[i]); + scene->cbuf_map[i] = llvmpipe_texture_map(cbuf->texture, + cbuf->face, + cbuf->level, + cbuf->zslice); if (!scene->cbuf_map[i]) goto fail; } @@ -432,20 +421,10 @@ lp_scene_map_buffers( struct lp_scene *scene ) */ zsbuf = scene->fb.zsbuf; if (zsbuf) { - scene->zsbuf_transfer = screen->get_tex_transfer(screen, - zsbuf->texture, - zsbuf->face, - zsbuf->level, - zsbuf->zslice, - PIPE_TRANSFER_READ_WRITE, - 0, 0, - zsbuf->width, - zsbuf->height); - if (!scene->zsbuf_transfer) - goto fail; - - scene->zsbuf_map = screen->transfer_map(screen, - scene->zsbuf_transfer); + scene->zsbuf_map = llvmpipe_texture_map(zsbuf->texture, + zsbuf->face, + zsbuf->level, + zsbuf->zslice); if (!scene->zsbuf_map) goto fail; } @@ -469,28 +448,27 @@ fail: static void lp_scene_unmap_buffers( struct lp_scene *scene ) { - struct pipe_screen *screen = scene->pipe->screen; unsigned i; for (i = 0; i < scene->fb.nr_cbufs; i++) { - if (scene->cbuf_map[i]) - screen->transfer_unmap(screen, scene->cbuf_transfer[i]); - - if (scene->cbuf_transfer[i]) - screen->tex_transfer_destroy(scene->cbuf_transfer[i]); - - scene->cbuf_transfer[i] = NULL; - scene->cbuf_map[i] = NULL; + if (scene->cbuf_map[i]) { + struct pipe_surface *cbuf = scene->fb.cbufs[i]; + llvmpipe_texture_unmap(cbuf->texture, + cbuf->face, + cbuf->level, + cbuf->zslice); + scene->cbuf_map[i] = NULL; + } } - if (scene->zsbuf_map) - screen->transfer_unmap(screen, scene->zsbuf_transfer); - - if (scene->zsbuf_transfer) - screen->tex_transfer_destroy(scene->zsbuf_transfer); - - scene->zsbuf_transfer = NULL; - scene->zsbuf_map = NULL; + if (scene->zsbuf_map) { + struct pipe_surface *zsbuf = scene->fb.zsbuf; + llvmpipe_texture_unmap(zsbuf->texture, + zsbuf->face, + zsbuf->level, + zsbuf->zslice); + scene->zsbuf_map = NULL; + } util_unreference_framebuffer_state( &scene->fb ); } diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index 739ac229089..b602b1e8a05 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -114,8 +114,6 @@ struct texture_ref { */ struct lp_scene { struct pipe_context *pipe; - struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS]; - struct pipe_transfer *zsbuf_transfer; /* Scene's buffers are mapped at the time the scene is enqueued: */ diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index f84ede675b3..f1bbc2092c4 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -34,11 +34,13 @@ #include "lp_texture.h" #include "lp_buffer.h" #include "lp_fence.h" -#include "lp_winsys.h" #include "lp_jit.h" #include "lp_screen.h" #include "lp_context.h" #include "lp_debug.h" +#include "lp_public.h" + +#include "state_tracker/sw_winsys.h" #ifdef DEBUG int LP_DEBUG = 0; @@ -107,11 +109,11 @@ llvmpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 13; /* max 4Kx4K */ + return LP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 9; /* max 256x256x256 */ + return LP_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 13; /* max 4Kx4K */ + return LP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_CONT_SUPPORTED: return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: @@ -167,7 +169,7 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, unsigned geom_flags ) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; const struct util_format_description *format_desc; format_desc = util_format_description(format); @@ -202,8 +204,10 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, return FALSE; } - if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { - if(!winsys->is_displaytarget_format_supported(winsys, format)) + if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) return FALSE; } @@ -238,18 +242,6 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, } -static struct pipe_buffer * -llvmpipe_surface_buffer_create(struct pipe_screen *screen, - unsigned width, unsigned height, - enum pipe_format format, - unsigned tex_usage, - unsigned usage, - unsigned *stride) -{ - /* This function should never be used */ - assert(0); - return NULL; -} static void @@ -258,7 +250,7 @@ llvmpipe_flush_frontbuffer(struct pipe_screen *_screen, void *context_private) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; struct llvmpipe_texture *texture = llvmpipe_texture(surface->texture); assert(texture->dt); @@ -271,7 +263,7 @@ static void llvmpipe_destroy_screen( struct pipe_screen *_screen ) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; lp_jit_screen_cleanup(screen); @@ -288,7 +280,7 @@ llvmpipe_destroy_screen( struct pipe_screen *_screen ) * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen). */ struct pipe_screen * -llvmpipe_create_screen(struct llvmpipe_winsys *winsys) +llvmpipe_create_screen(struct sw_winsys *winsys) { struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen); @@ -309,7 +301,6 @@ llvmpipe_create_screen(struct llvmpipe_winsys *winsys) screen->base.get_paramf = llvmpipe_get_paramf; screen->base.is_format_supported = llvmpipe_is_format_supported; - screen->base.surface_buffer_create = llvmpipe_surface_buffer_create; screen->base.context_create = llvmpipe_create_context; screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer; diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h index 4a1b4d6f3e2..af25e043cc9 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.h +++ b/src/gallium/drivers/llvmpipe/lp_screen.h @@ -34,23 +34,21 @@ #ifndef LP_SCREEN_H #define LP_SCREEN_H -#include <llvm-c/Core.h> -#include <llvm-c/Analysis.h> -#include <llvm-c/Target.h> +#include "gallivm/lp_bld.h" #include <llvm-c/ExecutionEngine.h> #include "pipe/p_screen.h" #include "pipe/p_defines.h" -struct llvmpipe_winsys; +struct sw_winsys; struct llvmpipe_screen { struct pipe_screen base; - struct llvmpipe_winsys *winsys; + struct sw_winsys *winsys; LLVMModuleRef module; LLVMExecutionEngineRef engine; @@ -76,4 +74,5 @@ llvmpipe_screen( struct pipe_screen *pipe ) } + #endif /* LP_SCREEN_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index b0713c3b71d..cd16b6b2d38 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -46,17 +46,17 @@ #include "lp_rast.h" #include "lp_setup_context.h" #include "lp_screen.h" -#include "lp_winsys.h" +#include "state_tracker/sw_winsys.h" #include "draw/draw_context.h" #include "draw/draw_vbuf.h" -static void set_scene_state( struct setup_context *, unsigned ); +static void set_scene_state( struct lp_setup_context *, unsigned ); struct lp_scene * -lp_setup_get_current_scene(struct setup_context *setup) +lp_setup_get_current_scene(struct lp_setup_context *setup) { if (!setup->scene) { @@ -74,7 +74,7 @@ lp_setup_get_current_scene(struct setup_context *setup) static void -first_triangle( struct setup_context *setup, +first_triangle( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], const float (*v2)[4]) @@ -85,7 +85,7 @@ first_triangle( struct setup_context *setup, } static void -first_line( struct setup_context *setup, +first_line( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { @@ -95,7 +95,7 @@ first_line( struct setup_context *setup, } static void -first_point( struct setup_context *setup, +first_point( struct lp_setup_context *setup, const float (*v0)[4]) { set_scene_state( setup, SETUP_ACTIVE ); @@ -103,7 +103,7 @@ first_point( struct setup_context *setup, setup->point( setup, v0 ); } -static void reset_context( struct setup_context *setup ) +static void reset_context( struct lp_setup_context *setup ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -131,7 +131,7 @@ static void reset_context( struct setup_context *setup ) /** Rasterize all scene's bins */ static void -lp_setup_rasterize_scene( struct setup_context *setup, +lp_setup_rasterize_scene( struct lp_setup_context *setup, boolean write_depth ) { struct lp_scene *scene = lp_setup_get_current_scene(setup); @@ -148,7 +148,7 @@ lp_setup_rasterize_scene( struct setup_context *setup, static void -begin_binning( struct setup_context *setup ) +begin_binning( struct lp_setup_context *setup ) { struct lp_scene *scene = lp_setup_get_current_scene(setup); @@ -184,7 +184,7 @@ begin_binning( struct setup_context *setup ) * TODO: fast path for fullscreen clears and no triangles. */ static void -execute_clears( struct setup_context *setup ) +execute_clears( struct lp_setup_context *setup ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -194,7 +194,7 @@ execute_clears( struct setup_context *setup ) static void -set_scene_state( struct setup_context *setup, +set_scene_state( struct lp_setup_context *setup, unsigned new_state ) { unsigned old_state = setup->state; @@ -229,7 +229,7 @@ set_scene_state( struct setup_context *setup, void -lp_setup_flush( struct setup_context *setup, +lp_setup_flush( struct lp_setup_context *setup, unsigned flags ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -239,7 +239,7 @@ lp_setup_flush( struct setup_context *setup, void -lp_setup_bind_framebuffer( struct setup_context *setup, +lp_setup_bind_framebuffer( struct lp_setup_context *setup, const struct pipe_framebuffer_state *fb ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -256,7 +256,7 @@ lp_setup_bind_framebuffer( struct setup_context *setup, void -lp_setup_clear( struct setup_context *setup, +lp_setup_clear( struct lp_setup_context *setup, const float *color, double depth, unsigned stencil, @@ -314,7 +314,7 @@ lp_setup_clear( struct setup_context *setup, * Emit a fence. */ struct pipe_fence_handle * -lp_setup_fence( struct setup_context *setup ) +lp_setup_fence( struct lp_setup_context *setup ) { struct lp_scene *scene = lp_setup_get_current_scene(setup); const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */ @@ -334,10 +334,11 @@ lp_setup_fence( struct setup_context *setup ) void -lp_setup_set_triangle_state( struct setup_context *setup, +lp_setup_set_triangle_state( struct lp_setup_context *setup, unsigned cull_mode, boolean ccw_is_frontface, - boolean scissor ) + boolean scissor, + boolean gl_rasterization_rules) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -345,12 +346,13 @@ lp_setup_set_triangle_state( struct setup_context *setup, setup->cullmode = cull_mode; setup->triangle = first_triangle; setup->scissor_test = scissor; + setup->pixel_offset = gl_rasterization_rules ? 0.5f : 0.0f; } void -lp_setup_set_fs_inputs( struct setup_context *setup, +lp_setup_set_fs_inputs( struct lp_setup_context *setup, const struct lp_shader_input *input, unsigned nr ) { @@ -361,7 +363,7 @@ lp_setup_set_fs_inputs( struct setup_context *setup, } void -lp_setup_set_fs_functions( struct setup_context *setup, +lp_setup_set_fs_functions( struct lp_setup_context *setup, lp_jit_frag_func jit_function0, lp_jit_frag_func jit_function1, boolean opaque ) @@ -376,7 +378,7 @@ lp_setup_set_fs_functions( struct setup_context *setup, } void -lp_setup_set_fs_constants(struct setup_context *setup, +lp_setup_set_fs_constants(struct lp_setup_context *setup, struct pipe_buffer *buffer) { LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); @@ -388,7 +390,7 @@ lp_setup_set_fs_constants(struct setup_context *setup, void -lp_setup_set_alpha_ref_value( struct setup_context *setup, +lp_setup_set_alpha_ref_value( struct lp_setup_context *setup, float alpha_ref_value ) { LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); @@ -400,7 +402,7 @@ lp_setup_set_alpha_ref_value( struct setup_context *setup, } void -lp_setup_set_blend_color( struct setup_context *setup, +lp_setup_set_blend_color( struct lp_setup_context *setup, const struct pipe_blend_color *blend_color ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -415,7 +417,7 @@ lp_setup_set_blend_color( struct setup_context *setup, void -lp_setup_set_scissor( struct setup_context *setup, +lp_setup_set_scissor( struct lp_setup_context *setup, const struct pipe_scissor_state *scissor ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -430,7 +432,7 @@ lp_setup_set_scissor( struct setup_context *setup, void -lp_setup_set_flatshade_first( struct setup_context *setup, +lp_setup_set_flatshade_first( struct lp_setup_context *setup, boolean flatshade_first ) { setup->flatshade_first = flatshade_first; @@ -438,7 +440,7 @@ lp_setup_set_flatshade_first( struct setup_context *setup, void -lp_setup_set_vertex_info( struct setup_context *setup, +lp_setup_set_vertex_info( struct lp_setup_context *setup, struct vertex_info *vertex_info ) { /* XXX: just silently holding onto the pointer: @@ -448,11 +450,12 @@ lp_setup_set_vertex_info( struct setup_context *setup, /** - * Called during state validation when LP_NEW_TEXTURE is set. + * Called during state validation when LP_NEW_SAMPLER_VIEW is set. */ void -lp_setup_set_sampler_textures( struct setup_context *setup, - unsigned num, struct pipe_texture **texture) +lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, + unsigned num, + struct pipe_sampler_view **views) { unsigned i; @@ -461,9 +464,10 @@ lp_setup_set_sampler_textures( struct setup_context *setup, assert(num <= PIPE_MAX_SAMPLERS); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - struct pipe_texture *tex = i < num ? texture[i] : NULL; + struct pipe_sampler_view *view = i < num ? views[i] : NULL; - if(tex) { + if(view) { + struct pipe_texture *tex = view->texture; struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex); struct lp_jit_texture *jit_tex; jit_tex = &setup->fs.current.jit_context.textures[i]; @@ -471,20 +475,27 @@ lp_setup_set_sampler_textures( struct setup_context *setup, jit_tex->height = tex->height0; jit_tex->depth = tex->depth0; jit_tex->last_level = tex->last_level; - jit_tex->stride = lp_tex->stride[0]; - if(!lp_tex->dt) { - jit_tex->data = lp_tex->data; + if (!lp_tex->dt) { + /* regular texture - setup array of mipmap level pointers */ + int j; + for (j = 0; j <= tex->last_level; j++) { + jit_tex->data[j] = + (ubyte *) lp_tex->data + lp_tex->level_offset[j]; + jit_tex->row_stride[j] = lp_tex->stride[j]; + } } else { + /* display target texture/surface */ /* * XXX: Where should this be unmapped? */ struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); - struct llvmpipe_winsys *winsys = screen->winsys; - jit_tex->data = winsys->displaytarget_map(winsys, lp_tex->dt, + struct sw_winsys *winsys = screen->winsys; + jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_BUFFER_USAGE_CPU_READ); - assert(jit_tex->data); + jit_tex->row_stride[0] = lp_tex->stride[0]; + assert(jit_tex->data[0]); } /* the scene references this texture */ @@ -505,7 +516,7 @@ lp_setup_set_sampler_textures( struct setup_context *setup, * being rendered and the current scene being built. */ unsigned -lp_setup_is_texture_referenced( const struct setup_context *setup, +lp_setup_is_texture_referenced( const struct lp_setup_context *setup, const struct pipe_texture *texture ) { unsigned i; @@ -534,7 +545,7 @@ lp_setup_is_texture_referenced( const struct setup_context *setup, * Called by vbuf code when we're about to draw something. */ void -lp_setup_update_state( struct setup_context *setup ) +lp_setup_update_state( struct lp_setup_context *setup ) { struct lp_scene *scene = lp_setup_get_current_scene(setup); @@ -652,7 +663,7 @@ lp_setup_update_state( struct setup_context *setup ) /* Only caller is lp_setup_vbuf_destroy() */ void -lp_setup_destroy( struct setup_context *setup ) +lp_setup_destroy( struct lp_setup_context *setup ) { reset_context( setup ); @@ -677,12 +688,12 @@ lp_setup_destroy( struct setup_context *setup ) * the draw module. Currently also creates a rasterizer to use with * it. */ -struct setup_context * +struct lp_setup_context * lp_setup_create( struct pipe_context *pipe, struct draw_context *draw ) { unsigned i; - struct setup_context *setup = CALLOC_STRUCT(setup_context); + struct lp_setup_context *setup = CALLOC_STRUCT(lp_setup_context); if (!setup) return NULL; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 17c112b5289..414eaec98d1 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -61,78 +61,80 @@ struct pipe_framebuffer_state; struct lp_fragment_shader; struct lp_jit_context; -struct setup_context * +struct lp_setup_context * lp_setup_create( struct pipe_context *pipe, struct draw_context *draw ); void -lp_setup_clear(struct setup_context *setup, +lp_setup_clear(struct lp_setup_context *setup, const float *clear_color, double clear_depth, unsigned clear_stencil, unsigned flags); struct pipe_fence_handle * -lp_setup_fence( struct setup_context *setup ); +lp_setup_fence( struct lp_setup_context *setup ); void -lp_setup_flush( struct setup_context *setup, +lp_setup_flush( struct lp_setup_context *setup, unsigned flags ); void -lp_setup_bind_framebuffer( struct setup_context *setup, +lp_setup_bind_framebuffer( struct lp_setup_context *setup, const struct pipe_framebuffer_state *fb ); void -lp_setup_set_triangle_state( struct setup_context *setup, +lp_setup_set_triangle_state( struct lp_setup_context *setup, unsigned cullmode, boolean front_is_ccw, - boolean scissor ); + boolean scissor, + boolean gl_rasterization_rules ); void -lp_setup_set_fs_inputs( struct setup_context *setup, +lp_setup_set_fs_inputs( struct lp_setup_context *setup, const struct lp_shader_input *interp, unsigned nr ); void -lp_setup_set_fs_functions( struct setup_context *setup, +lp_setup_set_fs_functions( struct lp_setup_context *setup, lp_jit_frag_func jit_function0, lp_jit_frag_func jit_function1, boolean opaque ); void -lp_setup_set_fs_constants(struct setup_context *setup, +lp_setup_set_fs_constants(struct lp_setup_context *setup, struct pipe_buffer *buffer); void -lp_setup_set_alpha_ref_value( struct setup_context *setup, +lp_setup_set_alpha_ref_value( struct lp_setup_context *setup, float alpha_ref_value ); void -lp_setup_set_blend_color( struct setup_context *setup, +lp_setup_set_blend_color( struct lp_setup_context *setup, const struct pipe_blend_color *blend_color ); void -lp_setup_set_scissor( struct setup_context *setup, +lp_setup_set_scissor( struct lp_setup_context *setup, const struct pipe_scissor_state *scissor ); void -lp_setup_set_sampler_textures( struct setup_context *setup, - unsigned num, struct pipe_texture **texture); +lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, + unsigned num, + struct pipe_sampler_view **views); unsigned -lp_setup_is_texture_referenced( const struct setup_context *setup, +lp_setup_is_texture_referenced( const struct lp_setup_context *setup, const struct pipe_texture *texture ); void -lp_setup_set_flatshade_first( struct setup_context *setup, +lp_setup_set_flatshade_first( struct lp_setup_context *setup, boolean flatshade_first ); void -lp_setup_set_vertex_info( struct setup_context *setup, +lp_setup_set_vertex_info( struct lp_setup_context *setup, struct vertex_info *info ); diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index a5fc34e54a2..464fb369840 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -65,7 +65,7 @@ struct lp_scene_queue; * Subclass of vbuf_render, plugged directly into the draw module as * the rendering backend. */ -struct setup_context +struct lp_setup_context { struct vbuf_render base; @@ -89,6 +89,7 @@ struct setup_context boolean ccw_is_frontface; boolean scissor_test; unsigned cullmode; + float pixel_offset; struct pipe_framebuffer_state fb; @@ -131,29 +132,29 @@ struct setup_context unsigned dirty; /**< bitmask of LP_SETUP_NEW_x bits */ - void (*point)( struct setup_context *, + void (*point)( struct lp_setup_context *, const float (*v0)[4]); - void (*line)( struct setup_context *, + void (*line)( struct lp_setup_context *, const float (*v0)[4], const float (*v1)[4]); - void (*triangle)( struct setup_context *, + void (*triangle)( struct lp_setup_context *, const float (*v0)[4], const float (*v1)[4], const float (*v2)[4]); }; -void lp_setup_choose_triangle( struct setup_context *setup ); -void lp_setup_choose_line( struct setup_context *setup ); -void lp_setup_choose_point( struct setup_context *setup ); +void lp_setup_choose_triangle( struct lp_setup_context *setup ); +void lp_setup_choose_line( struct lp_setup_context *setup ); +void lp_setup_choose_point( struct lp_setup_context *setup ); -struct lp_scene *lp_setup_get_current_scene(struct setup_context *setup); +struct lp_scene *lp_setup_get_current_scene(struct lp_setup_context *setup); -void lp_setup_init_vbuf(struct setup_context *setup); +void lp_setup_init_vbuf(struct lp_setup_context *setup); -void lp_setup_update_state( struct setup_context *setup ); +void lp_setup_update_state( struct lp_setup_context *setup ); -void lp_setup_destroy( struct setup_context *setup ); +void lp_setup_destroy( struct lp_setup_context *setup ); #endif diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c index feea79d3943..be41c44e6f5 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_line.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c @@ -31,7 +31,7 @@ #include "lp_setup_context.h" -static void line_nop( struct setup_context *setup, +static void line_nop( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4] ) { @@ -39,7 +39,7 @@ static void line_nop( struct setup_context *setup, void -lp_setup_choose_line( struct setup_context *setup ) +lp_setup_choose_line( struct lp_setup_context *setup ) { setup->line = line_nop; } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c index f03ca729b24..9f69e6c5ce2 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_point.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c @@ -31,14 +31,14 @@ #include "lp_setup_context.h" -static void point_nop( struct setup_context *setup, +static void point_nop( struct lp_setup_context *setup, const float (*v0)[4] ) { } void -lp_setup_choose_point( struct setup_context *setup ) +lp_setup_choose_point( struct lp_setup_context *setup ) { setup->point = point_nop; } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index e75412ac9aa..ac6264dc73e 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -41,7 +41,8 @@ /** * Compute a0 for a constant-valued coefficient (GL_FLAT shading). */ -static void constant_coef( struct lp_rast_triangle *tri, +static void constant_coef( struct lp_setup_context *setup, + struct lp_rast_triangle *tri, unsigned slot, const float value, unsigned i ) @@ -56,7 +57,8 @@ static void constant_coef( struct lp_rast_triangle *tri, * Compute a0, dadx and dady for a linearly interpolated coefficient, * for a triangle. */ -static void linear_coef( struct lp_rast_triangle *tri, +static void linear_coef( struct lp_setup_context *setup, + struct lp_rast_triangle *tri, float oneoverarea, unsigned slot, const float (*v1)[4], @@ -90,8 +92,8 @@ static void linear_coef( struct lp_rast_triangle *tri, * instead - i'll switch to this later. */ tri->inputs.a0[slot][i] = (a1 - - (dadx * (v1[0][0] - 0.5f) + - dady * (v1[0][1] - 0.5f))); + (dadx * (v1[0][0] - setup->pixel_offset) + + dady * (v1[0][1] - setup->pixel_offset))); } @@ -103,7 +105,8 @@ static void linear_coef( struct lp_rast_triangle *tri, * Later, when we compute the value at a particular fragment position we'll * divide the interpolated value by the interpolated W at that fragment. */ -static void perspective_coef( struct lp_rast_triangle *tri, +static void perspective_coef( struct lp_setup_context *setup, + struct lp_rast_triangle *tri, float oneoverarea, unsigned slot, const float (*v1)[4], @@ -125,8 +128,8 @@ static void perspective_coef( struct lp_rast_triangle *tri, tri->inputs.dadx[slot][i] = dadx; tri->inputs.dady[slot][i] = dady; tri->inputs.a0[slot][i] = (a1 - - (dadx * (v1[0][0] - 0.5f) + - dady * (v1[0][1] - 0.5f))); + (dadx * (v1[0][0] - setup->pixel_offset) + + dady * (v1[0][1] - setup->pixel_offset))); } @@ -137,7 +140,8 @@ static void perspective_coef( struct lp_rast_triangle *tri, * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. */ static void -setup_fragcoord_coef(struct lp_rast_triangle *tri, +setup_fragcoord_coef(struct lp_setup_context *setup, + struct lp_rast_triangle *tri, float oneoverarea, unsigned slot, const float (*v1)[4], @@ -153,27 +157,28 @@ setup_fragcoord_coef(struct lp_rast_triangle *tri, tri->inputs.dadx[slot][1] = 0.0; tri->inputs.dady[slot][1] = 1.0; /*Z*/ - linear_coef(tri, oneoverarea, slot, v1, v2, v3, 0, 2); + linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 2); /*W*/ - linear_coef(tri, oneoverarea, slot, v1, v2, v3, 0, 3); + linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 3); } -static void setup_facing_coef( struct lp_rast_triangle *tri, +static void setup_facing_coef( struct lp_setup_context *setup, + struct lp_rast_triangle *tri, unsigned slot, boolean frontface ) { - constant_coef( tri, slot, 1.0f - frontface, 0 ); - constant_coef( tri, slot, 0.0f, 1 ); /* wasted */ - constant_coef( tri, slot, 0.0f, 2 ); /* wasted */ - constant_coef( tri, slot, 0.0f, 3 ); /* wasted */ + constant_coef( setup, tri, slot, 1.0f - frontface, 0 ); + constant_coef( setup, tri, slot, 0.0f, 1 ); /* wasted */ + constant_coef( setup, tri, slot, 0.0f, 2 ); /* wasted */ + constant_coef( setup, tri, slot, 0.0f, 3 ); /* wasted */ } /** * Compute the tri->coef[] array dadx, dady, a0 values. */ -static void setup_tri_coefficients( struct setup_context *setup, +static void setup_tri_coefficients( struct lp_setup_context *setup, struct lp_rast_triangle *tri, float oneoverarea, const float (*v1)[4], @@ -185,7 +190,7 @@ static void setup_tri_coefficients( struct setup_context *setup, /* The internal position input is in slot zero: */ - setup_fragcoord_coef(tri, oneoverarea, 0, v1, v2, v3); + setup_fragcoord_coef(setup, tri, oneoverarea, 0, v1, v2, v3); /* setup interpolation for all the remaining attributes: */ @@ -196,27 +201,27 @@ static void setup_tri_coefficients( struct setup_context *setup, switch (setup->fs.input[slot].interp) { case LP_INTERP_CONSTANT: for (i = 0; i < NUM_CHANNELS; i++) - constant_coef(tri, slot+1, v3[vert_attr][i], i); + constant_coef(setup, tri, slot+1, v3[vert_attr][i], i); break; case LP_INTERP_LINEAR: for (i = 0; i < NUM_CHANNELS; i++) - linear_coef(tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); + linear_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); break; case LP_INTERP_PERSPECTIVE: for (i = 0; i < NUM_CHANNELS; i++) - perspective_coef(tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); + perspective_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); break; case LP_INTERP_POSITION: /* XXX: fix me - duplicates the values in slot zero. */ - setup_fragcoord_coef(tri, oneoverarea, slot+1, v1, v2, v3); + setup_fragcoord_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3); break; case LP_INTERP_FACING: - setup_facing_coef(tri, slot+1, frontface); + setup_facing_coef(setup, tri, slot+1, frontface); break; default: @@ -274,19 +279,19 @@ alloc_triangle(struct lp_scene *scene, unsigned nr_inputs, unsigned *tri_size) * bins for the tiles which we overlap. */ static void -do_triangle_ccw(struct setup_context *setup, +do_triangle_ccw(struct lp_setup_context *setup, const float (*v1)[4], const float (*v2)[4], const float (*v3)[4], boolean frontfacing ) { /* x/y positions in fixed point */ - const int x1 = subpixel_snap(v1[0][0]); - const int x2 = subpixel_snap(v2[0][0]); - const int x3 = subpixel_snap(v3[0][0]); - const int y1 = subpixel_snap(v1[0][1]); - const int y2 = subpixel_snap(v2[0][1]); - const int y3 = subpixel_snap(v3[0][1]); + const int x1 = subpixel_snap(v1[0][0] + 0.5 - setup->pixel_offset); + const int x2 = subpixel_snap(v2[0][0] + 0.5 - setup->pixel_offset); + const int x3 = subpixel_snap(v3[0][0] + 0.5 - setup->pixel_offset); + const int y1 = subpixel_snap(v1[0][1] + 0.5 - setup->pixel_offset); + const int y2 = subpixel_snap(v2[0][1] + 0.5 - setup->pixel_offset); + const int y3 = subpixel_snap(v3[0][1] + 0.5 - setup->pixel_offset); struct lp_scene *scene = lp_setup_get_current_scene(setup); struct lp_rast_triangle *tri; @@ -565,7 +570,7 @@ do_triangle_ccw(struct setup_context *setup, } -static void triangle_cw( struct setup_context *setup, +static void triangle_cw( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], const float (*v2)[4] ) @@ -574,7 +579,7 @@ static void triangle_cw( struct setup_context *setup, } -static void triangle_ccw( struct setup_context *setup, +static void triangle_ccw( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], const float (*v2)[4] ) @@ -583,7 +588,7 @@ static void triangle_ccw( struct setup_context *setup, } -static void triangle_both( struct setup_context *setup, +static void triangle_both( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], const float (*v2)[4] ) @@ -602,7 +607,7 @@ static void triangle_both( struct setup_context *setup, } -static void triangle_nop( struct setup_context *setup, +static void triangle_nop( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], const float (*v2)[4] ) @@ -611,7 +616,7 @@ static void triangle_nop( struct setup_context *setup, void -lp_setup_choose_triangle( struct setup_context *setup ) +lp_setup_choose_triangle( struct lp_setup_context *setup ) { switch (setup->cullmode) { case PIPE_WINDING_NONE: diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c index 24291da91e4..d7336d82b21 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c @@ -48,10 +48,10 @@ /** cast wrapper */ -static struct setup_context * -setup_context(struct vbuf_render *vbr) +static struct lp_setup_context * +lp_setup_context(struct vbuf_render *vbr) { - return (struct setup_context *) vbr; + return (struct lp_setup_context *) vbr; } @@ -59,7 +59,7 @@ setup_context(struct vbuf_render *vbr) static const struct vertex_info * lp_setup_get_vertex_info(struct vbuf_render *vbr) { - struct setup_context *setup = setup_context(vbr); + struct lp_setup_context *setup = lp_setup_context(vbr); return setup->vertex_info; } @@ -68,7 +68,7 @@ static boolean lp_setup_allocate_vertices(struct vbuf_render *vbr, ushort vertex_size, ushort nr_vertices) { - struct setup_context *setup = setup_context(vbr); + struct lp_setup_context *setup = lp_setup_context(vbr); unsigned size = vertex_size * nr_vertices; if (setup->vertex_buffer_size < size) { @@ -92,7 +92,7 @@ lp_setup_release_vertices(struct vbuf_render *vbr) static void * lp_setup_map_vertices(struct vbuf_render *vbr) { - struct setup_context *setup = setup_context(vbr); + struct lp_setup_context *setup = lp_setup_context(vbr); return setup->vertex_buffer; } @@ -101,7 +101,7 @@ lp_setup_unmap_vertices(struct vbuf_render *vbr, ushort min_index, ushort max_index ) { - struct setup_context *setup = setup_context(vbr); + struct lp_setup_context *setup = lp_setup_context(vbr); assert( setup->vertex_buffer_size >= (max_index+1) * setup->vertex_size ); /* do nothing */ } @@ -110,7 +110,7 @@ lp_setup_unmap_vertices(struct vbuf_render *vbr, static boolean lp_setup_set_primitive(struct vbuf_render *vbr, unsigned prim) { - setup_context(vbr)->prim = prim; + lp_setup_context(vbr)->prim = prim; return TRUE; } @@ -129,7 +129,7 @@ static INLINE const_float4_ptr get_vert( const void *vertex_buffer, static void lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) { - struct setup_context *setup = setup_context(vbr); + struct lp_setup_context *setup = lp_setup_context(vbr); const unsigned stride = setup->vertex_info->size * sizeof(float); const void *vertex_buffer = setup->vertex_buffer; unsigned i; @@ -231,57 +231,29 @@ lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_QUADS: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_QUAD_STRIP: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride)); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; @@ -312,7 +284,7 @@ lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) static void lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) { - struct setup_context *setup = setup_context(vbr); + struct lp_setup_context *setup = lp_setup_context(vbr); const unsigned stride = setup->vertex_info->size * sizeof(float); const void *vertex_buffer = (void *) get_vert(setup->vertex_buffer, start, stride); @@ -415,57 +387,28 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_QUADS: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; case PIPE_PRIM_QUAD_STRIP: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - setup->triangle( setup, - - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-0, stride) ); - } + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; @@ -493,7 +436,7 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) static void lp_setup_vbuf_destroy(struct vbuf_render *vbr) { - lp_setup_destroy(setup_context(vbr)); + lp_setup_destroy(lp_setup_context(vbr)); } @@ -501,7 +444,7 @@ lp_setup_vbuf_destroy(struct vbuf_render *vbr) * Create the post-transform vertex handler for the given context. */ void -lp_setup_init_vbuf(struct setup_context *setup) +lp_setup_init_vbuf(struct lp_setup_context *setup) { setup->base.max_indices = LP_MAX_VBUF_INDEXES; setup->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE; diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index 9beba32271f..be02e97648e 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -31,7 +31,7 @@ #ifndef LP_STATE_H #define LP_STATE_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include "pipe/p_state.h" #include "tgsi/tgsi_scan.h" @@ -50,7 +50,7 @@ #define LP_NEW_DEPTH_STENCIL_ALPHA 0x100 #define LP_NEW_CONSTANTS 0x200 #define LP_NEW_SAMPLER 0x400 -#define LP_NEW_TEXTURE 0x800 +#define LP_NEW_SAMPLER_VIEW 0x800 #define LP_NEW_VERTEX 0x1000 #define LP_NEW_VS 0x2000 #define LP_NEW_QUERY 0x4000 @@ -119,6 +119,10 @@ struct lp_vertex_shader { struct draw_vertex_shader *draw_data; }; +struct lp_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; void * @@ -176,28 +180,39 @@ void *llvmpipe_create_vs_state(struct pipe_context *, void llvmpipe_bind_vs_state(struct pipe_context *, void *); void llvmpipe_delete_vs_state(struct pipe_context *, void *); +void *llvmpipe_create_vertex_elements_state(struct pipe_context *, + unsigned count, + const struct pipe_vertex_element *); +void llvmpipe_bind_vertex_elements_state(struct pipe_context *, void *); +void llvmpipe_delete_vertex_elements_state(struct pipe_context *, void *); + void llvmpipe_set_polygon_stipple( struct pipe_context *, - const struct pipe_poly_stipple * ); + const struct pipe_poly_stipple * ); void llvmpipe_set_scissor_state( struct pipe_context *, const struct pipe_scissor_state * ); -void llvmpipe_set_sampler_textures( struct pipe_context *, - unsigned num, - struct pipe_texture ** ); +void llvmpipe_set_fragment_sampler_views(struct pipe_context *, + unsigned num, + struct pipe_sampler_view **); + +void +llvmpipe_set_vertex_sampler_views(struct pipe_context *, + unsigned num, + struct pipe_sampler_view **); + +struct pipe_sampler_view * +llvmpipe_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ); void -llvmpipe_set_vertex_sampler_textures(struct pipe_context *, - unsigned num_textures, - struct pipe_texture **); +llvmpipe_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view); void llvmpipe_set_viewport_state( struct pipe_context *, const struct pipe_viewport_state * ); -void llvmpipe_set_vertex_elements(struct pipe_context *, - unsigned count, - const struct pipe_vertex_element *); - void llvmpipe_set_vertex_buffers(struct pipe_context *, unsigned count, const struct pipe_vertex_buffer *); diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index bdd906e1a73..9c91ce9238f 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -150,7 +150,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) */ if (llvmpipe->tex_timestamp != lp_screen->timestamp) { llvmpipe->tex_timestamp = lp_screen->timestamp; - llvmpipe->dirty |= LP_NEW_TEXTURE; + llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; } if (llvmpipe->dirty & (LP_NEW_RASTERIZER | @@ -164,7 +164,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) LP_NEW_DEPTH_STENCIL_ALPHA | LP_NEW_RASTERIZER | LP_NEW_SAMPLER | - LP_NEW_TEXTURE)) + LP_NEW_SAMPLER_VIEW)) llvmpipe_update_fs( llvmpipe ); if (llvmpipe->dirty & LP_NEW_BLEND_COLOR) @@ -182,10 +182,10 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) lp_setup_set_fs_constants(llvmpipe->setup, llvmpipe->constants[PIPE_SHADER_FRAGMENT]); - if (llvmpipe->dirty & LP_NEW_TEXTURE) - lp_setup_set_sampler_textures(llvmpipe->setup, - llvmpipe->num_textures, - llvmpipe->texture); + if (llvmpipe->dirty & LP_NEW_SAMPLER_VIEW) + lp_setup_set_fragment_sampler_views(llvmpipe->setup, + llvmpipe->num_fragment_sampler_views, + llvmpipe->fragment_sampler_views); llvmpipe->dirty = 0; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index c4b79dd4156..a2ec8c39435 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -40,7 +40,7 @@ * - depth/stencil test (stencil TBI) * - blending * - * This file has only the glue to assembly the fragment pipeline. The actual + * This file has only the glue to assemble the fragment pipeline. The actual * plumbing of converting Gallium state into LLVM IR is done elsewhere, in the * lp_bld_*.[ch] files, and in a complete generic and reusable way. Here we * muster the LLVM JIT execution engine to create a function that follows an @@ -95,6 +95,9 @@ #include "lp_tex_sample.h" +#include <llvm-c/Analysis.h> + + static const unsigned char quad_offset_x[4] = {0, 1, 0, 1}; static const unsigned char quad_offset_y[4] = {0, 0, 1, 1}; @@ -249,7 +252,7 @@ generate_tri_edge_mask(LLVMBuilderRef builder, LLVMConstInt(LLVMInt32Type(), INT_MIN, 0), ""); - in_out_mask = lp_build_int_const_scalar(i32_type, ~0); + in_out_mask = lp_build_const_int_vec(i32_type, ~0); lp_build_flow_scope_declare(flow, &in_out_mask); @@ -364,7 +367,7 @@ build_int32_vec_const(int value) i32_type.norm = FALSE; /* values are not normalized */ i32_type.width = 32; /* 32-bit int values */ i32_type.length = 4; /* 4 elements per vector */ - return lp_build_int_const_scalar(i32_type, value); + return lp_build_const_int_vec(i32_type, value); } @@ -1091,7 +1094,7 @@ make_variant_key(struct llvmpipe_context *lp, for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) - lp_sampler_static_state(&key->sampler[i], lp->texture[i], lp->sampler[i]); + lp_sampler_static_state(&key->sampler[i], lp->fragment_sampler_views[i]->texture, lp->sampler[i]); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c index feb012816c9..6df3ef25b0e 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c +++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c @@ -62,7 +62,8 @@ void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, lp_setup_set_triangle_state( llvmpipe->setup, llvmpipe->rasterizer->cull_mode, llvmpipe->rasterizer->front_winding == PIPE_WINDING_CCW, - llvmpipe->rasterizer->scissor); + llvmpipe->rasterizer->scissor, + llvmpipe->rasterizer->gl_rasterization_rules); } llvmpipe->dirty |= LP_NEW_RASTERIZER; diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c index b30a0757768..2645441b58c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c @@ -105,8 +105,9 @@ llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe, void -llvmpipe_set_sampler_textures(struct pipe_context *pipe, - unsigned num, struct pipe_texture **texture) +llvmpipe_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); uint i; @@ -114,51 +115,79 @@ llvmpipe_set_sampler_textures(struct pipe_context *pipe, assert(num <= PIPE_MAX_SAMPLERS); /* Check for no-op */ - if (num == llvmpipe->num_textures && - !memcmp(llvmpipe->texture, texture, num * sizeof(struct pipe_texture *))) + if (num == llvmpipe->num_fragment_sampler_views && + !memcmp(llvmpipe->fragment_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) return; draw_flush(llvmpipe->draw); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - struct pipe_texture *tex = i < num ? texture[i] : NULL; + struct pipe_sampler_view *view = i < num ? views[i] : NULL; - pipe_texture_reference(&llvmpipe->texture[i], tex); + pipe_sampler_view_reference(&llvmpipe->fragment_sampler_views[i], view); } - llvmpipe->num_textures = num; + llvmpipe->num_fragment_sampler_views = num; - llvmpipe->dirty |= LP_NEW_TEXTURE; + llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; } void -llvmpipe_set_vertex_sampler_textures(struct pipe_context *pipe, - unsigned num_textures, - struct pipe_texture **textures) +llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); uint i; - assert(num_textures <= PIPE_MAX_VERTEX_SAMPLERS); + assert(num <= PIPE_MAX_VERTEX_SAMPLERS); /* Check for no-op */ - if (num_textures == llvmpipe->num_vertex_textures && - !memcmp(llvmpipe->vertex_textures, textures, num_textures * sizeof(struct pipe_texture *))) { + if (num == llvmpipe->num_vertex_sampler_views && + !memcmp(llvmpipe->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) { return; } draw_flush(llvmpipe->draw); for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - struct pipe_texture *tex = i < num_textures ? textures[i] : NULL; + struct pipe_sampler_view *view = i < num ? views[i] : NULL; - pipe_texture_reference(&llvmpipe->vertex_textures[i], tex); + pipe_sampler_view_reference(&llvmpipe->vertex_sampler_views[i], view); } - llvmpipe->num_vertex_textures = num_textures; + llvmpipe->num_vertex_sampler_views = num; - llvmpipe->dirty |= LP_NEW_TEXTURE; + llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; +} + + +struct pipe_sampler_view * +llvmpipe_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +void +llvmpipe_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c index 57ac25ea0cb..f6427aa908e 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c +++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c @@ -35,24 +35,41 @@ #include "draw/draw_context.h" +void * +llvmpipe_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) +{ + struct lp_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct lp_velems_state *) MALLOC(sizeof(struct lp_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + void -llvmpipe_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *attribs) +llvmpipe_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); + struct lp_velems_state *lp_velems = (struct lp_velems_state *) velems; - assert(count <= PIPE_MAX_ATTRIBS); - - memcpy(llvmpipe->vertex_element, attribs, - count * sizeof(struct pipe_vertex_element)); - llvmpipe->num_vertex_elements = count; + llvmpipe->velems = lp_velems; llvmpipe->dirty |= LP_NEW_VERTEX; - draw_set_vertex_elements(llvmpipe->draw, count, attribs); + if (velems) + draw_set_vertex_elements(llvmpipe->draw, lp_velems->count, lp_velems->velem); } +void +llvmpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} void llvmpipe_set_vertex_buffers(struct pipe_context *pipe, diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index 6110b0a193e..ca3d62c3613 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -27,6 +27,7 @@ #include "util/u_rect.h" #include "lp_context.h" +#include "lp_flush.h" #include "lp_surface.h" @@ -36,6 +37,20 @@ lp_surface_copy(struct pipe_context *pipe, struct pipe_surface *src, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { + llvmpipe_flush_texture(pipe, + dest->texture, dest->face, dest->level, + 0, /* flush_flags */ + FALSE, /* read_only */ + FALSE, /* cpu_access */ + FALSE); /* do_not_flush */ + + llvmpipe_flush_texture(pipe, + src->texture, src->face, src->level, + 0, /* flush_flags */ + TRUE, /* read_only */ + FALSE, /* cpu_access */ + FALSE); /* do_not_flush */ + util_surface_copy(pipe, FALSE, dest, destx, desty, src, srcx, srcy, diff --git a/src/gallium/drivers/llvmpipe/lp_test.h b/src/gallium/drivers/llvmpipe/lp_test.h index a9b99945f92..338a04a4878 100644 --- a/src/gallium/drivers/llvmpipe/lp_test.h +++ b/src/gallium/drivers/llvmpipe/lp_test.h @@ -41,7 +41,7 @@ #include <stdio.h> #include <float.h> -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include <llvm-c/Analysis.h> #include <llvm-c/ExecutionEngine.h> #include <llvm-c/Target.h> diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c index d05157991bb..fb595893bd0 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_format.c +++ b/src/gallium/drivers/llvmpipe/lp_test_format.c @@ -29,7 +29,7 @@ #include <stdlib.h> #include <stdio.h> -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" #include <llvm-c/Analysis.h> #include <llvm-c/ExecutionEngine.h> #include <llvm-c/Target.h> diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.h b/src/gallium/drivers/llvmpipe/lp_tex_sample.h index cb59a94464a..1228a831f3b 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.h +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.h @@ -29,7 +29,7 @@ #define LP_TEX_SAMPLE_H -#include <llvm-c/Core.h> +#include "gallivm/lp_bld.h" struct lp_sampler_static_state; diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c index 632462460a3..662508af61a 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c @@ -51,10 +51,11 @@ /** - * This provides the bridge between the sampler state store in lp_jit_context - * and lp_jit_texture and the sampler code generator. It provides the - * texture layout information required by the texture sampler code generator - * in terms of the state stored in lp_jit_context and lp_jit_texture in runtime. + * This provides the bridge between the sampler state store in + * lp_jit_context and lp_jit_texture and the sampler code + * generator. It provides the texture layout information required by + * the texture sampler code generator in terms of the state stored in + * lp_jit_context and lp_jit_texture in runtime. */ struct llvmpipe_sampler_dynamic_state { @@ -79,6 +80,9 @@ struct lp_llvm_sampler_soa /** * Fetch the specified member of the lp_jit_texture structure. + * \param emit_load if TRUE, emit the LLVM load instruction to actually + * fetch the field's value. Otherwise, just emit the + * GEP code to address the field. * * @sa http://llvm.org/docs/GetElementPtr.html */ @@ -87,9 +91,11 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, LLVMBuilderRef builder, unsigned unit, unsigned member_index, - const char *member_name) + const char *member_name, + boolean emit_load) { - struct llvmpipe_sampler_dynamic_state *state = (struct llvmpipe_sampler_dynamic_state *)base; + struct llvmpipe_sampler_dynamic_state *state = + (struct llvmpipe_sampler_dynamic_state *)base; LLVMValueRef indices[4]; LLVMValueRef ptr; LLVMValueRef res; @@ -107,7 +113,10 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), ""); - res = LLVMBuildLoad(builder, ptr, ""); + if (emit_load) + res = LLVMBuildLoad(builder, ptr, ""); + else + res = ptr; lp_build_name(res, "context.texture%u.%s", unit, member_name); @@ -116,28 +125,30 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, /** - * Helper macro to instantiate the functions that generate the code to fetch - * the members of lp_jit_texture to fulfill the sampler code generator requests. + * Helper macro to instantiate the functions that generate the code to + * fetch the members of lp_jit_texture to fulfill the sampler code + * generator requests. * - * This complexity is the price we have to pay to keep the texture sampler code - * generator a reusable module without dependencies to llvmpipe internals. + * This complexity is the price we have to pay to keep the texture + * sampler code generator a reusable module without dependencies to + * llvmpipe internals. */ -#define LP_LLVM_TEXTURE_MEMBER(_name, _index) \ +#define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \ static LLVMValueRef \ lp_llvm_texture_##_name( struct lp_sampler_dynamic_state *base, \ LLVMBuilderRef builder, \ unsigned unit) \ { \ - return lp_llvm_texture_member(base, builder, unit, _index, #_name ); \ + return lp_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \ } -LP_LLVM_TEXTURE_MEMBER(width, LP_JIT_TEXTURE_WIDTH) -LP_LLVM_TEXTURE_MEMBER(height, LP_JIT_TEXTURE_HEIGHT) -LP_LLVM_TEXTURE_MEMBER(depth, LP_JIT_TEXTURE_DEPTH) -LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL) -LP_LLVM_TEXTURE_MEMBER(stride, LP_JIT_TEXTURE_STRIDE) -LP_LLVM_TEXTURE_MEMBER(data_ptr, LP_JIT_TEXTURE_DATA) +LP_LLVM_TEXTURE_MEMBER(width, LP_JIT_TEXTURE_WIDTH, TRUE) +LP_LLVM_TEXTURE_MEMBER(height, LP_JIT_TEXTURE_HEIGHT, TRUE) +LP_LLVM_TEXTURE_MEMBER(depth, LP_JIT_TEXTURE_DEPTH, TRUE) +LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE) +LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE) +LP_LLVM_TEXTURE_MEMBER(data_ptr, LP_JIT_TEXTURE_DATA, FALSE) static void @@ -193,7 +204,7 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, sampler->dynamic_state.base.height = lp_llvm_texture_height; sampler->dynamic_state.base.depth = lp_llvm_texture_depth; sampler->dynamic_state.base.last_level = lp_llvm_texture_last_level; - sampler->dynamic_state.base.stride = lp_llvm_texture_stride; + sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride; sampler->dynamic_state.base.data_ptr = lp_llvm_texture_data_ptr; sampler->dynamic_state.static_state = static_state; sampler->dynamic_state.context_ptr = context_ptr; diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 7f456355428..93ad789c35d 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -40,9 +40,10 @@ #include "lp_context.h" #include "lp_screen.h" +#include "lp_flush.h" #include "lp_texture.h" #include "lp_tile_size.h" -#include "lp_winsys.h" +#include "state_tracker/sw_winsys.h" /** @@ -93,7 +94,7 @@ static boolean llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, struct llvmpipe_texture *lpt) { - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; /* Round up the surface size to a multiple of the tile size to * avoid tile clipping. @@ -102,6 +103,7 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, unsigned height = align(lpt->base.height0, TILE_SIZE); lpt->dt = winsys->displaytarget_create(winsys, + lpt->base.tex_usage, lpt->base.format, width, height, 16, @@ -125,7 +127,8 @@ llvmpipe_texture_create(struct pipe_screen *_screen, lpt->base.screen = &screen->base; if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) { + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { if (!llvmpipe_displaytarget_layout(screen, lpt)) goto fail; } @@ -142,60 +145,154 @@ llvmpipe_texture_create(struct pipe_screen *_screen, } -static struct pipe_texture * -llvmpipe_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) +static void +llvmpipe_texture_destroy(struct pipe_texture *pt) { - /* FIXME */ -#if 0 - struct llvmpipe_texture *lpt; - assert(screen); + struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen); + struct llvmpipe_texture *lpt = llvmpipe_texture(pt); - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; + if (lpt->dt) { + /* display target */ + struct sw_winsys *winsys = screen->winsys; + winsys->displaytarget_destroy(winsys, lpt->dt); + } + else { + /* regular texture */ + align_free(lpt->data); + } + + FREE(lpt); +} + + +/** + * Map a texture. Without any synchronization. + */ +void * +llvmpipe_texture_map(struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned zslice) +{ + struct llvmpipe_texture *lpt = llvmpipe_texture(texture); + uint8_t *map; + + if (lpt->dt) { + /* display target */ + struct llvmpipe_screen *screen = llvmpipe_screen(texture->screen); + struct sw_winsys *winsys = screen->winsys; + const unsigned usage = PIPE_BUFFER_USAGE_CPU_READ_WRITE; + + assert(face == 0); + assert(level == 0); + assert(zslice == 0); + + /* FIXME: keep map count? */ + map = winsys->displaytarget_map(winsys, lpt->dt, usage); } + else { + /* regular texture */ + unsigned offset; + unsigned stride; + + map = lpt->data; + + assert(level < LP_MAX_TEXTURE_2D_LEVELS); + + offset = lpt->level_offset[level]; + stride = lpt->stride[level]; + + /* XXX shouldn't that rather be + tex_height = align(u_minify(texture->height0, level), 2) + to account for alignment done in llvmpipe_texture_layout ? + */ + if (texture->target == PIPE_TEXTURE_CUBE) { + unsigned tex_height = u_minify(texture->height0, level); + offset += face * util_format_get_nblocksy(texture->format, tex_height) * stride; + } + else if (texture->target == PIPE_TEXTURE_3D) { + unsigned tex_height = u_minify(texture->height0, level); + offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * stride; + } + else { + assert(face == 0); + assert(zslice == 0); + } + + map += offset; + } + + return map; +} + + +/** + * Unmap a texture. Without any synchronization. + */ +void +llvmpipe_texture_unmap(struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned zslice) +{ + struct llvmpipe_texture *lpt = llvmpipe_texture(texture); + + if (lpt->dt) { + /* display target */ + struct llvmpipe_screen *lp_screen = llvmpipe_screen(texture->screen); + struct sw_winsys *winsys = lp_screen->winsys; + + assert(face == 0); + assert(level == 0); + assert(zslice == 0); + + winsys->displaytarget_unmap(winsys, lpt->dt); + } +} - lpt = CALLOC_STRUCT(llvmpipe_texture); + +static struct pipe_texture * +llvmpipe_texture_from_handle(struct pipe_screen *screen, + const struct pipe_texture *template, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; + struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture); if (!lpt) return NULL; - lpt->base = *base; + lpt->base = *template; pipe_reference_init(&lpt->base.reference, 1); lpt->base.screen = screen; - lpt->stride[0] = stride[0]; - pipe_buffer_reference(&lpt->buffer, buffer); + lpt->dt = winsys->displaytarget_from_handle(winsys, + template, + whandle, + &lpt->stride[0]); + if (!lpt->dt) + goto fail; return &lpt->base; -#else - debug_printf("llvmpipe_texture_blanket() not implemented!"); + + fail: + FREE(lpt); return NULL; -#endif } -static void -llvmpipe_texture_destroy(struct pipe_texture *pt) +static boolean +llvmpipe_texture_get_handle(struct pipe_screen *screen, + struct pipe_texture *pt, + struct winsys_handle *whandle) { - struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen); + struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; struct llvmpipe_texture *lpt = llvmpipe_texture(pt); - if (lpt->dt) { - /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; - winsys->displaytarget_destroy(winsys, lpt->dt); - } - else { - /* regular texture */ - align_free(lpt->data); - } + assert(lpt->dt); + if (!lpt->dt) + return FALSE; - FREE(lpt); + return winsys->displaytarget_get_handle(winsys, lpt->dt, whandle); } @@ -217,7 +314,6 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen, ps->format = pt->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); - ps->offset = lpt->level_offset[level]; ps->usage = usage; /* Because we are llvmpipe, anything that the state tracker @@ -243,23 +339,6 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen, ps->face = face; ps->level = level; ps->zslice = zslice; - - /* XXX shouldn't that rather be - tex_height = align(ps->height, 2); - to account for alignment done in llvmpipe_texture_layout ? - */ - if (pt->target == PIPE_TEXTURE_CUBE) { - unsigned tex_height = ps->height; - ps->offset += face * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level]; - } - else if (pt->target == PIPE_TEXTURE_3D) { - unsigned tex_height = ps->height; - ps->offset += zslice * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level]; - } - else { - assert(face == 0); - assert(zslice == 0); - } } return ps; } @@ -279,7 +358,7 @@ llvmpipe_tex_surface_destroy(struct pipe_surface *surf) static struct pipe_transfer * -llvmpipe_get_tex_transfer(struct pipe_screen *screen, +llvmpipe_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, @@ -305,24 +384,6 @@ llvmpipe_get_tex_transfer(struct pipe_screen *screen, pt->level = level; pt->zslice = zslice; - lpt->offset = lptex->level_offset[level]; - - /* XXX shouldn't that rather be - tex_height = align(u_minify(texture->height0, level), 2) - to account for alignment done in llvmpipe_texture_layout ? - */ - if (texture->target == PIPE_TEXTURE_CUBE) { - unsigned tex_height = u_minify(texture->height0, level); - lpt->offset += face * util_format_get_nblocksy(texture->format, tex_height) * pt->stride; - } - else if (texture->target == PIPE_TEXTURE_3D) { - unsigned tex_height = u_minify(texture->height0, level); - lpt->offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * pt->stride; - } - else { - assert(face == 0); - assert(zslice == 0); - } return pt; } return NULL; @@ -330,7 +391,8 @@ llvmpipe_get_tex_transfer(struct pipe_screen *screen, static void -llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer) +llvmpipe_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) { /* Effectively do the texture_update work here - if texture images * needed post-processing to put them into hardware layout, this is @@ -343,11 +405,11 @@ llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer) static void * -llvmpipe_transfer_map( struct pipe_screen *_screen, +llvmpipe_transfer_map( struct pipe_context *pipe, struct pipe_transfer *transfer ) { - struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - ubyte *map, *xfer_map; + struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); + ubyte *map; struct llvmpipe_texture *lpt; enum pipe_format format; @@ -355,52 +417,45 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, lpt = llvmpipe_texture(transfer->texture); format = lpt->base.format; - if (lpt->dt) { - /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; + /* + * Transfers, like other pipe operations, must happen in order, so flush the + * context if necessary. + */ + llvmpipe_flush_texture(pipe, + transfer->texture, transfer->face, transfer->level, + 0, /* flush_flags */ + !(transfer->usage & PIPE_TRANSFER_WRITE), /* read_only */ + TRUE, /* cpu_access */ + FALSE); /* do_not_flush */ - map = winsys->displaytarget_map(winsys, lpt->dt, - pipe_transfer_buffer_flags(transfer)); - if (map == NULL) - return NULL; - } - else { - /* regular texture */ - map = lpt->data; - } + map = llvmpipe_texture_map(transfer->texture, + transfer->face, transfer->level, transfer->zslice); /* May want to different things here depending on read/write nature * of the map: */ - if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE)) { + if (transfer->usage & PIPE_TRANSFER_WRITE) { /* Do something to notify sharing contexts of a texture change. */ screen->timestamp++; } - xfer_map = map + llvmpipe_transfer(transfer)->offset + + map += transfer->y / util_format_get_blockheight(format) * transfer->stride + transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); - /*printf("map = %p xfer map = %p\n", map, xfer_map);*/ - return xfer_map; + + return map; } static void -llvmpipe_transfer_unmap(struct pipe_screen *screen, - struct pipe_transfer *transfer) +llvmpipe_transfer_unmap(struct pipe_context *pipe, + struct pipe_transfer *transfer) { - struct llvmpipe_screen *lp_screen = llvmpipe_screen(screen); - struct llvmpipe_texture *lpt; - assert(transfer->texture); - lpt = llvmpipe_texture(transfer->texture); - if (lpt->dt) { - /* display target */ - struct llvmpipe_winsys *winsys = lp_screen->winsys; - winsys->displaytarget_unmap(winsys, lpt->dt); - } + llvmpipe_texture_unmap(transfer->texture, + transfer->face, transfer->level, transfer->zslice); } @@ -408,14 +463,19 @@ void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen) { screen->texture_create = llvmpipe_texture_create; - screen->texture_blanket = llvmpipe_texture_blanket; screen->texture_destroy = llvmpipe_texture_destroy; + screen->texture_get_handle = llvmpipe_texture_get_handle; screen->get_tex_surface = llvmpipe_get_tex_surface; screen->tex_surface_destroy = llvmpipe_tex_surface_destroy; +} + - screen->get_tex_transfer = llvmpipe_get_tex_transfer; - screen->tex_transfer_destroy = llvmpipe_tex_transfer_destroy; - screen->transfer_map = llvmpipe_transfer_map; - screen->transfer_unmap = llvmpipe_transfer_unmap; +void +llvmpipe_init_context_texture_funcs(struct pipe_context *pipe) +{ + pipe->get_tex_transfer = llvmpipe_get_tex_transfer; + pipe->tex_transfer_destroy = llvmpipe_tex_transfer_destroy; + pipe->transfer_map = llvmpipe_transfer_map; + pipe->transfer_unmap = llvmpipe_transfer_unmap; } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index 87c905bc027..2350c26e4fc 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -32,24 +32,29 @@ #include "pipe/p_state.h" +#define LP_MAX_TEXTURE_2D_LEVELS 13 /* 4K x 4K for now */ +#define LP_MAX_TEXTURE_3D_LEVELS 10 /* 512 x 512 x 512 for now */ + + struct pipe_context; struct pipe_screen; struct llvmpipe_context; -struct llvmpipe_displaytarget; + +struct sw_displaytarget; struct llvmpipe_texture { struct pipe_texture base; - unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS]; - unsigned stride[PIPE_MAX_TEXTURE_LEVELS]; + unsigned long level_offset[LP_MAX_TEXTURE_2D_LEVELS]; + unsigned stride[LP_MAX_TEXTURE_2D_LEVELS]; /** * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET * usage. */ - struct llvmpipe_displaytarget *dt; + struct sw_displaytarget *dt; /** * Malloc'ed data for regular textures, or a mapping to dt above. @@ -90,8 +95,32 @@ llvmpipe_transfer(struct pipe_transfer *pt) } +static INLINE unsigned +llvmpipe_texture_stride(struct pipe_texture *texture, + unsigned level) +{ + struct llvmpipe_texture *lpt = llvmpipe_texture(texture); + assert(level < LP_MAX_TEXTURE_2D_LEVELS); + return lpt->stride[level]; +} + + +void * +llvmpipe_texture_map(struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned zslice); + +void +llvmpipe_texture_unmap(struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned zslice); + extern void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen); +extern void +llvmpipe_init_context_texture_funcs(struct pipe_context *pipe); #endif /* LP_TEXTURE_H */ diff --git a/src/gallium/drivers/nouveau/Makefile b/src/gallium/drivers/nouveau/Makefile index 0e02680bc63..0cb66041d50 100644 --- a/src/gallium/drivers/nouveau/Makefile +++ b/src/gallium/drivers/nouveau/Makefile @@ -4,7 +4,6 @@ include $(TOP)/configs/current LIBNAME = nouveau C_SOURCES = nouveau_screen.c \ - nouveau_context.c \ - nv04_surface_2d.c + nouveau_context.c include ../../Makefile.template diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index 3c2f771b51e..b1ad686022a 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -4,6 +4,7 @@ #include "util/u_memory.h" #include "util/u_inlines.h" +#include "util/u_format.h" #include <stdio.h> #include <errno.h> @@ -12,6 +13,9 @@ #include "nouveau_winsys.h" #include "nouveau_screen.h" +/* XXX this should go away */ +#include "state_tracker/drm_api.h" + static const char * nouveau_screen_get_name(struct pipe_screen *pscreen) { @@ -120,7 +124,7 @@ nouveau_screen_map_flags(unsigned pipe) if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK) flags |= NOUVEAU_BO_NOWAIT; else - if (pipe & 0 /*PIPE_BUFFER_USAGE_UNSYNCHRONIZED*/) + if (pipe & PIPE_BUFFER_USAGE_UNSYNCHRONIZED) flags |= NOUVEAU_BO_NOSYNC; return flags; @@ -231,6 +235,72 @@ nouveau_screen_fence_finish(struct pipe_screen *screen, return 0; } + +/* + * Both texture_{from|get}_handle use drm api defines directly which they + * shouldn't do. The problem is that from|get are pipe functions and as + * such they should be defined in the pipe level. If nouveau had a propper + * winsys interface we would have added from|get to that interface using + * the winsys_handle struct as done with other drivers. However this code + * calls directly into the libdrm_nouveau.so functions (nouveau_bo_*). So + * we need to translate the handle into something they understand. + */ +static struct pipe_texture * +nouveau_screen_texture_from_handle(struct pipe_screen *pscreen, + const struct pipe_texture *templ, + struct winsys_handle *whandle) +{ + struct nouveau_device *dev = nouveau_screen(pscreen)->device; + struct pipe_texture *pt; + struct pipe_buffer *pb; + int ret; + + pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*)); + if (!pb) + return NULL; + + ret = nouveau_bo_handle_ref(dev, whandle->handle, (struct nouveau_bo**)(pb+1)); + if (ret) { + debug_printf("%s: ref name 0x%08x failed with %d\n", + __func__, whandle->handle, ret); + FREE(pb); + return NULL; + } + + pipe_reference_init(&pb->reference, 1); + pb->screen = pscreen; + pb->alignment = 0; + pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | + PIPE_BUFFER_USAGE_CPU_READ_WRITE; + pb->size = nouveau_bo(pb)->size; + pt = nouveau_screen(pscreen)->texture_blanket(pscreen, templ, + &whandle->stride, pb); + pipe_buffer_reference(&pb, NULL); + return pt; +} + +static boolean +nouveau_screen_texture_get_handle(struct pipe_screen *pscreen, + struct pipe_texture *pt, + struct winsys_handle *whandle) +{ + struct nouveau_miptree *mt = nouveau_miptree(pt); + + if (!mt || !mt->bo) + return false; + + whandle->stride = util_format_get_stride(mt->base.format, mt->base.width0); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + return nouveau_bo_handle_get(mt->bo, &whandle->handle) == 0; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = mt->bo->handle; + return TRUE; + } else { + return FALSE; + } +} + int nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) { @@ -258,6 +328,9 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) pscreen->fence_signalled = nouveau_screen_fence_signalled; pscreen->fence_finish = nouveau_screen_fence_finish; + pscreen->texture_from_handle = nouveau_screen_texture_from_handle; + pscreen->texture_get_handle = nouveau_screen_texture_get_handle; + return 0; } diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h index a7927d88dfc..f4a7a2bc234 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.h +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -6,6 +6,18 @@ struct nouveau_screen { struct nouveau_device *device; struct nouveau_channel *channel; + /** + * Create a new texture object, using the given template info, but on top of + * existing memory. + * + * It is assumed that the buffer data is layed out according to the expected + * by the hardware. NULL will be returned if any inconsistency is found. + */ + struct pipe_texture * (*texture_blanket)(struct pipe_screen *, + const struct pipe_texture *templat, + const unsigned *stride, + struct pipe_buffer *buffer); + int (*pre_pipebuffer_map_callback) (struct pipe_screen *pscreen, struct pipe_buffer *pb, unsigned usage); }; diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h index a10114beab9..ab7761a31da 100644 --- a/src/gallium/drivers/nouveau/nouveau_util.h +++ b/src/gallium/drivers/nouveau/nouveau_util.h @@ -33,7 +33,7 @@ nouveau_vbuf_split(unsigned remaining, unsigned overhead, unsigned vpp, max = max - (max % 3); break; case PIPE_PRIM_QUADS: - max = max & 3; + max = max & ~3; break; case PIPE_PRIM_LINE_LOOP: case PIPE_PRIM_LINE_STRIP: @@ -88,4 +88,104 @@ static INLINE unsigned log2i(unsigned i) return r; } +struct u_split_prim { + void *priv; + void (*emit)(void *priv, unsigned start, unsigned count); + void (*edge)(void *priv, boolean enabled); + + unsigned mode; + unsigned start; + unsigned p_start; + unsigned p_end; + + int repeat_first:1; + int close_first:1; + int edgeflag_off:1; +}; + +static inline void +u_split_prim_init(struct u_split_prim *s, + unsigned mode, unsigned start, unsigned count) +{ + if (mode == PIPE_PRIM_LINE_LOOP) { + s->mode = PIPE_PRIM_LINE_STRIP; + s->close_first = 1; + } else { + s->mode = mode; + s->close_first = 0; + } + s->start = start; + s->p_start = start; + s->p_end = start + count; + s->edgeflag_off = 0; + s->repeat_first = 0; +} + +static INLINE boolean +u_split_prim_next(struct u_split_prim *s, unsigned max_verts) +{ + int repeat = 0; + + if (s->repeat_first) { + s->emit(s->priv, s->start, 1); + max_verts--; + if (s->edgeflag_off) { + s->edge(s->priv, TRUE); + s->edgeflag_off = FALSE; + } + } + + if (s->p_start + s->close_first + max_verts >= s->p_end) { + s->emit(s->priv, s->p_start, s->p_end - s->p_start); + if (s->close_first) + s->emit(s->priv, s->start, 1); + return TRUE; + } + + switch (s->mode) { + case PIPE_PRIM_LINES: + max_verts &= ~1; + break; + case PIPE_PRIM_LINE_STRIP: + repeat = 1; + break; + case PIPE_PRIM_POLYGON: + max_verts--; + s->emit(s->priv, s->p_start, max_verts); + s->edge(s->priv, FALSE); + s->emit(s->priv, s->p_start + max_verts, 1); + s->p_start += max_verts; + s->repeat_first = TRUE; + s->edgeflag_off = TRUE; + return FALSE; + case PIPE_PRIM_TRIANGLES: + max_verts = max_verts - (max_verts % 3); + break; + case PIPE_PRIM_TRIANGLE_STRIP: + /* to ensure winding stays correct, always split + * on an even number of generated triangles + */ + max_verts = max_verts & ~1; + repeat = 2; + break; + case PIPE_PRIM_TRIANGLE_FAN: + s->repeat_first = TRUE; + repeat = 1; + break; + case PIPE_PRIM_QUADS: + max_verts &= ~3; + break; + case PIPE_PRIM_QUAD_STRIP: + max_verts &= ~1; + repeat = 2; + break; + default: + break; + } + + s->emit (s->priv, s->p_start, max_verts); + s->p_start += (max_verts - repeat); + return FALSE; +} + #endif diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index af9ddd558c8..bed014b9ce0 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -27,10 +27,7 @@ #define NOUVEAU_BUFFER_USAGE_NO_RENDER (1 << 19) extern struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *); - -extern struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *); +nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_screen * nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *); diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile deleted file mode 100644 index 364c80d8f3e..00000000000 --- a/src/gallium/drivers/nv30/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -LIBNAME = nv30 - -C_SOURCES = \ - nv30_clear.c \ - nv30_context.c \ - nv30_draw.c \ - nv30_fragprog.c \ - nv30_fragtex.c \ - nv30_miptree.c \ - nv30_query.c \ - nv30_screen.c \ - nv30_state.c \ - nv30_state_blend.c \ - nv30_state_emit.c \ - nv30_state_fb.c \ - nv30_state_rasterizer.c \ - nv30_state_scissor.c \ - nv30_state_stipple.c \ - nv30_state_viewport.c \ - nv30_state_zsa.c \ - nv30_surface.c \ - nv30_transfer.c \ - nv30_vbo.c \ - nv30_vertprog.c - -include ../../Makefile.template diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c deleted file mode 100644 index c4ba9266647..00000000000 --- a/src/gallium/drivers/nv30/nv30_clear.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_clear.h" - -#include "nv30_context.h" - -void -nv30_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil) -{ - util_clear(pipe, &nv30_context(pipe)->framebuffer, buffers, rgba, depth, - stencil); -} diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c deleted file mode 100644 index 279b74445ca..00000000000 --- a/src/gallium/drivers/nv30/nv30_context.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "draw/draw_context.h" -#include "pipe/p_defines.h" - -#include "nv30_context.h" -#include "nv30_screen.h" - -static void -nv30_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - - if (flags & PIPE_FLUSH_TEXTURE_CACHE) { - BEGIN_RING(chan, rankine, 0x1fd8, 1); - OUT_RING (chan, 2); - BEGIN_RING(chan, rankine, 0x1fd8, 1); - OUT_RING (chan, 1); - } - - FIRE_RING(chan); - if (fence) - *fence = NULL; -} - -static void -nv30_destroy(struct pipe_context *pipe) -{ - struct nv30_context *nv30 = nv30_context(pipe); - unsigned i; - - for (i = 0; i < NV30_STATE_MAX; i++) { - if (nv30->state.hw[i]) - so_ref(NULL, &nv30->state.hw[i]); - } - - if (nv30->draw) - draw_destroy(nv30->draw); - FREE(nv30); -} - -struct pipe_context * -nv30_create(struct pipe_screen *pscreen, void *priv) -{ - struct nv30_screen *screen = nv30_screen(pscreen); - struct pipe_winsys *ws = pscreen->winsys; - struct nv30_context *nv30; - struct nouveau_winsys *nvws = screen->nvws; - - nv30 = CALLOC(1, sizeof(struct nv30_context)); - if (!nv30) - return NULL; - nv30->screen = screen; - - nv30->nvws = nvws; - - nv30->pipe.winsys = ws; - nv30->pipe.screen = pscreen; - nv30->pipe.priv = priv; - nv30->pipe.destroy = nv30_destroy; - nv30->pipe.draw_arrays = nv30_draw_arrays; - nv30->pipe.draw_elements = nv30_draw_elements; - nv30->pipe.clear = nv30_clear; - nv30->pipe.flush = nv30_flush; - - nv30->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv30->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - - screen->base.channel->user_private = nv30; - screen->base.channel->flush_notify = nv30_state_flush_notify; - - nv30_init_query_functions(nv30); - nv30_init_surface_functions(nv30); - nv30_init_state_functions(nv30); - - /* Create, configure, and install fallback swtnl path */ - nv30->draw = draw_create(); - draw_wide_point_threshold(nv30->draw, 9999999.0); - draw_wide_line_threshold(nv30->draw, 9999999.0); - draw_enable_line_stipple(nv30->draw, FALSE); - draw_enable_point_sprites(nv30->draw, FALSE); - draw_set_rasterize_stage(nv30->draw, nv30_draw_render_stage(nv30)); - - return &nv30->pipe; -} diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h deleted file mode 100644 index ea259aadf35..00000000000 --- a/src/gallium/drivers/nv30/nv30_context.h +++ /dev/null @@ -1,218 +0,0 @@ -#ifndef __NV30_CONTEXT_H__ -#define __NV30_CONTEXT_H__ - -#include <stdio.h> - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_inlines.h" - -#include "draw/draw_vertex.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_gldefs.h" -#include "nouveau/nouveau_context.h" -#include "nouveau/nouveau_stateobj.h" - -#include "nv30_state.h" - -#define NOUVEAU_ERR(fmt, args...) \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); -#define NOUVEAU_MSG(fmt, args...) \ - fprintf(stderr, "nouveau: "fmt, ##args); - -enum nv30_state_index { - NV30_STATE_FB = 0, - NV30_STATE_VIEWPORT = 1, - NV30_STATE_BLEND = 2, - NV30_STATE_RAST = 3, - NV30_STATE_ZSA = 4, - NV30_STATE_BCOL = 5, - NV30_STATE_CLIP = 6, - NV30_STATE_SCISSOR = 7, - NV30_STATE_STIPPLE = 8, - NV30_STATE_FRAGPROG = 9, - NV30_STATE_VERTPROG = 10, - NV30_STATE_FRAGTEX0 = 11, - NV30_STATE_FRAGTEX1 = 12, - NV30_STATE_FRAGTEX2 = 13, - NV30_STATE_FRAGTEX3 = 14, - NV30_STATE_FRAGTEX4 = 15, - NV30_STATE_FRAGTEX5 = 16, - NV30_STATE_FRAGTEX6 = 17, - NV30_STATE_FRAGTEX7 = 18, - NV30_STATE_FRAGTEX8 = 19, - NV30_STATE_FRAGTEX9 = 20, - NV30_STATE_FRAGTEX10 = 21, - NV30_STATE_FRAGTEX11 = 22, - NV30_STATE_FRAGTEX12 = 23, - NV30_STATE_FRAGTEX13 = 24, - NV30_STATE_FRAGTEX14 = 25, - NV30_STATE_FRAGTEX15 = 26, - NV30_STATE_VERTTEX0 = 27, - NV30_STATE_VERTTEX1 = 28, - NV30_STATE_VERTTEX2 = 29, - NV30_STATE_VERTTEX3 = 30, - NV30_STATE_VTXBUF = 31, - NV30_STATE_VTXFMT = 32, - NV30_STATE_VTXATTR = 33, - NV30_STATE_SR = 34, - NV30_STATE_MAX = 35 -}; - -#include "nv30_screen.h" - -#define NV30_NEW_BLEND (1 << 0) -#define NV30_NEW_RAST (1 << 1) -#define NV30_NEW_ZSA (1 << 2) -#define NV30_NEW_SAMPLER (1 << 3) -#define NV30_NEW_FB (1 << 4) -#define NV30_NEW_STIPPLE (1 << 5) -#define NV30_NEW_SCISSOR (1 << 6) -#define NV30_NEW_VIEWPORT (1 << 7) -#define NV30_NEW_BCOL (1 << 8) -#define NV30_NEW_VERTPROG (1 << 9) -#define NV30_NEW_FRAGPROG (1 << 10) -#define NV30_NEW_ARRAYS (1 << 11) -#define NV30_NEW_UCP (1 << 12) -#define NV30_NEW_SR (1 << 13) - -struct nv30_rasterizer_state { - struct pipe_rasterizer_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv30_zsa_state { - struct pipe_depth_stencil_alpha_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv30_blend_state { - struct pipe_blend_state pipe; - struct nouveau_stateobj *so; -}; - - -struct nv30_state { - unsigned scissor_enabled; - unsigned stipple_enabled; - unsigned fp_samplers; - - uint64_t dirty; - struct nouveau_stateobj *hw[NV30_STATE_MAX]; -}; - -struct nv30_context { - struct pipe_context pipe; - - struct nouveau_winsys *nvws; - struct nv30_screen *screen; - - struct draw_context *draw; - - /* HW state derived from pipe states */ - struct nv30_state state; - - /* Context state */ - unsigned dirty; - struct pipe_scissor_state scissor; - unsigned stipple[32]; - struct nv30_vertex_program *vertprog; - struct nv30_fragment_program *fragprog; - struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; - unsigned constbuf_nr[PIPE_SHADER_TYPES]; - struct nv30_rasterizer_state *rasterizer; - struct nv30_zsa_state *zsa; - struct nv30_blend_state *blend; - struct pipe_blend_color blend_colour; - struct pipe_stencil_ref stencil_ref; - struct pipe_viewport_state viewport; - struct pipe_framebuffer_state framebuffer; - struct pipe_buffer *idxbuf; - unsigned idxbuf_format; - struct nv30_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; - struct nv30_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; - unsigned nr_samplers; - unsigned nr_textures; - unsigned dirty_samplers; - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - unsigned vtxbuf_nr; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; - unsigned vtxelt_nr; -}; - -static INLINE struct nv30_context * -nv30_context(struct pipe_context *pipe) -{ - return (struct nv30_context *)pipe; -} - -struct nv30_state_entry { - boolean (*validate)(struct nv30_context *nv30); - struct { - unsigned pipe; - unsigned hw; - } dirty; -}; - -extern void nv30_init_state_functions(struct nv30_context *nv30); -extern void nv30_init_surface_functions(struct nv30_context *nv30); -extern void nv30_init_query_functions(struct nv30_context *nv30); - -extern void nv30_screen_init_miptree_functions(struct pipe_screen *pscreen); - -/* nv30_draw.c */ -extern struct draw_stage *nv30_draw_render_stage(struct nv30_context *nv30); - -/* nv30_vertprog.c */ -extern void nv30_vertprog_destroy(struct nv30_context *, - struct nv30_vertex_program *); - -/* nv30_fragprog.c */ -extern void nv30_fragprog_destroy(struct nv30_context *, - struct nv30_fragment_program *); - -/* nv30_fragtex.c */ -extern void nv30_fragtex_bind(struct nv30_context *); - -/* nv30_state.c and friends */ -extern boolean nv30_state_validate(struct nv30_context *nv30); -extern void nv30_state_emit(struct nv30_context *nv30); -extern void nv30_state_flush_notify(struct nouveau_channel *chan); -extern struct nv30_state_entry nv30_state_rasterizer; -extern struct nv30_state_entry nv30_state_scissor; -extern struct nv30_state_entry nv30_state_stipple; -extern struct nv30_state_entry nv30_state_fragprog; -extern struct nv30_state_entry nv30_state_vertprog; -extern struct nv30_state_entry nv30_state_blend; -extern struct nv30_state_entry nv30_state_blend_colour; -extern struct nv30_state_entry nv30_state_zsa; -extern struct nv30_state_entry nv30_state_viewport; -extern struct nv30_state_entry nv30_state_framebuffer; -extern struct nv30_state_entry nv30_state_fragtex; -extern struct nv30_state_entry nv30_state_vbo; -extern struct nv30_state_entry nv30_state_sr; - -/* nv30_vbo.c */ -extern void nv30_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv30_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, - unsigned count); - -/* nv30_clear.c */ -extern void nv30_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil); - -/* nv30_context.c */ -struct pipe_context * -nv30_create(struct pipe_screen *pscreen, void *priv); - -#endif diff --git a/src/gallium/drivers/nv30/nv30_draw.c b/src/gallium/drivers/nv30/nv30_draw.c deleted file mode 100644 index 74fc138c051..00000000000 --- a/src/gallium/drivers/nv30/nv30_draw.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "draw/draw_pipe.h" - -#include "nv30_context.h" - -struct nv30_draw_stage { - struct draw_stage draw; - struct nv30_context *nv30; -}; - -static void -nv30_draw_point(struct draw_stage *draw, struct prim_header *prim) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_line(struct draw_stage *draw, struct prim_header *prim) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_tri(struct draw_stage *draw, struct prim_header *prim) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_flush(struct draw_stage *draw, unsigned flags) -{ -} - -static void -nv30_draw_reset_stipple_counter(struct draw_stage *draw) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_destroy(struct draw_stage *draw) -{ - FREE(draw); -} - -struct draw_stage * -nv30_draw_render_stage(struct nv30_context *nv30) -{ - struct nv30_draw_stage *nv30draw = CALLOC_STRUCT(nv30_draw_stage); - - nv30draw->nv30 = nv30; - nv30draw->draw.draw = nv30->draw; - nv30draw->draw.point = nv30_draw_point; - nv30draw->draw.line = nv30_draw_line; - nv30draw->draw.tri = nv30_draw_tri; - nv30draw->draw.flush = nv30_draw_flush; - nv30draw->draw.reset_stipple_counter = nv30_draw_reset_stipple_counter; - nv30draw->draw.destroy = nv30_draw_destroy; - - return &nv30draw->draw; -} - diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c deleted file mode 100644 index 2c432c6dfa7..00000000000 --- a/src/gallium/drivers/nv30/nv30_fragprog.c +++ /dev/null @@ -1,905 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_util.h" - -#include "nv30_context.h" - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 1 -#define MASK_Y 2 -#define MASK_Z 4 -#define MASK_W 8 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE NV30_FP_OP_DST_SCALE_1X -#define DEF_CTEST NV30_FP_OP_COND_TR -#include "nv30_shader.h" - -#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv30_sr_neg((s)) -#define abs(s) nv30_sr_abs((s)) -#define scale(s,v) nv30_sr_scale((s), NV30_FP_OP_DST_SCALE_##v) - -#define MAX_CONSTS 128 -#define MAX_IMM 32 -struct nv30_fpc { - struct nv30_fragment_program *fp; - - uint attrib_map[PIPE_MAX_SHADER_INPUTS]; - - int high_temp; - int temp_temp_count; - int num_regs; - - uint depth_id; - uint colour_id; - - unsigned inst_offset; - - struct { - int pipe; - float vals[4]; - } consts[MAX_CONSTS]; - int nr_consts; - - struct nv30_sreg imm[MAX_IMM]; - unsigned nr_imm; -}; - -static INLINE struct nv30_sreg -temp(struct nv30_fpc *fpc) -{ - int idx; - - idx = fpc->temp_temp_count++; - idx += fpc->high_temp + 1; - return nv30_sr(NV30SR_TEMP, idx); -} - -static INLINE struct nv30_sreg -constant(struct nv30_fpc *fpc, int pipe, float vals[4]) -{ - int idx; - - if (fpc->nr_consts == MAX_CONSTS) - assert(0); - idx = fpc->nr_consts++; - - fpc->consts[idx].pipe = pipe; - if (pipe == -1) - memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float)); - return nv30_sr(NV30SR_CONST, idx); -} - -#define arith(cc,s,o,d,m,s0,s1,s2) \ - nv30_fp_arith((cc), (s), NV30_FP_OP_OPCODE_##o, \ - (d), (m), (s0), (s1), (s2)) -#define tex(cc,s,o,u,d,m,s0,s1,s2) \ - nv30_fp_tex((cc), (s), NV30_FP_OP_OPCODE_##o, (u), \ - (d), (m), (s0), none, none) - -static void -grow_insns(struct nv30_fpc *fpc, int size) -{ - struct nv30_fragment_program *fp = fpc->fp; - - fp->insn_len += size; - fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len); -} - -static void -emit_src(struct nv30_fpc *fpc, int pos, struct nv30_sreg src) -{ - struct nv30_fragment_program *fp = fpc->fp; - uint32_t *hw = &fp->insn[fpc->inst_offset]; - uint32_t sr = 0; - - switch (src.type) { - case NV30SR_INPUT: - sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT); - hw[0] |= (src.index << NV30_FP_OP_INPUT_SRC_SHIFT); - break; - case NV30SR_OUTPUT: - sr |= NV30_FP_REG_SRC_HALF; - /* fall-through */ - case NV30SR_TEMP: - sr |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT); - sr |= (src.index << NV30_FP_REG_SRC_SHIFT); - break; - case NV30SR_CONST: - grow_insns(fpc, 4); - hw = &fp->insn[fpc->inst_offset]; - if (fpc->consts[src.index].pipe >= 0) { - struct nv30_fragment_program_data *fpd; - - fp->consts = realloc(fp->consts, ++fp->nr_consts * - sizeof(*fpd)); - fpd = &fp->consts[fp->nr_consts - 1]; - fpd->offset = fpc->inst_offset + 4; - fpd->index = fpc->consts[src.index].pipe; - memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4); - } else { - memcpy(&fp->insn[fpc->inst_offset + 4], - fpc->consts[src.index].vals, - sizeof(uint32_t) * 4); - } - - sr |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT); - break; - case NV30SR_NONE: - sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT); - break; - default: - assert(0); - } - - if (src.negate) - sr |= NV30_FP_REG_NEGATE; - - if (src.abs) - hw[1] |= (1 << (29 + pos)); - - sr |= ((src.swz[0] << NV30_FP_REG_SWZ_X_SHIFT) | - (src.swz[1] << NV30_FP_REG_SWZ_Y_SHIFT) | - (src.swz[2] << NV30_FP_REG_SWZ_Z_SHIFT) | - (src.swz[3] << NV30_FP_REG_SWZ_W_SHIFT)); - - hw[pos + 1] |= sr; -} - -static void -emit_dst(struct nv30_fpc *fpc, struct nv30_sreg dst) -{ - struct nv30_fragment_program *fp = fpc->fp; - uint32_t *hw = &fp->insn[fpc->inst_offset]; - - switch (dst.type) { - case NV30SR_TEMP: - if (fpc->num_regs < (dst.index + 1)) - fpc->num_regs = dst.index + 1; - break; - case NV30SR_OUTPUT: - if (dst.index == 1) { - fp->fp_control |= 0xe; - } else { - hw[0] |= NV30_FP_OP_OUT_REG_HALF; - } - break; - case NV30SR_NONE: - hw[0] |= (1 << 30); - break; - default: - assert(0); - } - - hw[0] |= (dst.index << NV30_FP_OP_OUT_REG_SHIFT); -} - -static void -nv30_fp_arith(struct nv30_fpc *fpc, int sat, int op, - struct nv30_sreg dst, int mask, - struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2) -{ - struct nv30_fragment_program *fp = fpc->fp; - uint32_t *hw; - - fpc->inst_offset = fp->insn_len; - grow_insns(fpc, 4); - hw = &fp->insn[fpc->inst_offset]; - memset(hw, 0, sizeof(uint32_t) * 4); - - if (op == NV30_FP_OP_OPCODE_KIL) - fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL; - hw[0] |= (op << NV30_FP_OP_OPCODE_SHIFT); - hw[0] |= (mask << NV30_FP_OP_OUTMASK_SHIFT); - hw[2] |= (dst.dst_scale << NV30_FP_OP_DST_SCALE_SHIFT); - - if (sat) - hw[0] |= NV30_FP_OP_OUT_SAT; - - if (dst.cc_update) - hw[0] |= NV30_FP_OP_COND_WRITE_ENABLE; - hw[1] |= (dst.cc_test << NV30_FP_OP_COND_SHIFT); - hw[1] |= ((dst.cc_swz[0] << NV30_FP_OP_COND_SWZ_X_SHIFT) | - (dst.cc_swz[1] << NV30_FP_OP_COND_SWZ_Y_SHIFT) | - (dst.cc_swz[2] << NV30_FP_OP_COND_SWZ_Z_SHIFT) | - (dst.cc_swz[3] << NV30_FP_OP_COND_SWZ_W_SHIFT)); - - emit_dst(fpc, dst); - emit_src(fpc, 0, s0); - emit_src(fpc, 1, s1); - emit_src(fpc, 2, s2); -} - -static void -nv30_fp_tex(struct nv30_fpc *fpc, int sat, int op, int unit, - struct nv30_sreg dst, int mask, - struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2) -{ - struct nv30_fragment_program *fp = fpc->fp; - - nv30_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); - - fp->insn[fpc->inst_offset] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT); - fp->samplers |= (1 << unit); -} - -static INLINE struct nv30_sreg -tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc) -{ - struct nv30_sreg src; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - src = nv30_sr(NV30SR_INPUT, - fpc->attrib_map[fsrc->Register.Index]); - break; - case TGSI_FILE_CONSTANT: - src = constant(fpc, fsrc->Register.Index, NULL); - break; - case TGSI_FILE_IMMEDIATE: - assert(fsrc->Register.Index < fpc->nr_imm); - src = fpc->imm[fsrc->Register.Index]; - break; - case TGSI_FILE_TEMPORARY: - src = nv30_sr(NV30SR_TEMP, fsrc->Register.Index + 1); - if (fpc->high_temp < src.index) - fpc->high_temp = src.index; - break; - /* This is clearly insane, but gallium hands us shaders like this. - * Luckily fragprog results are just temp regs.. - */ - case TGSI_FILE_OUTPUT: - if (fsrc->Register.Index == fpc->colour_id) - return nv30_sr(NV30SR_OUTPUT, 0); - else - return nv30_sr(NV30SR_OUTPUT, 1); - break; - default: - NOUVEAU_ERR("bad src file\n"); - break; - } - - src.abs = fsrc->Register.Absolute; - src.negate = fsrc->Register.Negate; - src.swz[0] = fsrc->Register.SwizzleX; - src.swz[1] = fsrc->Register.SwizzleY; - src.swz[2] = fsrc->Register.SwizzleZ; - src.swz[3] = fsrc->Register.SwizzleW; - return src; -} - -static INLINE struct nv30_sreg -tgsi_dst(struct nv30_fpc *fpc, const struct tgsi_full_dst_register *fdst) { - int idx; - - switch (fdst->Register.File) { - case TGSI_FILE_OUTPUT: - if (fdst->Register.Index == fpc->colour_id) - return nv30_sr(NV30SR_OUTPUT, 0); - else - return nv30_sr(NV30SR_OUTPUT, 1); - break; - case TGSI_FILE_TEMPORARY: - idx = fdst->Register.Index + 1; - if (fpc->high_temp < idx) - fpc->high_temp = idx; - return nv30_sr(NV30SR_TEMP, idx); - case TGSI_FILE_NULL: - return nv30_sr(NV30SR_NONE, 0); - default: - NOUVEAU_ERR("bad dst file %d\n", fdst->Register.File); - return nv30_sr(NV30SR_NONE, 0); - } -} - -static INLINE int -tgsi_mask(uint tgsi) -{ - int mask = 0; - - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; - return mask; -} - -static boolean -src_native_swz(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc, - struct nv30_sreg *src) -{ - const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); - struct nv30_sreg tgsi = tgsi_src(fpc, fsrc); - uint mask = 0; - uint c; - - for (c = 0; c < 4; c++) { - switch (tgsi_util_get_full_src_register_swizzle(fsrc, c)) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - mask |= (1 << c); - break; - default: - assert(0); - } - } - - if (mask == MASK_ALL) - return TRUE; - - *src = temp(fpc); - - if (mask) - arith(fpc, 0, MOV, *src, mask, tgsi, none, none); - - return FALSE; -} - -static boolean -nv30_fragprog_parse_instruction(struct nv30_fpc *fpc, - const struct tgsi_full_instruction *finst) -{ - const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); - struct nv30_sreg src[3], dst, tmp; - int mask, sat, unit = 0; - int ai = -1, ci = -1; - int i; - - if (finst->Instruction.Opcode == TGSI_OPCODE_END) - return TRUE; - - fpc->temp_temp_count = 0; - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - if (fsrc->Register.File == TGSI_FILE_TEMPORARY) { - src[i] = tgsi_src(fpc, fsrc); - } - } - - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - case TGSI_FILE_CONSTANT: - case TGSI_FILE_TEMPORARY: - if (!src_native_swz(fpc, fsrc, &src[i])) - continue; - break; - default: - break; - } - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - if (ai == -1 || ai == fsrc->Register.Index) { - ai = fsrc->Register.Index; - src[i] = tgsi_src(fpc, fsrc); - } else { - NOUVEAU_MSG("extra src attr %d\n", - fsrc->Register.Index); - src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, - tgsi_src(fpc, fsrc), none, none); - } - break; - case TGSI_FILE_CONSTANT: - case TGSI_FILE_IMMEDIATE: - if (ci == -1 || ci == fsrc->Register.Index) { - ci = fsrc->Register.Index; - src[i] = tgsi_src(fpc, fsrc); - } else { - src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, - tgsi_src(fpc, fsrc), none, none); - } - break; - case TGSI_FILE_TEMPORARY: - /* handled above */ - break; - case TGSI_FILE_SAMPLER: - unit = fsrc->Register.Index; - break; - case TGSI_FILE_OUTPUT: - break; - default: - NOUVEAU_ERR("bad src file\n"); - return FALSE; - } - } - - dst = tgsi_dst(fpc, &finst->Dst[0]); - mask = tgsi_mask(finst->Dst[0].Register.WriteMask); - sat = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE); - - switch (finst->Instruction.Opcode) { - case TGSI_OPCODE_ABS: - arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none); - break; - case TGSI_OPCODE_ADD: - arith(fpc, sat, ADD, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_CMP: - tmp = nv30_sr(NV30SR_NONE, 0); - tmp.cc_update = 1; - arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none); - dst.cc_test = NV30_VP_INST_COND_GE; - arith(fpc, sat, MOV, dst, mask, src[2], none, none); - dst.cc_test = NV30_VP_INST_COND_LT; - arith(fpc, sat, MOV, dst, mask, src[1], none, none); - break; - case TGSI_OPCODE_COS: - arith(fpc, sat, COS, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_DP3: - arith(fpc, sat, DP3, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DP4: - arith(fpc, sat, DP4, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DPH: - tmp = temp(fpc); - arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none); - arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X), - swz(src[1], W, W, W, W), none); - break; - case TGSI_OPCODE_DST: - arith(fpc, sat, DST, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_EX2: - arith(fpc, sat, EX2, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FLR: - arith(fpc, sat, FLR, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FRC: - arith(fpc, sat, FRC, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_KILP: - arith(fpc, 0, KIL, none, 0, none, none, none); - break; - case TGSI_OPCODE_KIL: - dst = nv30_sr(NV30SR_NONE, 0); - dst.cc_update = 1; - arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none); - dst.cc_update = 0; dst.cc_test = NV30_FP_OP_COND_LT; - arith(fpc, 0, KIL, dst, 0, none, none, none); - break; - case TGSI_OPCODE_LG2: - arith(fpc, sat, LG2, dst, mask, src[0], none, none); - break; -// case TGSI_OPCODE_LIT: - case TGSI_OPCODE_LRP: - arith(fpc, sat, LRP, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAD: - arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAX: - arith(fpc, sat, MAX, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MIN: - arith(fpc, sat, MIN, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MOV: - arith(fpc, sat, MOV, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_MUL: - arith(fpc, sat, MUL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_POW: - arith(fpc, sat, POW, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_RCP: - arith(fpc, sat, RCP, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_RET: - assert(0); - break; - case TGSI_OPCODE_RFL: - arith(fpc, 0, RFL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_RSQ: - arith(fpc, sat, RSQ, dst, mask, abs(swz(src[0], X, X, X, X)), none, none); - break; - case TGSI_OPCODE_SCS: - /* avoid overwriting the source */ - if(src[0].swz[SWZ_X] != SWZ_X) - { - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, - swz(src[0], X, X, X, X), none, none); - } - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, - swz(src[0], X, X, X, X), none, none); - } - } - else - { - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, - swz(src[0], X, X, X, X), none, none); - } - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, - swz(src[0], X, X, X, X), none, none); - } - } - break; - case TGSI_OPCODE_SIN: - arith(fpc, sat, SIN, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_SGE: - arith(fpc, sat, SGE, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SGT: - arith(fpc, sat, SGT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SLT: - arith(fpc, sat, SLT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SUB: - arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none); - break; - case TGSI_OPCODE_TEX: - tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_TXB: - tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_TXP: - tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_XPD: - tmp = temp(fpc); - arith(fpc, 0, MUL, tmp, mask, - swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(fpc, sat, MAD, dst, (mask & ~MASK_W), - swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), - neg(tmp)); - break; - default: - NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); - return FALSE; - } - - return TRUE; -} - -static boolean -nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc, - const struct tgsi_full_declaration *fdec) -{ - int hw; - - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - hw = NV30_FP_OP_INPUT_SRC_POSITION; - break; - case TGSI_SEMANTIC_COLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_FP_OP_INPUT_SRC_COL0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_FP_OP_INPUT_SRC_COL1; - } else { - NOUVEAU_ERR("bad colour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_FOG: - hw = NV30_FP_OP_INPUT_SRC_FOGC; - break; - case TGSI_SEMANTIC_GENERIC: - if (fdec->Semantic.Index <= 7) { - hw = NV30_FP_OP_INPUT_SRC_TC(fdec->Semantic. - Index); - } else { - NOUVEAU_ERR("bad generic semantic index\n"); - return FALSE; - } - break; - default: - NOUVEAU_ERR("bad input semantic\n"); - return FALSE; - } - - fpc->attrib_map[fdec->Range.First] = hw; - return TRUE; -} - -static boolean -nv30_fragprog_parse_decl_output(struct nv30_fpc *fpc, - const struct tgsi_full_declaration *fdec) -{ - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - fpc->depth_id = fdec->Range.First; - break; - case TGSI_SEMANTIC_COLOR: - fpc->colour_id = fdec->Range.First; - break; - default: - NOUVEAU_ERR("bad output semantic\n"); - return FALSE; - } - - return TRUE; -} - -static boolean -nv30_fragprog_prepare(struct nv30_fpc *fpc) -{ - struct tgsi_parse_context p; - /*int high_temp = -1, i;*/ - - tgsi_parse_init(&p, fpc->fp->pipe.tokens); - while (!tgsi_parse_end_of_tokens(&p)) { - const union tgsi_full_token *tok = &p.FullToken; - - tgsi_parse_token(&p); - switch(tok->Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - { - const struct tgsi_full_declaration *fdec; - fdec = &p.FullToken.FullDeclaration; - switch (fdec->Declaration.File) { - case TGSI_FILE_INPUT: - if (!nv30_fragprog_parse_decl_attrib(fpc, fdec)) - goto out_err; - break; - case TGSI_FILE_OUTPUT: - if (!nv30_fragprog_parse_decl_output(fpc, fdec)) - goto out_err; - break; - /*case TGSI_FILE_TEMPORARY: - if (fdec->Range.Last > high_temp) { - high_temp = - fdec->Range.Last; - } - break;*/ - default: - break; - } - } - break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - { - struct tgsi_full_immediate *imm; - float vals[4]; - - imm = &p.FullToken.FullImmediate; - assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); - assert(fpc->nr_imm < MAX_IMM); - - vals[0] = imm->u[0].Float; - vals[1] = imm->u[1].Float; - vals[2] = imm->u[2].Float; - vals[3] = imm->u[3].Float; - fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals); - } - break; - default: - break; - } - } - tgsi_parse_free(&p); - - /*if (++high_temp) { - fpc->r_temp = CALLOC(high_temp, sizeof(struct nv30_sreg)); - for (i = 0; i < high_temp; i++) - fpc->r_temp[i] = temp(fpc); - fpc->r_temps_discard = 0; - }*/ - - return TRUE; - -out_err: - /*if (fpc->r_temp) - FREE(fpc->r_temp);*/ - tgsi_parse_free(&p); - return FALSE; -} - -static void -nv30_fragprog_translate(struct nv30_context *nv30, - struct nv30_fragment_program *fp) -{ - struct tgsi_parse_context parse; - struct nv30_fpc *fpc = NULL; - - tgsi_dump(fp->pipe.tokens,0); - - fpc = CALLOC(1, sizeof(struct nv30_fpc)); - if (!fpc) - return; - fpc->fp = fp; - fpc->high_temp = -1; - fpc->num_regs = 2; - - if (!nv30_fragprog_prepare(fpc)) { - FREE(fpc); - return; - } - - tgsi_parse_init(&parse, fp->pipe.tokens); - - while (!tgsi_parse_end_of_tokens(&parse)) { - tgsi_parse_token(&parse); - - switch (parse.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - const struct tgsi_full_instruction *finst; - - finst = &parse.FullToken.FullInstruction; - if (!nv30_fragprog_parse_instruction(fpc, finst)) - goto out_err; - } - break; - default: - break; - } - } - - fp->fp_control |= (fpc->num_regs-1)/2; - fp->fp_reg_control = (1<<16)|0x4; - - /* Terminate final instruction */ - fp->insn[fpc->inst_offset] |= 0x00000001; - - /* Append NOP + END instruction, may or may not be necessary. */ - fpc->inst_offset = fp->insn_len; - grow_insns(fpc, 4); - fp->insn[fpc->inst_offset + 0] = 0x00000001; - fp->insn[fpc->inst_offset + 1] = 0x00000000; - fp->insn[fpc->inst_offset + 2] = 0x00000000; - fp->insn[fpc->inst_offset + 3] = 0x00000000; - - fp->translated = TRUE; - fp->on_hw = FALSE; -out_err: - tgsi_parse_free(&parse); - FREE(fpc); -} - -static void -nv30_fragprog_upload(struct nv30_context *nv30, - struct nv30_fragment_program *fp) -{ - struct pipe_screen *pscreen = nv30->pipe.screen; - const uint32_t le = 1; - uint32_t *map; - int i; - - map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); - -#if 0 - for (i = 0; i < fp->insn_len; i++) { - fflush(stdout); fflush(stderr); - NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]); - fflush(stdout); fflush(stderr); - } -#endif - - if ((*(const uint8_t *)&le)) { - for (i = 0; i < fp->insn_len; i++) { - map[i] = fp->insn[i]; - } - } else { - /* Weird swapping for big-endian chips */ - for (i = 0; i < fp->insn_len; i++) { - map[i] = ((fp->insn[i] & 0xffff) << 16) | - ((fp->insn[i] >> 16) & 0xffff); - } - } - - pipe_buffer_unmap(pscreen, fp->buffer); -} - -static boolean -nv30_fragprog_validate(struct nv30_context *nv30) -{ - struct nv30_fragment_program *fp = nv30->fragprog; - struct pipe_buffer *constbuf = - nv30->constbuf[PIPE_SHADER_FRAGMENT]; - struct pipe_screen *pscreen = nv30->pipe.screen; - struct nouveau_stateobj *so; - boolean new_consts = FALSE; - int i; - - if (fp->translated) - goto update_constants; - - /*nv30->fallback_swrast &= ~NV30_NEW_FRAGPROG;*/ - nv30_fragprog_translate(nv30, fp); - if (!fp->translated) { - /*nv30->fallback_swrast |= NV30_NEW_FRAGPROG;*/ - return FALSE; - } - - fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4); - nv30_fragprog_upload(nv30, fp); - - so = so_new(4, 4, 1); - so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1); - so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | - NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0, - NV34TCL_FP_ACTIVE_PROGRAM_DMA1); - so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1); - so_data (so, fp->fp_control); - so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1); - so_data (so, fp->fp_reg_control); - so_method(so, nv30->screen->rankine, NV34TCL_TX_UNITS_ENABLE, 1); - so_data (so, fp->samplers); - so_ref(so, &fp->so); - so_ref(NULL, &so); - -update_constants: - if (fp->nr_consts) { - float *map; - - map = pipe_buffer_map(pscreen, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); - for (i = 0; i < fp->nr_consts; i++) { - struct nv30_fragment_program_data *fpd = &fp->consts[i]; - uint32_t *p = &fp->insn[fpd->offset]; - uint32_t *cb = (uint32_t *)&map[fpd->index * 4]; - - if (!memcmp(p, cb, 4 * sizeof(float))) - continue; - memcpy(p, cb, 4 * sizeof(float)); - new_consts = TRUE; - } - pipe_buffer_unmap(pscreen, constbuf); - - if (new_consts) - nv30_fragprog_upload(nv30, fp); - } - - if (new_consts || fp->so != nv30->state.hw[NV30_STATE_FRAGPROG]) { - so_ref(fp->so, &nv30->state.hw[NV30_STATE_FRAGPROG]); - return TRUE; - } - - return FALSE; -} - -void -nv30_fragprog_destroy(struct nv30_context *nv30, - struct nv30_fragment_program *fp) -{ - if (fp->buffer) - pipe_buffer_reference(&fp->buffer, NULL); - - if (fp->so) - so_ref(NULL, &fp->so); - - if (fp->insn_len) - FREE(fp->insn); -} - -struct nv30_state_entry nv30_state_fragprog = { - .validate = nv30_fragprog_validate, - .dirty = { - .pipe = NV30_NEW_FRAGPROG, - .hw = NV30_STATE_FRAGPROG - } -}; diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c deleted file mode 100644 index 697b1b92ff6..00000000000 --- a/src/gallium/drivers/nv30/nv30_miptree.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" - -#include "nv30_context.h" -#include "../nouveau/nv04_surface_2d.h" - -static void -nv30_miptree_layout(struct nv30_miptree *nv30mt) -{ - struct pipe_texture *pt = &nv30mt->base; - uint width = pt->width0; - uint offset = 0; - int nr_faces, l, f; - uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); - - if (pt->target == PIPE_TEXTURE_CUBE) { - nr_faces = 6; - } else - if (pt->target == PIPE_TEXTURE_3D) { - nr_faces = pt->depth0; - } else { - nr_faces = 1; - } - - for (l = 0; l <= pt->last_level; l++) { - if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) - nv30mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64); - else - nv30mt->level[l].pitch = util_format_get_stride(pt->format, width); - - nv30mt->level[l].image_offset = - CALLOC(nr_faces, sizeof(unsigned)); - - width = u_minify(width, 1); - } - - for (f = 0; f < nr_faces; f++) { - for (l = 0; l < pt->last_level; l++) { - nv30mt->level[l].image_offset[f] = offset; - - if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) && - u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1) - offset += align(nv30mt->level[l].pitch * u_minify(pt->height0, l), 64); - else - offset += nv30mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv30mt->level[l].image_offset[f] = offset; - offset += nv30mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv30mt->total_size = offset; -} - -static struct pipe_texture * -nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) -{ - struct nv30_miptree *mt; - unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | - NOUVEAU_BUFFER_USAGE_TEXTURE; - - mt = MALLOC(sizeof(struct nv30_miptree)); - if (!mt) - return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - - /* Swizzled textures must be POT */ - if (pt->width0 & (pt->width0 - 1) || - pt->height0 & (pt->height0 - 1)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else { - switch (pt->format) { - /* TODO: Figure out which formats can be swizzled */ - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_R16_SNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - case PIPE_FORMAT_L8A8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - { - if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - break; - } - default: - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - } - } - - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE; - - /* apparently we can't render to swizzled surfaces smaller than 64 bytes, so make them linear. - * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy. - * This also happens for small mipmaps of large textures. */ - if (pt->tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET && util_format_get_stride(pt->format, pt->width0) < 64) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - - nv30_miptree_layout(mt); - - mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage, - mt->total_size); - if (!mt->buffer) { - FREE(mt); - return NULL; - } - mt->bo = nouveau_bo(mt->buffer); - - return &mt->base; -} - -static struct pipe_texture * -nv30_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) -{ - struct nv30_miptree *mt; - - /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) - return NULL; - - mt = CALLOC_STRUCT(nv30_miptree); - if (!mt) - return NULL; - - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - mt->level[0].pitch = stride[0]; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - - /* Assume whoever created this buffer expects it to be linear for now */ - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - - pipe_buffer_reference(&mt->buffer, pb); - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; -} - -static void -nv30_miptree_destroy(struct pipe_texture *pt) -{ - struct nv30_miptree *mt = (struct nv30_miptree *)pt; - int l; - - pipe_buffer_reference(&mt->buffer, NULL); - for (l = 0; l <= pt->last_level; l++) { - if (mt->level[l].image_offset) - FREE(mt->level[l].image_offset); - } - - FREE(mt); -} - -static struct pipe_surface * -nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) -{ - struct nv30_miptree *nv30mt = (struct nv30_miptree *)pt; - struct nv04_surface *ns; - - ns = CALLOC_STRUCT(nv04_surface); - if (!ns) - return NULL; - pipe_texture_reference(&ns->base.texture, pt); - ns->base.format = pt->format; - ns->base.width = u_minify(pt->width0, level); - ns->base.height = u_minify(pt->height0, level); - ns->base.usage = flags; - pipe_reference_init(&ns->base.reference, 1); - ns->base.face = face; - ns->base.level = level; - ns->base.zslice = zslice; - ns->pitch = nv30mt->level[level].pitch; - - if (pt->target == PIPE_TEXTURE_CUBE) { - ns->base.offset = nv30mt->level[level].image_offset[face]; - } else - if (pt->target == PIPE_TEXTURE_3D) { - ns->base.offset = nv30mt->level[level].image_offset[zslice]; - } else { - ns->base.offset = nv30mt->level[level].image_offset[0]; - } - - /* create a linear temporary that we can render into if necessary. - * Note that ns->pitch is always a multiple of 64 for linear surfaces and swizzled surfaces are POT, so - * ns->pitch & 63 is equivalent to (ns->pitch < 64 && swizzled)*/ - if((ns->pitch & 63) && (ns->base.usage & (PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER)) == PIPE_BUFFER_USAGE_GPU_WRITE) - return &nv04_surface_wrap_for_render(pscreen, ((struct nv30_screen*)pscreen)->eng2d, ns)->base; - - return &ns->base; -} - -static void -nv30_miptree_surface_del(struct pipe_surface *ps) -{ - struct nv04_surface* ns = (struct nv04_surface*)ps; - if(ns->backing) - { - struct nv30_screen* screen = (struct nv30_screen*)ps->texture->screen; - if(ns->backing->base.usage & PIPE_BUFFER_USAGE_GPU_WRITE) - screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height); - nv30_miptree_surface_del(&ns->backing->base); - } - - pipe_texture_reference(&ps->texture, NULL); - FREE(ps); -} - -void -nv30_screen_init_miptree_functions(struct pipe_screen *pscreen) -{ - pscreen->texture_create = nv30_miptree_create; - pscreen->texture_blanket = nv30_miptree_blanket; - pscreen->texture_destroy = nv30_miptree_destroy; - pscreen->get_tex_surface = nv30_miptree_surface_new; - pscreen->tex_surface_destroy = nv30_miptree_surface_del; -} diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c deleted file mode 100644 index e27e9ccbf60..00000000000 --- a/src/gallium/drivers/nv30/nv30_query.c +++ /dev/null @@ -1,127 +0,0 @@ -#include "pipe/p_context.h" - -#include "nv30_context.h" - -struct nv30_query { - struct nouveau_resource *object; - unsigned type; - boolean ready; - uint64_t result; -}; - -static INLINE struct nv30_query * -nv30_query(struct pipe_query *pipe) -{ - return (struct nv30_query *)pipe; -} - -static struct pipe_query * -nv30_query_create(struct pipe_context *pipe, unsigned query_type) -{ - struct nv30_query *q; - - q = CALLOC(1, sizeof(struct nv30_query)); - q->type = query_type; - - return (struct pipe_query *)q; -} - -static void -nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv30_query *q = nv30_query(pq); - - if (q->object) - nouveau_resource_free(&q->object); - FREE(q); -} - -static void -nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_query *q = nv30_query(pq); - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - - assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - /* Happens when end_query() is called, then another begin_query() - * without querying the result in-between. For now we'll wait for - * the existing query to notify completion, but it could be better. - */ - if (q->object) { - uint64_t tmp; - pipe->get_query_result(pipe, pq, 1, &tmp); - } - - if (nouveau_resource_alloc(nv30->screen->query_heap, 1, NULL, &q->object)) - assert(0); - nouveau_notifier_reset(nv30->screen->query, q->object->start); - - BEGIN_RING(chan, rankine, NV34TCL_QUERY_RESET, 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, rankine, NV34TCL_QUERY_UNK17CC, 1); - OUT_RING (chan, 1); - - q->ready = FALSE; -} - -static void -nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - struct nv30_query *q = nv30_query(pq); - - BEGIN_RING(chan, rankine, NV34TCL_QUERY_GET, 1); - OUT_RING (chan, (0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) | - ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT)); - FIRE_RING(chan); -} - -static boolean -nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq, - boolean wait, uint64_t *result) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_query *q = nv30_query(pq); - - assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - if (!q->ready) { - unsigned status; - - status = nouveau_notifier_status(nv30->screen->query, - q->object->start); - if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { - if (wait == FALSE) - return FALSE; - - nouveau_notifier_wait_status(nv30->screen->query, - q->object->start, - NV_NOTIFY_STATE_STATUS_COMPLETED, 0); - } - - q->result = nouveau_notifier_return_val(nv30->screen->query, - q->object->start); - q->ready = TRUE; - nouveau_resource_free(&q->object); - } - - *result = q->result; - return TRUE; -} - -void -nv30_init_query_functions(struct nv30_context *nv30) -{ - nv30->pipe.create_query = nv30_query_create; - nv30->pipe.destroy_query = nv30_query_destroy; - nv30->pipe.begin_query = nv30_query_begin; - nv30->pipe.end_query = nv30_query_end; - nv30->pipe.get_query_result = nv30_query_result; -} diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h deleted file mode 100644 index 8591cd31cab..00000000000 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __NV30_SCREEN_H__ -#define __NV30_SCREEN_H__ - -#include "nouveau/nouveau_screen.h" - -#include "nouveau/nv04_surface_2d.h" - -struct nv30_screen { - struct nouveau_screen base; - - struct nouveau_winsys *nvws; - - struct nv30_context *cur_ctx; - - /* HW graphics objects */ - struct nv04_surface_2d *eng2d; - struct nouveau_grobj *rankine; - struct nouveau_notifier *sync; - - /* Query object resources */ - struct nouveau_notifier *query; - struct nouveau_resource *query_heap; - - /* Vtxprog resources */ - struct nouveau_resource *vp_exec_heap; - struct nouveau_resource *vp_data_heap; - - /* Current 3D state of channel */ - struct nouveau_stateobj *state[NV30_STATE_MAX]; -}; - -static INLINE struct nv30_screen * -nv30_screen(struct pipe_screen *screen) -{ - return (struct nv30_screen *)screen; -} - -void -nv30_screen_init_transfer_functions(struct pipe_screen *pscreen); - -#endif diff --git a/src/gallium/drivers/nv30/nv30_shader.h b/src/gallium/drivers/nv30/nv30_shader.h deleted file mode 100644 index dd3a36f78f3..00000000000 --- a/src/gallium/drivers/nv30/nv30_shader.h +++ /dev/null @@ -1,490 +0,0 @@ -#ifndef __NV30_SHADER_H__ -#define __NV30_SHADER_H__ - -/* Vertex programs instruction set - * - * 128bit opcodes, split into 4 32-bit ones for ease of use. - * - * Non-native instructions - * ABS - MOV + NV40_VP_INST0_DEST_ABS - * POW - EX2 + MUL + LG2 - * SUB - ADD, second source negated - * SWZ - MOV - * XPD - - * - * Register access - * - Only one INPUT can be accessed per-instruction (move extras into TEMPs) - * - Only one CONST can be accessed per-instruction (move extras into TEMPs) - * - * Relative Addressing - * According to the value returned for - * MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB - * - * there are only two address registers available. The destination in the - * ARL instruction is set to TEMP <n> (The temp isn't actually written). - * - * When using vanilla ARB_v_p, the proprietary driver will squish both the - * available ADDRESS regs into the first hardware reg in the X and Y - * components. - * - * To use an address reg as an index into consts, the CONST_SRC is set to - * (const_base + offset) and INDEX_CONST is set. - * - * To access the second address reg use ADDR_REG_SELECT_1. A particular - * component of the address regs is selected with ADDR_SWZ. - * - * Only one address register can be accessed per instruction. - * - * Conditional execution (see NV_vertex_program{2,3} for details) Conditional - * execution of an instruction is enabled by setting COND_TEST_ENABLE, and - * selecting the condition which will allow the test to pass with - * COND_{FL,LT,...}. It is possible to swizzle the values in the condition - * register, which allows for testing against an individual component. - * - * Branching: - * - * The BRA/CAL instructions seem to follow a slightly different opcode - * layout. The destination instruction ID (IADDR) overlaps a source field. - * Instruction ID's seem to be numbered based on the UPLOAD_FROM_ID FIFO - * command, and is incremented automatically on each UPLOAD_INST FIFO - * command. - * - * Conditional branching is achieved by using the condition tests described - * above. There doesn't appear to be dedicated looping instructions, but - * this can be done using a temp reg + conditional branching. - * - * Subroutines may be uploaded before the main program itself, but the first - * executed instruction is determined by the PROGRAM_START_ID FIFO command. - * - */ - -/* DWORD 0 */ - -#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24) -#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */ -#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */ -#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */ -#define NV30_VP_INST_VEC_RESULT (1 << 20) -#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16 -#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16) -#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15) -#define NV30_VP_INST_VEC_DEST_TEMP_MASK (0xF << 16) -#define NV30_VP_INST_COND_TEST_ENABLE (1<<14) -#define NV30_VP_INST_COND_SHIFT 11 -#define NV30_VP_INST_COND_MASK (0x07 << 11) -# define NV30_VP_INST_COND_FL 0 /* guess */ -# define NV30_VP_INST_COND_LT 1 -# define NV30_VP_INST_COND_EQ 2 -# define NV30_VP_INST_COND_LE 3 -# define NV30_VP_INST_COND_GT 4 -# define NV30_VP_INST_COND_NE 5 -# define NV30_VP_INST_COND_GE 6 -# define NV30_VP_INST_COND_TR 7 /* guess */ -#define NV30_VP_INST_COND_SWZ_X_SHIFT 9 -#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9) -#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7 -#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7) -#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5 -#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5) -#define NV30_VP_INST_COND_SWZ_W_SHIFT 3 -#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3) -#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3 -#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3) -#define NV30_VP_INST_ADDR_SWZ_SHIFT 1 -#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1) -#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0 -#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0) - -/* DWORD 1 */ -#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28 -#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28) -# define NV30_VP_INST_OP_NOP 0x00 -# define NV30_VP_INST_OP_RCP 0x02 -# define NV30_VP_INST_OP_RCC 0x03 -# define NV30_VP_INST_OP_RSQ 0x04 -# define NV30_VP_INST_OP_EXP 0x05 -# define NV30_VP_INST_OP_LOG 0x06 -# define NV30_VP_INST_OP_LIT 0x07 -# define NV30_VP_INST_OP_BRA 0x09 -# define NV30_VP_INST_OP_CAL 0x0B -# define NV30_VP_INST_OP_RET 0x0C -# define NV30_VP_INST_OP_LG2 0x0D -# define NV30_VP_INST_OP_EX2 0x0E -# define NV30_VP_INST_OP_SIN 0x0F -# define NV30_VP_INST_OP_COS 0x10 -#define NV30_VP_INST_VEC_OPCODE_SHIFT 23 -#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23) -# define NV30_VP_INST_OP_NOPV 0x00 -# define NV30_VP_INST_OP_MOV 0x01 -# define NV30_VP_INST_OP_MUL 0x02 -# define NV30_VP_INST_OP_ADD 0x03 -# define NV30_VP_INST_OP_MAD 0x04 -# define NV30_VP_INST_OP_DP3 0x05 -# define NV30_VP_INST_OP_DP4 0x07 -# define NV30_VP_INST_OP_DPH 0x06 -# define NV30_VP_INST_OP_DST 0x08 -# define NV30_VP_INST_OP_MIN 0x09 -# define NV30_VP_INST_OP_MAX 0x0A -# define NV30_VP_INST_OP_SLT 0x0B -# define NV30_VP_INST_OP_SGE 0x0C -# define NV30_VP_INST_OP_ARL 0x0D -# define NV30_VP_INST_OP_FRC 0x0E -# define NV30_VP_INST_OP_FLR 0x0F -# define NV30_VP_INST_OP_SEQ 0x10 -# define NV30_VP_INST_OP_SFL 0x11 -# define NV30_VP_INST_OP_SGT 0x12 -# define NV30_VP_INST_OP_SLE 0x13 -# define NV30_VP_INST_OP_SNE 0x14 -# define NV30_VP_INST_OP_STR 0x15 -# define NV30_VP_INST_OP_SSG 0x16 -# define NV30_VP_INST_OP_ARR 0x17 -# define NV30_VP_INST_OP_ARA 0x18 -#define NV30_VP_INST_CONST_SRC_SHIFT 14 -#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14) -#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/ -#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/ -# define NV30_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */ -# define NV30_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */ -# define NV30_VP_INST_IN_NORMAL 2 -# define NV30_VP_INST_IN_COL0 3 /* Should probably confirm them all though */ -# define NV30_VP_INST_IN_COL1 4 -# define NV30_VP_INST_IN_FOGC 5 -# define NV30_VP_INST_IN_TC0 8 -# define NV30_VP_INST_IN_TC(n) (8+n) -#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/ -#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/ - -/* Please note: the IADDR fields overlap other fields because they are used - * only for branch instructions. See Branching: label above - * - * DWORD 2 - */ -#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/ -#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /* NV30_VP_SRC0_LOW_MASK << 26 */ -#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/ -#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/ -#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/ -#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /* NV30_VP_SRC2_HIGH_MASK >> 4*/ -#define NV30_VP_INST_IADDR_SHIFT 2 -#define NV30_VP_INST_IADDR_MASK (0xF << 28) /* NV30_VP_SRC2_LOW_MASK << 28 */ - -/* DWORD 3 */ -#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/ -#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/ -#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24 -#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24) -#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20 -#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20) -#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16 -#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16) -#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/ -#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/ -#define NV30_VP_INST_DEST_SHIFT 2 -#define NV30_VP_INST_DEST_MASK (0x0F << 2) -# define NV30_VP_INST_DEST_POS 0 -# define NV30_VP_INST_DEST_BFC0 1 -# define NV30_VP_INST_DEST_BFC1 2 -# define NV30_VP_INST_DEST_COL0 3 -# define NV30_VP_INST_DEST_COL1 4 -# define NV30_VP_INST_DEST_FOGC 5 -# define NV30_VP_INST_DEST_PSZ 6 -# define NV30_VP_INST_DEST_TC(n) (8+n) - -#define NV30_VP_INST_LAST (1 << 0) - -/* Useful to split the source selection regs into their pieces */ -#define NV30_VP_SRC0_HIGH_SHIFT 6 -#define NV30_VP_SRC0_HIGH_MASK 0x00007FC0 -#define NV30_VP_SRC0_LOW_MASK 0x0000003F -#define NV30_VP_SRC2_HIGH_SHIFT 4 -#define NV30_VP_SRC2_HIGH_MASK 0x00007FF0 -#define NV30_VP_SRC2_LOW_MASK 0x0000000F - - -/* Source-register definition - matches NV20 exactly */ -#define NV30_VP_SRC_NEGATE (1<<14) -#define NV30_VP_SRC_SWZ_X_SHIFT 12 -#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12) -#define NV30_VP_SRC_SWZ_Y_SHIFT 10 -#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10) -#define NV30_VP_SRC_SWZ_Z_SHIFT 8 -#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8) -#define NV30_VP_SRC_SWZ_W_SHIFT 6 -#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6) -#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6 -#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6) -#define NV30_VP_SRC_TEMP_SRC_SHIFT 2 -#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0) -#define NV30_VP_SRC_REG_TYPE_SHIFT 0 -#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0) -#define NV30_VP_SRC_REG_TYPE_TEMP 1 -#define NV30_VP_SRC_REG_TYPE_INPUT 2 -#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */ - -/* - * Each fragment program opcode appears to be comprised of 4 32-bit values. - * - * 0 - Opcode, output reg/mask, ATTRIB source - * 1 - Source 0 - * 2 - Source 1 - * 3 - Source 2 - * - * There appears to be no special difference between result regs and temp regs. - * result.color == R0.xyzw - * result.depth == R1.z - * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0 - * otherwise it is set to 1. - * - * Constants are inserted directly after the instruction that uses them. - * - * It appears that it's not possible to use two input registers in one - * instruction as the input sourcing is done in the instruction dword - * and not the source selection dwords. As such instructions such as: - * - * ADD result.color, fragment.color, fragment.texcoord[0]; - * - * must be split into two MOV's and then an ADD (nvidia does this) but - * I'm not sure why it's not just one MOV and then source the second input - * in the ADD instruction.. - * - * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary - * negation requires multiplication with a const. - * - * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE - * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO - * is implemented simply by not writing to the relevant components of the destination. - * - * Conditional execution - * TODO - * - * Non-native instructions: - * LIT - * LRP - MAD+MAD - * SUB - ADD, negate second source - * RSQ - LG2 + EX2 - * POW - LG2 + MUL + EX2 - * SCS - COS + SIN - * XPD - */ - -//== Opcode / Destination selection == -#define NV30_FP_OP_PROGRAM_END (1 << 0) -#define NV30_FP_OP_OUT_REG_SHIFT 1 -#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */ -/* Needs to be set when writing outputs to get expected result.. */ -#define NV30_FP_OP_OUT_REG_HALF (1 << 7) -#define NV30_FP_OP_COND_WRITE_ENABLE (1 << 8) -#define NV30_FP_OP_OUTMASK_SHIFT 9 -#define NV30_FP_OP_OUTMASK_MASK (0xF << 9) -# define NV30_FP_OP_OUT_X (1<<9) -# define NV30_FP_OP_OUT_Y (1<<10) -# define NV30_FP_OP_OUT_Z (1<<11) -# define NV30_FP_OP_OUT_W (1<<12) -/* Uncertain about these, especially the input_src values.. it's possible that - * they can be dynamically changed. - */ -#define NV30_FP_OP_INPUT_SRC_SHIFT 13 -#define NV30_FP_OP_INPUT_SRC_MASK (15 << 13) -# define NV30_FP_OP_INPUT_SRC_POSITION 0x0 -# define NV30_FP_OP_INPUT_SRC_COL0 0x1 -# define NV30_FP_OP_INPUT_SRC_COL1 0x2 -# define NV30_FP_OP_INPUT_SRC_FOGC 0x3 -# define NV30_FP_OP_INPUT_SRC_TC0 0x4 -# define NV30_FP_OP_INPUT_SRC_TC(n) (0x4 + n) -#define NV30_FP_OP_TEX_UNIT_SHIFT 17 -#define NV30_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */ -#define NV30_FP_OP_PRECISION_SHIFT 22 -#define NV30_FP_OP_PRECISION_MASK (3 << 22) -# define NV30_FP_PRECISION_FP32 0 -# define NV30_FP_PRECISION_FP16 1 -# define NV30_FP_PRECISION_FX12 2 -#define NV30_FP_OP_OPCODE_SHIFT 24 -#define NV30_FP_OP_OPCODE_MASK (0x3F << 24) -# define NV30_FP_OP_OPCODE_NOP 0x00 -# define NV30_FP_OP_OPCODE_MOV 0x01 -# define NV30_FP_OP_OPCODE_MUL 0x02 -# define NV30_FP_OP_OPCODE_ADD 0x03 -# define NV30_FP_OP_OPCODE_MAD 0x04 -# define NV30_FP_OP_OPCODE_DP3 0x05 -# define NV30_FP_OP_OPCODE_DP4 0x06 -# define NV30_FP_OP_OPCODE_DST 0x07 -# define NV30_FP_OP_OPCODE_MIN 0x08 -# define NV30_FP_OP_OPCODE_MAX 0x09 -# define NV30_FP_OP_OPCODE_SLT 0x0A -# define NV30_FP_OP_OPCODE_SGE 0x0B -# define NV30_FP_OP_OPCODE_SLE 0x0C -# define NV30_FP_OP_OPCODE_SGT 0x0D -# define NV30_FP_OP_OPCODE_SNE 0x0E -# define NV30_FP_OP_OPCODE_SEQ 0x0F -# define NV30_FP_OP_OPCODE_FRC 0x10 -# define NV30_FP_OP_OPCODE_FLR 0x11 -# define NV30_FP_OP_OPCODE_KIL 0x12 -# define NV30_FP_OP_OPCODE_PK4B 0x13 -# define NV30_FP_OP_OPCODE_UP4B 0x14 -# define NV30_FP_OP_OPCODE_DDX 0x15 /* can only write XY */ -# define NV30_FP_OP_OPCODE_DDY 0x16 /* can only write XY */ -# define NV30_FP_OP_OPCODE_TEX 0x17 -# define NV30_FP_OP_OPCODE_TXP 0x18 -# define NV30_FP_OP_OPCODE_TXD 0x19 -# define NV30_FP_OP_OPCODE_RCP 0x1A -# define NV30_FP_OP_OPCODE_RSQ 0x1B -# define NV30_FP_OP_OPCODE_EX2 0x1C -# define NV30_FP_OP_OPCODE_LG2 0x1D -# define NV30_FP_OP_OPCODE_LIT 0x1E -# define NV30_FP_OP_OPCODE_LRP 0x1F -# define NV30_FP_OP_OPCODE_STR 0x20 -# define NV30_FP_OP_OPCODE_SFL 0x21 -# define NV30_FP_OP_OPCODE_COS 0x22 -# define NV30_FP_OP_OPCODE_SIN 0x23 -# define NV30_FP_OP_OPCODE_PK2H 0x24 -# define NV30_FP_OP_OPCODE_UP2H 0x25 -# define NV30_FP_OP_OPCODE_POW 0x26 -# define NV30_FP_OP_OPCODE_PK4UB 0x27 -# define NV30_FP_OP_OPCODE_UP4UB 0x28 -# define NV30_FP_OP_OPCODE_PK2US 0x29 -# define NV30_FP_OP_OPCODE_UP2US 0x2A -# define NV30_FP_OP_OPCODE_DP2A 0x2E -# define NV30_FP_OP_OPCODE_TXB 0x31 -# define NV30_FP_OP_OPCODE_RFL 0x36 -# define NV30_FP_OP_OPCODE_DIV 0x3A -#define NV30_FP_OP_OUT_SAT (1 << 31) - -/* high order bits of SRC0 */ -#define NV30_FP_OP_OUT_ABS (1 << 29) -#define NV30_FP_OP_COND_SWZ_W_SHIFT 27 -#define NV30_FP_OP_COND_SWZ_W_MASK (3 << 27) -#define NV30_FP_OP_COND_SWZ_Z_SHIFT 25 -#define NV30_FP_OP_COND_SWZ_Z_MASK (3 << 25) -#define NV30_FP_OP_COND_SWZ_Y_SHIFT 23 -#define NV30_FP_OP_COND_SWZ_Y_MASK (3 << 23) -#define NV30_FP_OP_COND_SWZ_X_SHIFT 21 -#define NV30_FP_OP_COND_SWZ_X_MASK (3 << 21) -#define NV30_FP_OP_COND_SWZ_ALL_SHIFT 21 -#define NV30_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) -#define NV30_FP_OP_COND_SHIFT 18 -#define NV30_FP_OP_COND_MASK (0x07 << 18) -# define NV30_FP_OP_COND_FL 0 -# define NV30_FP_OP_COND_LT 1 -# define NV30_FP_OP_COND_EQ 2 -# define NV30_FP_OP_COND_LE 3 -# define NV30_FP_OP_COND_GT 4 -# define NV30_FP_OP_COND_NE 5 -# define NV30_FP_OP_COND_GE 6 -# define NV30_FP_OP_COND_TR 7 - -/* high order bits of SRC1 */ -#define NV30_FP_OP_DST_SCALE_SHIFT 28 -#define NV30_FP_OP_DST_SCALE_MASK (3 << 28) -#define NV30_FP_OP_DST_SCALE_1X 0 -#define NV30_FP_OP_DST_SCALE_2X 1 -#define NV30_FP_OP_DST_SCALE_4X 2 -#define NV30_FP_OP_DST_SCALE_8X 3 -#define NV30_FP_OP_DST_SCALE_INV_2X 5 -#define NV30_FP_OP_DST_SCALE_INV_4X 6 -#define NV30_FP_OP_DST_SCALE_INV_8X 7 - - -/* high order bits of SRC2 */ -#define NV30_FP_OP_INDEX_INPUT (1 << 30) - -//== Register selection == -#define NV30_FP_REG_TYPE_SHIFT 0 -#define NV30_FP_REG_TYPE_MASK (3 << 0) -# define NV30_FP_REG_TYPE_TEMP 0 -# define NV30_FP_REG_TYPE_INPUT 1 -# define NV30_FP_REG_TYPE_CONST 2 -#define NV30_FP_REG_SRC_SHIFT 2 /* uncertain */ -#define NV30_FP_REG_SRC_MASK (31 << 2) -#define NV30_FP_REG_SRC_HALF (1 << 8) -#define NV30_FP_REG_SWZ_ALL_SHIFT 9 -#define NV30_FP_REG_SWZ_ALL_MASK (255 << 9) -#define NV30_FP_REG_SWZ_X_SHIFT 9 -#define NV30_FP_REG_SWZ_X_MASK (3 << 9) -#define NV30_FP_REG_SWZ_Y_SHIFT 11 -#define NV30_FP_REG_SWZ_Y_MASK (3 << 11) -#define NV30_FP_REG_SWZ_Z_SHIFT 13 -#define NV30_FP_REG_SWZ_Z_MASK (3 << 13) -#define NV30_FP_REG_SWZ_W_SHIFT 15 -#define NV30_FP_REG_SWZ_W_MASK (3 << 15) -# define NV30_FP_SWIZZLE_X 0 -# define NV30_FP_SWIZZLE_Y 1 -# define NV30_FP_SWIZZLE_Z 2 -# define NV30_FP_SWIZZLE_W 3 -#define NV30_FP_REG_NEGATE (1 << 17) - -#define NV30SR_NONE 0 -#define NV30SR_OUTPUT 1 -#define NV30SR_INPUT 2 -#define NV30SR_TEMP 3 -#define NV30SR_CONST 4 - -struct nv30_sreg { - int type; - int index; - - int dst_scale; - - int negate; - int abs; - int swz[4]; - - int cc_update; - int cc_update_reg; - int cc_test; - int cc_test_reg; - int cc_swz[4]; -}; - -static INLINE struct nv30_sreg -nv30_sr(int type, int index) -{ - struct nv30_sreg temp = { - .type = type, - .index = index, - .dst_scale = DEF_SCALE, - .abs = 0, - .negate = 0, - .swz = { 0, 1, 2, 3 }, - .cc_update = 0, - .cc_update_reg = 0, - .cc_test = DEF_CTEST, - .cc_test_reg = 0, - .cc_swz = { 0, 1, 2, 3 }, - }; - return temp; -} - -static INLINE struct nv30_sreg -nv30_sr_swz(struct nv30_sreg src, int x, int y, int z, int w) -{ - struct nv30_sreg dst = src; - - dst.swz[SWZ_X] = src.swz[x]; - dst.swz[SWZ_Y] = src.swz[y]; - dst.swz[SWZ_Z] = src.swz[z]; - dst.swz[SWZ_W] = src.swz[w]; - return dst; -} - -static INLINE struct nv30_sreg -nv30_sr_neg(struct nv30_sreg src) -{ - src.negate = !src.negate; - return src; -} - -static INLINE struct nv30_sreg -nv30_sr_abs(struct nv30_sreg src) -{ - src.abs = 1; - return src; -} - -static INLINE struct nv30_sreg -nv30_sr_scale(struct nv30_sreg src, int scale) -{ - src.dst_scale = scale; - return src; -} - -#endif diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c deleted file mode 100644 index d911c807074..00000000000 --- a/src/gallium/drivers/nv30/nv30_state.c +++ /dev/null @@ -1,728 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" - -#include "tgsi/tgsi_parse.h" - -#include "nv30_context.h" -#include "nv30_state.h" - -static void * -nv30_blend_state_create(struct pipe_context *pipe, - const struct pipe_blend_state *cso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso)); - struct nouveau_stateobj *so = so_new(5, 8, 0); - - if (cso->rt[0].blend_enable) { - so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3); - so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | - nvgl_blend_func(cso->rt[0].rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rt[0].rgb_dst_factor)); - /* FIXME: Gallium assumes GL_EXT_blend_func_separate. - It is not the case for NV30 */ - so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); - } else { - so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, rankine, NV34TCL_COLOR_MASK, 1); - so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); - - if (cso->logicop_enable) { - so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2); - so_data (so, 1); - so_data (so, nvgl_logicop_func(cso->logicop_func)); - } else { - so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, rankine, NV34TCL_DITHER_ENABLE, 1); - so_data (so, cso->dither ? 1 : 0); - - so_ref(so, &bso->so); - so_ref(NULL, &so); - bso->pipe = *cso; - return (void *)bso; -} - -static void -nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->blend = hwcso; - nv30->dirty |= NV30_NEW_BLEND; -} - -static void -nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_blend_state *bso = hwcso; - - so_ref(NULL, &bso->so); - FREE(bso); -} - - -static INLINE unsigned -wrap_mode(unsigned wrap) { - unsigned ret; - - switch (wrap) { - case PIPE_TEX_WRAP_REPEAT: - ret = NV34TCL_TX_WRAP_S_REPEAT; - break; - case PIPE_TEX_WRAP_MIRROR_REPEAT: - ret = NV34TCL_TX_WRAP_S_MIRRORED_REPEAT; - break; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - ret = NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - ret = NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_CLAMP: - ret = NV34TCL_TX_WRAP_S_CLAMP; - break; -/* case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP; - break;*/ - default: - NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); - ret = NV34TCL_TX_WRAP_S_REPEAT; - break; - } - - return ret >> NV34TCL_TX_WRAP_S_SHIFT; -} - -static void * -nv30_sampler_state_create(struct pipe_context *pipe, - const struct pipe_sampler_state *cso) -{ - struct nv30_sampler_state *ps; - uint32_t filter = 0; - - ps = MALLOC(sizeof(struct nv30_sampler_state)); - - ps->fmt = 0; - /* TODO: Not all RECTs formats have this bit set, bits 15-8 of format - are the tx format to use. We should store normalized coord flag - in sampler state structure, and set appropriate format in - nvxx_fragtex_build() - */ - /*NV34TCL_TX_FORMAT_RECT*/ - /*if (!cso->normalized_coords) { - ps->fmt |= (1<<14) ; - }*/ - - ps->wrap = ((wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) | - (wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) | - (wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT)); - - ps->en = 0; - - if (cso->max_anisotropy >= 8) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_8X; - } else - if (cso->max_anisotropy >= 4) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_4X; - } else - if (cso->max_anisotropy >= 2) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_2X; - } - - switch (cso->mag_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - filter |= NV34TCL_TX_FILTER_MAGNIFY_LINEAR; - break; - case PIPE_TEX_FILTER_NEAREST: - default: - filter |= NV34TCL_TX_FILTER_MAGNIFY_NEAREST; - break; - } - - switch (cso->min_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR; - break; - } - break; - case PIPE_TEX_FILTER_NEAREST: - default: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST; - break; - } - break; - } - - ps->filt = filter; - - { - float limit; - - limit = CLAMP(cso->lod_bias, -16.0, 15.0); - ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; - - limit = CLAMP(cso->max_lod, 0.0, 15.0); - ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/; - - limit = CLAMP(cso->min_lod, 0.0, 15.0); - ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/; - } - - if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - switch (cso->compare_func) { - case PIPE_FUNC_NEVER: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NEVER; - break; - case PIPE_FUNC_GREATER: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GREATER; - break; - case PIPE_FUNC_EQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_EQUAL; - break; - case PIPE_FUNC_GEQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GEQUAL; - break; - case PIPE_FUNC_LESS: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LESS; - break; - case PIPE_FUNC_NOTEQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NOTEQUAL; - break; - case PIPE_FUNC_LEQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LEQUAL; - break; - case PIPE_FUNC_ALWAYS: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_ALWAYS; - break; - default: - break; - } - } - - ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | - (float_to_ubyte(cso->border_color[0]) << 16) | - (float_to_ubyte(cso->border_color[1]) << 8) | - (float_to_ubyte(cso->border_color[2]) << 0)); - - return (void *)ps; -} - -static void -nv30_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) -{ - struct nv30_context *nv30 = nv30_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - nv30->tex_sampler[unit] = sampler[unit]; - nv30->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv30->nr_samplers; unit++) { - nv30->tex_sampler[unit] = NULL; - nv30->dirty_samplers |= (1 << unit); - } - - nv30->nr_samplers = nr; - nv30->dirty |= NV30_NEW_SAMPLER; -} - -static void -nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso) -{ - FREE(hwcso); -} - -static void -nv30_set_sampler_texture(struct pipe_context *pipe, unsigned nr, - struct pipe_texture **miptree) -{ - struct nv30_context *nv30 = nv30_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - pipe_texture_reference((struct pipe_texture **) - &nv30->tex_miptree[unit], miptree[unit]); - nv30->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv30->nr_textures; unit++) { - pipe_texture_reference((struct pipe_texture **) - &nv30->tex_miptree[unit], NULL); - nv30->dirty_samplers |= (1 << unit); - } - - nv30->nr_textures = nr; - nv30->dirty |= NV30_NEW_SAMPLER; -} - -static void * -nv30_rasterizer_state_create(struct pipe_context *pipe, - const struct pipe_rasterizer_state *cso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); - struct nouveau_stateobj *so = so_new(9, 19, 0); - struct nouveau_grobj *rankine = nv30->screen->rankine; - - /*XXX: ignored: - * light_twoside - * point_smooth -nohw - * multisample - */ - - so_method(so, rankine, NV34TCL_SHADE_MODEL, 1); - so_data (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT : - NV34TCL_SHADE_MODEL_SMOOTH); - - so_method(so, rankine, NV34TCL_LINE_WIDTH, 2); - so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff); - so_data (so, cso->line_smooth ? 1 : 0); - so_method(so, rankine, NV34TCL_LINE_STIPPLE_ENABLE, 2); - so_data (so, cso->line_stipple_enable ? 1 : 0); - so_data (so, (cso->line_stipple_pattern << 16) | - cso->line_stipple_factor); - - so_method(so, rankine, NV34TCL_POINT_SIZE, 1); - so_data (so, fui(cso->point_size)); - - so_method(so, rankine, NV34TCL_POLYGON_MODE_FRONT, 6); - if (cso->front_winding == PIPE_WINDING_CCW) { - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV34TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_CW: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV34TCL_FRONT_FACE_CCW); - } else { - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_CW: - so_data(so, NV34TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV34TCL_FRONT_FACE_CW); - } - so_data(so, cso->poly_smooth ? 1 : 0); - so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); - - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, cso->poly_stipple_enable ? 1 : 0); - - so_method(so, rankine, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) - so_data(so, 1); - else - so_data(so, 0); - if (cso->offset_cw || cso->offset_ccw) { - so_method(so, rankine, NV34TCL_POLYGON_OFFSET_FACTOR, 2); - so_data (so, fui(cso->offset_scale)); - so_data (so, fui(cso->offset_units * 2)); - } - - so_method(so, rankine, NV34TCL_POINT_SPRITE, 1); - if (cso->point_quad_rasterization) { - unsigned psctl = (1 << 0), i; - - for (i = 0; i < 8; i++) { - if ((cso->sprite_coord_enable >> i) & 1) - psctl |= (1 << (8 + i)); - } - - so_data(so, psctl); - } else { - so_data(so, 0); - } - - so_ref(so, &rsso->so); - so_ref(NULL, &so); - rsso->pipe = *cso; - return (void *)rsso; -} - -static void -nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->rasterizer = hwcso; - nv30->dirty |= NV30_NEW_RAST; - /*nv30->draw_dirty |= NV30_NEW_RAST;*/ -} - -static void -nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_rasterizer_state *rsso = hwcso; - - so_ref(NULL, &rsso->so); - FREE(rsso); -} - -static void * -nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe, - const struct pipe_depth_stencil_alpha_state *cso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); - struct nouveau_stateobj *so = so_new(6, 20, 0); - struct nouveau_grobj *rankine = nv30->screen->rankine; - - so_method(so, rankine, NV34TCL_DEPTH_FUNC, 3); - so_data (so, nvgl_comparison_op(cso->depth.func)); - so_data (so, cso->depth.writemask ? 1 : 0); - so_data (so, cso->depth.enabled ? 1 : 0); - - so_method(so, rankine, NV34TCL_ALPHA_FUNC_ENABLE, 3); - so_data (so, cso->alpha.enabled ? 1 : 0); - so_data (so, nvgl_comparison_op(cso->alpha.func)); - so_data (so, float_to_ubyte(cso->alpha.ref_value)); - - if (cso->stencil[0].enabled) { - so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 3); - so_data (so, cso->stencil[0].enabled ? 1 : 0); - so_data (so, cso->stencil[0].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[0].func)); - so_method(so, rankine, NV34TCL_STENCIL_FRONT_FUNC_MASK, 4); - so_data (so, cso->stencil[0].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); - } else { - so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 1); - so_data (so, 0); - } - - if (cso->stencil[1].enabled) { - so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 3); - so_data (so, cso->stencil[1].enabled ? 1 : 0); - so_data (so, cso->stencil[1].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[1].func)); - so_method(so, rankine, NV34TCL_STENCIL_BACK_FUNC_MASK, 4); - so_data (so, cso->stencil[1].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); - } else { - so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &zsaso->so); - so_ref(NULL, &so); - zsaso->pipe = *cso; - return (void *)zsaso; -} - -static void -nv30_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->zsa = hwcso; - nv30->dirty |= NV30_NEW_ZSA; -} - -static void -nv30_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_zsa_state *zsaso = hwcso; - - so_ref(NULL, &zsaso->so); - FREE(zsaso); -} - -static void * -nv30_vp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - /*struct nv30_context *nv30 = nv30_context(pipe);*/ - struct nv30_vertex_program *vp; - - vp = CALLOC(1, sizeof(struct nv30_vertex_program)); - vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - /*vp->draw = draw_create_vertex_shader(nv30->draw, &vp->pipe);*/ - - return (void *)vp; -} - -static void -nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->vertprog = hwcso; - nv30->dirty |= NV30_NEW_VERTPROG; - /*nv30->draw_dirty |= NV30_NEW_VERTPROG;*/ -} - -static void -nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_vertex_program *vp = hwcso; - - /*draw_delete_vertex_shader(nv30->draw, vp->draw);*/ - nv30_vertprog_destroy(nv30, vp); - FREE((void*)vp->pipe.tokens); - FREE(vp); -} - -static void * -nv30_fp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - struct nv30_fragment_program *fp; - - fp = CALLOC(1, sizeof(struct nv30_fragment_program)); - fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - - tgsi_scan_shader(fp->pipe.tokens, &fp->info); - - return (void *)fp; -} - -static void -nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->fragprog = hwcso; - nv30->dirty |= NV30_NEW_FRAGPROG; -} - -static void -nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_fragment_program *fp = hwcso; - - nv30_fragprog_destroy(nv30, fp); - FREE((void*)fp->pipe.tokens); - FREE(fp); -} - -static void -nv30_set_blend_color(struct pipe_context *pipe, - const struct pipe_blend_color *bcol) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->blend_colour = *bcol; - nv30->dirty |= NV30_NEW_BCOL; -} - -static void -nv30_set_stencil_ref(struct pipe_context *pipe, - const struct pipe_stencil_ref *sr) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->stencil_ref = *sr; - nv30->dirty |= NV30_NEW_SR; -} - -static void -nv30_set_clip_state(struct pipe_context *pipe, - const struct pipe_clip_state *clip) -{ -} - -static void -nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf ) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->constbuf[shader] = buf; - nv30->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); - - if (shader == PIPE_SHADER_VERTEX) { - nv30->dirty |= NV30_NEW_VERTPROG; - } else - if (shader == PIPE_SHADER_FRAGMENT) { - nv30->dirty |= NV30_NEW_FRAGPROG; - } -} - -static void -nv30_set_framebuffer_state(struct pipe_context *pipe, - const struct pipe_framebuffer_state *fb) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->framebuffer = *fb; - nv30->dirty |= NV30_NEW_FB; -} - -static void -nv30_set_polygon_stipple(struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - memcpy(nv30->stipple, stipple->stipple, 4 * 32); - nv30->dirty |= NV30_NEW_STIPPLE; -} - -static void -nv30_set_scissor_state(struct pipe_context *pipe, - const struct pipe_scissor_state *s) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->scissor = *s; - nv30->dirty |= NV30_NEW_SCISSOR; -} - -static void -nv30_set_viewport_state(struct pipe_context *pipe, - const struct pipe_viewport_state *vpt) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->viewport = *vpt; - nv30->dirty |= NV30_NEW_VIEWPORT; - /*nv30->draw_dirty |= NV30_NEW_VIEWPORT;*/ -} - -static void -nv30_set_vertex_buffers(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_buffer *vb) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count); - nv30->vtxbuf_nr = count; - - nv30->dirty |= NV30_NEW_ARRAYS; - /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ -} - -static void -nv30_set_vertex_elements(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_element *ve) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - memcpy(nv30->vtxelt, ve, sizeof(*ve) * count); - nv30->vtxelt_nr = count; - - nv30->dirty |= NV30_NEW_ARRAYS; - /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ -} - -void -nv30_init_state_functions(struct nv30_context *nv30) -{ - nv30->pipe.create_blend_state = nv30_blend_state_create; - nv30->pipe.bind_blend_state = nv30_blend_state_bind; - nv30->pipe.delete_blend_state = nv30_blend_state_delete; - - nv30->pipe.create_sampler_state = nv30_sampler_state_create; - nv30->pipe.bind_fragment_sampler_states = nv30_sampler_state_bind; - nv30->pipe.delete_sampler_state = nv30_sampler_state_delete; - nv30->pipe.set_fragment_sampler_textures = nv30_set_sampler_texture; - - nv30->pipe.create_rasterizer_state = nv30_rasterizer_state_create; - nv30->pipe.bind_rasterizer_state = nv30_rasterizer_state_bind; - nv30->pipe.delete_rasterizer_state = nv30_rasterizer_state_delete; - - nv30->pipe.create_depth_stencil_alpha_state = - nv30_depth_stencil_alpha_state_create; - nv30->pipe.bind_depth_stencil_alpha_state = - nv30_depth_stencil_alpha_state_bind; - nv30->pipe.delete_depth_stencil_alpha_state = - nv30_depth_stencil_alpha_state_delete; - - nv30->pipe.create_vs_state = nv30_vp_state_create; - nv30->pipe.bind_vs_state = nv30_vp_state_bind; - nv30->pipe.delete_vs_state = nv30_vp_state_delete; - - nv30->pipe.create_fs_state = nv30_fp_state_create; - nv30->pipe.bind_fs_state = nv30_fp_state_bind; - nv30->pipe.delete_fs_state = nv30_fp_state_delete; - - nv30->pipe.set_blend_color = nv30_set_blend_color; - nv30->pipe.set_stencil_ref = nv30_set_stencil_ref; - nv30->pipe.set_clip_state = nv30_set_clip_state; - nv30->pipe.set_constant_buffer = nv30_set_constant_buffer; - nv30->pipe.set_framebuffer_state = nv30_set_framebuffer_state; - nv30->pipe.set_polygon_stipple = nv30_set_polygon_stipple; - nv30->pipe.set_scissor_state = nv30_set_scissor_state; - nv30->pipe.set_viewport_state = nv30_set_viewport_state; - - nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers; - nv30->pipe.set_vertex_elements = nv30_set_vertex_elements; -} - diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h deleted file mode 100644 index e42e872de75..00000000000 --- a/src/gallium/drivers/nv30/nv30_state.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef __NV30_STATE_H__ -#define __NV30_STATE_H__ - -#include "pipe/p_state.h" -#include "tgsi/tgsi_scan.h" - -struct nv30_sampler_state { - uint32_t fmt; - uint32_t wrap; - uint32_t en; - uint32_t filt; - uint32_t bcol; -}; - -struct nv30_vertex_program_exec { - uint32_t data[4]; - boolean has_branch_offset; - int const_index; -}; - -struct nv30_vertex_program_data { - int index; /* immediates == -1 */ - float value[4]; -}; - -struct nv30_vertex_program { - struct pipe_shader_state pipe; - - boolean translated; - - struct nv30_vertex_program_exec *insns; - unsigned nr_insns; - struct nv30_vertex_program_data *consts; - unsigned nr_consts; - - struct nouveau_resource *exec; - unsigned exec_start; - struct nouveau_resource *data; - unsigned data_start; - unsigned data_start_min; - - uint32_t ir; - uint32_t or; - struct nouveau_stateobj *so; -}; - -struct nv30_fragment_program_data { - unsigned offset; - unsigned index; -}; - -struct nv30_fragment_program { - struct pipe_shader_state pipe; - struct tgsi_shader_info info; - - boolean translated; - boolean on_hw; - unsigned samplers; - - uint32_t *insn; - int insn_len; - - struct nv30_fragment_program_data *consts; - unsigned nr_consts; - - struct pipe_buffer *buffer; - - uint32_t fp_control; - uint32_t fp_reg_control; - struct nouveau_stateobj *so; -}; - -struct nv30_miptree { - struct pipe_texture base; - struct nouveau_bo *bo; - - struct pipe_buffer *buffer; - uint total_size; - - struct { - uint pitch; - uint *image_offset; - } level[PIPE_MAX_TEXTURE_LEVELS]; -}; - -#endif diff --git a/src/gallium/drivers/nv30/nv30_state_blend.c b/src/gallium/drivers/nv30/nv30_state_blend.c deleted file mode 100644 index c36d58c040c..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_blend.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_blend_validate(struct nv30_context *nv30) -{ - so_ref(nv30->blend->so, &nv30->state.hw[NV30_STATE_BLEND]); - return TRUE; -} - -struct nv30_state_entry nv30_state_blend = { - .validate = nv30_state_blend_validate, - .dirty = { - .pipe = NV30_NEW_BLEND, - .hw = NV30_STATE_BLEND - } -}; - -static boolean -nv30_state_blend_colour_validate(struct nv30_context *nv30) -{ - struct nouveau_stateobj *so = so_new(1, 1, 0); - struct pipe_blend_color *bcol = &nv30->blend_colour; - - so_method(so, nv30->screen->rankine, NV34TCL_BLEND_COLOR, 1); - so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | - (float_to_ubyte(bcol->color[0]) << 16) | - (float_to_ubyte(bcol->color[1]) << 8) | - (float_to_ubyte(bcol->color[2]) << 0))); - - so_ref(so, &nv30->state.hw[NV30_STATE_BCOL]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_blend_colour = { - .validate = nv30_state_blend_colour_validate, - .dirty = { - .pipe = NV30_NEW_BCOL, - .hw = NV30_STATE_BCOL - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c deleted file mode 100644 index deefe7fd8db..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_emit.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "nv30_context.h" -#include "nv30_state.h" - -static struct nv30_state_entry *render_states[] = { - &nv30_state_framebuffer, - &nv30_state_rasterizer, - &nv30_state_scissor, - &nv30_state_stipple, - &nv30_state_fragprog, - &nv30_state_fragtex, - &nv30_state_vertprog, - &nv30_state_blend, - &nv30_state_blend_colour, - &nv30_state_zsa, - &nv30_state_sr, - &nv30_state_viewport, - &nv30_state_vbo, - NULL -}; - -static void -nv30_state_do_validate(struct nv30_context *nv30, - struct nv30_state_entry **states) -{ - while (*states) { - struct nv30_state_entry *e = *states; - - if (nv30->dirty & e->dirty.pipe) { - if (e->validate(nv30)) { - nv30->state.dirty |= (1ULL << e->dirty.hw); - } - } - - states++; - } - nv30->dirty = 0; -} - -void -nv30_state_emit(struct nv30_context *nv30) -{ - struct nouveau_channel *chan = nv30->screen->base.channel; - struct nv30_state *state = &nv30->state; - struct nv30_screen *screen = nv30->screen; - unsigned i; - uint64_t states; - - /* XXX: racy! - */ - if (nv30 != screen->cur_ctx) { - for (i = 0; i < NV30_STATE_MAX; i++) { - if (state->hw[i] && screen->state[i] != state->hw[i]) - state->dirty |= (1ULL << i); - } - - screen->cur_ctx = nv30; - } - - for (i = 0, states = state->dirty; states; i++) { - if (!(states & (1ULL << i))) - continue; - so_ref (state->hw[i], &nv30->screen->state[i]); - if (state->hw[i]) - so_emit(chan, nv30->screen->state[i]); - states &= ~(1ULL << i); - } - - state->dirty = 0; -} - -void -nv30_state_flush_notify(struct nouveau_channel *chan) -{ - struct nv30_context *nv30 = chan->user_private; - struct nv30_state *state = &nv30->state; - unsigned i, samplers; - - so_emit_reloc_markers(chan, state->hw[NV30_STATE_FB]); - for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { - if (!(samplers & (1 << i))) - continue; - so_emit_reloc_markers(chan, - state->hw[NV30_STATE_FRAGTEX0+i]); - samplers &= ~(1ULL << i); - } - so_emit_reloc_markers(chan, state->hw[NV30_STATE_FRAGPROG]); - if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/) - so_emit_reloc_markers(chan, state->hw[NV30_STATE_VTXBUF]); -} - -boolean -nv30_state_validate(struct nv30_context *nv30) -{ -#if 0 - boolean was_sw = nv30->fallback_swtnl ? TRUE : FALSE; - - if (nv30->render_mode != HW) { - /* Don't even bother trying to go back to hw if none - * of the states that caused swtnl previously have changed. - */ - if ((nv30->fallback_swtnl & nv30->dirty) - != nv30->fallback_swtnl) - return FALSE; - - /* Attempt to go to hwtnl again */ - nv30->pipe.flush(&nv30->pipe, 0, NULL); - nv30->dirty |= (NV30_NEW_VIEWPORT | - NV30_NEW_VERTPROG | - NV30_NEW_ARRAYS); - nv30->render_mode = HW; - } -#endif - nv30_state_do_validate(nv30, render_states); -#if 0 - if (nv30->fallback_swtnl || nv30->fallback_swrast) - return FALSE; - - if (was_sw) - NOUVEAU_ERR("swtnl->hw\n"); -#endif - return TRUE; -} diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c deleted file mode 100644 index f7fe9833c77..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_fb.c +++ /dev/null @@ -1,173 +0,0 @@ -#include "nv30_context.h" -#include "nouveau/nouveau_util.h" - -static boolean -nv30_state_framebuffer_validate(struct nv30_context *nv30) -{ - struct pipe_framebuffer_state *fb = &nv30->framebuffer; - struct nouveau_channel *chan = nv30->screen->base.channel; - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct nv04_surface *rt[2], *zeta = NULL; - uint32_t rt_enable = 0, rt_format = 0; - int i, colour_format = 0, zeta_format = 0, depth_only = 0; - struct nouveau_stateobj *so = so_new(12, 18, 10); - unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; - unsigned w = fb->width; - unsigned h = fb->height; - struct nv30_miptree *nv30mt; - int colour_bits = 32, zeta_bits = 32; - - for (i = 0; i < fb->nr_cbufs; i++) { - if (colour_format) { - assert(colour_format == fb->cbufs[i]->format); - } else { - colour_format = fb->cbufs[i]->format; - rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i); - rt[i] = (struct nv04_surface *)fb->cbufs[i]; - } - } - - if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) - rt_enable |= NV34TCL_RT_ENABLE_MRT; - - if (fb->zsbuf) { - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0|NV34TCL_RT_ENABLE_COLOR1)) { - /* Render to at least a colour buffer */ - if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); - for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); - - rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | - (log2i(rt[0]->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | - (log2i(rt[0]->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); - } - else - rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; - } else if (fb->zsbuf) { - depth_only = 1; - - /* Render to depth buffer only */ - if (!(zeta->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); - - rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | - (log2i(zeta->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | - (log2i(zeta->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); - } - else - rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; - } else { - return FALSE; - } - - switch (colour_format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - rt_format |= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - case 0: - rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5; - colour_bits = 16; - break; - default: - assert(0); - } - - switch (zeta_format) { - case PIPE_FORMAT_Z16_UNORM: - rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16; - zeta_bits = 16; - break; - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - case 0: - rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8; - break; - default: - assert(0); - } - - if (colour_bits > zeta_bits) { - return FALSE; - } - - if (depth_only || (rt_enable & NV34TCL_RT_ENABLE_COLOR0)) { - struct nv04_surface *rt0 = (depth_only ? zeta : rt[0]); - uint32_t pitch = rt0->pitch; - - if (zeta) { - pitch |= (zeta->pitch << 16); - } else { - pitch |= (pitch << 16); - } - - nv30mt = (struct nv30_miptree *) rt0->base.texture; - so_method(so, rankine, NV34TCL_DMA_COLOR0, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, rankine, NV34TCL_COLOR0_PITCH, 2); - so_data (so, pitch); - so_reloc (so, nouveau_bo(nv30mt->buffer), rt0->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); - } - - if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { - nv30mt = (struct nv30_miptree *)rt[1]->base.texture; - so_method(so, rankine, NV34TCL_DMA_COLOR1, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, rankine, NV34TCL_COLOR1_OFFSET, 2); - so_reloc (so, nouveau_bo(nv30mt->buffer), rt[1]->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_data (so, rt[1]->pitch); - } - - if (zeta_format) { - nv30mt = (struct nv30_miptree *)zeta->base.texture; - so_method(so, rankine, NV34TCL_DMA_ZETA, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, rankine, NV34TCL_ZETA_OFFSET, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), zeta->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); - /* TODO: allocate LMA depth buffer */ - } - - so_method(so, rankine, NV34TCL_RT_ENABLE, 1); - so_data (so, rt_enable); - so_method(so, rankine, NV34TCL_RT_HORIZ, 3); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_data (so, rt_format); - so_method(so, rankine, NV34TCL_VIEWPORT_HORIZ, 2); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_method(so, rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); - so_data (so, ((w - 1) << 16) | 0); - so_data (so, ((h - 1) << 16) | 0); - so_method(so, rankine, 0x1d88, 1); - so_data (so, (1 << 12) | h); - /* Wonder why this is needed, context should all be set to zero on init */ - so_method(so, rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1); - so_data (so, 0); - - so_ref(so, &nv30->state.hw[NV30_STATE_FB]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_framebuffer = { - .validate = nv30_state_framebuffer_validate, - .dirty = { - .pipe = NV30_NEW_FB, - .hw = NV30_STATE_FB - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_rasterizer.c b/src/gallium/drivers/nv30/nv30_state_rasterizer.c deleted file mode 100644 index 6d1b60e043d..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_rasterizer.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_rasterizer_validate(struct nv30_context *nv30) -{ - so_ref(nv30->rasterizer->so, - &nv30->state.hw[NV30_STATE_RAST]); - return TRUE; -} - -struct nv30_state_entry nv30_state_rasterizer = { - .validate = nv30_state_rasterizer_validate, - .dirty = { - .pipe = NV30_NEW_RAST, - .hw = NV30_STATE_RAST - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_scissor.c b/src/gallium/drivers/nv30/nv30_state_scissor.c deleted file mode 100644 index ba61a9e24a4..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_scissor.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_scissor_validate(struct nv30_context *nv30) -{ - struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe; - struct pipe_scissor_state *s = &nv30->scissor; - struct nouveau_stateobj *so; - - if (nv30->state.hw[NV30_STATE_SCISSOR] && - (rast->scissor == 0 && nv30->state.scissor_enabled == 0)) - return FALSE; - nv30->state.scissor_enabled = rast->scissor; - - so = so_new(1, 2, 0); - so_method(so, nv30->screen->rankine, NV34TCL_SCISSOR_HORIZ, 2); - if (nv30->state.scissor_enabled) { - so_data (so, ((s->maxx - s->minx) << 16) | s->minx); - so_data (so, ((s->maxy - s->miny) << 16) | s->miny); - } else { - so_data (so, 4096 << 16); - so_data (so, 4096 << 16); - } - - so_ref(so, &nv30->state.hw[NV30_STATE_SCISSOR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_scissor = { - .validate = nv30_state_scissor_validate, - .dirty = { - .pipe = NV30_NEW_SCISSOR | NV30_NEW_RAST, - .hw = NV30_STATE_SCISSOR - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_stipple.c b/src/gallium/drivers/nv30/nv30_state_stipple.c deleted file mode 100644 index ed520a4f439..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_stipple.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_stipple_validate(struct nv30_context *nv30) -{ - struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe; - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct nouveau_stateobj *so; - - if (nv30->state.hw[NV30_STATE_STIPPLE] && - (rast->poly_stipple_enable == 0 && nv30->state.stipple_enabled == 0)) - return FALSE; - - if (rast->poly_stipple_enable) { - unsigned i; - - so = so_new(2, 33, 0); - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 1); - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32); - for (i = 0; i < 32; i++) - so_data(so, nv30->stipple[i]); - } else { - so = so_new(1, 1, 0); - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &nv30->state.hw[NV30_STATE_STIPPLE]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_stipple = { - .validate = nv30_state_stipple_validate, - .dirty = { - .pipe = NV30_NEW_STIPPLE | NV30_NEW_RAST, - .hw = NV30_STATE_STIPPLE, - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_viewport.c b/src/gallium/drivers/nv30/nv30_state_viewport.c deleted file mode 100644 index 6fccd6b60e7..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_viewport.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_viewport_validate(struct nv30_context *nv30) -{ - struct pipe_viewport_state *vpt = &nv30->viewport; - struct nouveau_stateobj *so; - - if (nv30->state.hw[NV30_STATE_VIEWPORT] && - !(nv30->dirty & NV30_NEW_VIEWPORT)) - return FALSE; - - so = so_new(3, 10, 0); - so_method(so, nv30->screen->rankine, - NV34TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(vpt->translate[0])); - so_data (so, fui(vpt->translate[1])); - so_data (so, fui(vpt->translate[2])); - so_data (so, fui(vpt->translate[3])); - so_data (so, fui(vpt->scale[0])); - so_data (so, fui(vpt->scale[1])); - so_data (so, fui(vpt->scale[2])); - so_data (so, fui(vpt->scale[3])); -/* so_method(so, nv30->screen->rankine, 0x1d78, 1); - so_data (so, 1); -*/ - /* TODO/FIXME: never saw value 0x0110 in renouveau dumps, only 0x0001 */ - so_method(so, nv30->screen->rankine, 0x1d78, 1); - so_data (so, 1); - - so_ref(so, &nv30->state.hw[NV30_STATE_VIEWPORT]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_viewport = { - .validate = nv30_state_viewport_validate, - .dirty = { - .pipe = NV30_NEW_VIEWPORT | NV30_NEW_RAST, - .hw = NV30_STATE_VIEWPORT - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_zsa.c b/src/gallium/drivers/nv30/nv30_state_zsa.c deleted file mode 100644 index 88cd74f180a..00000000000 --- a/src/gallium/drivers/nv30/nv30_state_zsa.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_zsa_validate(struct nv30_context *nv30) -{ - so_ref(nv30->zsa->so, - &nv30->state.hw[NV30_STATE_ZSA]); - return TRUE; -} - -struct nv30_state_entry nv30_state_zsa = { - .validate = nv30_state_zsa_validate, - .dirty = { - .pipe = NV30_NEW_ZSA, - .hw = NV30_STATE_ZSA - } -}; - -static boolean -nv30_state_sr_validate(struct nv30_context *nv30) -{ - struct nouveau_stateobj *so = so_new(2, 2, 0); - struct pipe_stencil_ref *sr = &nv30->stencil_ref; - - so_method(so, nv30->screen->rankine, NV34TCL_STENCIL_FRONT_FUNC_REF, 1); - so_data (so, sr->ref_value[0]); - so_method(so, nv30->screen->rankine, NV34TCL_STENCIL_BACK_FUNC_REF, 1); - so_data (so, sr->ref_value[1]); - - so_ref(so, &nv30->state.hw[NV30_STATE_SR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_sr = { - .validate = nv30_state_sr_validate, - .dirty = { - .pipe = NV30_NEW_SR, - .hw = NV30_STATE_SR - } -}; diff --git a/src/gallium/drivers/nv30/nv30_transfer.c b/src/gallium/drivers/nv30/nv30_transfer.c deleted file mode 100644 index 3aeda51ea19..00000000000 --- a/src/gallium/drivers/nv30/nv30_transfer.c +++ /dev/null @@ -1,178 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "nouveau/nouveau_winsys.h" -#include "nv30_context.h" -#include "nv30_screen.h" -#include "nv30_state.h" - -struct nv30_transfer { - struct pipe_transfer base; - struct pipe_surface *surface; - boolean direct; -}; - -static void -nv30_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, - struct pipe_texture *template) -{ - memset(template, 0, sizeof(struct pipe_texture)); - template->target = pt->target; - template->format = pt->format; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->last_level = 0; - template->nr_samples = pt->nr_samples; - - template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | - NOUVEAU_TEXTURE_USAGE_LINEAR; -} - -static struct pipe_transfer * -nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct nv30_miptree *mt = (struct nv30_miptree *)pt; - struct nv30_transfer *tx; - struct pipe_texture tx_tex_template, *tx_tex; - - tx = CALLOC_STRUCT(nv30_transfer); - if (!tx) - return NULL; - - pipe_texture_reference(&tx->base.texture, pt); - tx->base.x = x; - tx->base.y = y; - tx->base.width = w; - tx->base.height = h; - tx->base.stride = mt->level[level].pitch; - tx->base.usage = usage; - tx->base.face = face; - tx->base.level = level; - tx->base.zslice = zslice; - - /* Direct access to texture */ - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || - debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && - pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) - { - tx->direct = true; - tx->surface = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - pipe_transfer_buffer_flags(&tx->base)); - return &tx->base; - } - - tx->direct = false; - - nv30_compatible_transfer_tex(pt, w, h, &tx_tex_template); - - tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); - if (!tx_tex) - { - FREE(tx); - return NULL; - } - - tx->base.stride = ((struct nv30_miptree*)tx_tex)->level[0].pitch; - - tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, - 0, 0, 0, - pipe_transfer_buffer_flags(&tx->base)); - - pipe_texture_reference(&tx_tex, NULL); - - if (!tx->surface) - { - pipe_surface_reference(&tx->surface, NULL); - FREE(tx); - return NULL; - } - - if (usage & PIPE_TRANSFER_READ) { - struct nv30_screen *nvscreen = nv30_screen(pscreen); - struct pipe_surface *src; - - src = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - PIPE_BUFFER_USAGE_GPU_READ); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - /* TODO: Check if SIFM can un-swizzle */ - nvscreen->eng2d->copy(nvscreen->eng2d, - tx->surface, 0, 0, - src, x, y, - w, h); - - pipe_surface_reference(&src, NULL); - } - - return &tx->base; -} - -static void -nv30_transfer_del(struct pipe_transfer *ptx) -{ - struct nv30_transfer *tx = (struct nv30_transfer *)ptx; - - if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = ptx->texture->screen; - struct nv30_screen *nvscreen = nv30_screen(pscreen); - struct pipe_surface *dst; - - dst = pscreen->get_tex_surface(pscreen, ptx->texture, - ptx->face, ptx->level, ptx->zslice, - PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - nvscreen->eng2d->copy(nvscreen->eng2d, - dst, tx->base.x, tx->base.y, - tx->surface, 0, 0, - tx->base.width, tx->base.height); - - pipe_surface_reference(&dst, NULL); - } - - pipe_surface_reference(&tx->surface, NULL); - pipe_texture_reference(&ptx->texture, NULL); - FREE(ptx); -} - -static void * -nv30_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv30_transfer *tx = (struct nv30_transfer *)ptx; - struct nv04_surface *ns = (struct nv04_surface *)tx->surface; - struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; - void *map = pipe_buffer_map(pscreen, mt->buffer, - pipe_transfer_buffer_flags(ptx)); - - if(!tx->direct) - return map + ns->base.offset; - else - return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format); -} - -static void -nv30_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv30_transfer *tx = (struct nv30_transfer *)ptx; - struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; - - pipe_buffer_unmap(pscreen, mt->buffer); -} - -void -nv30_screen_init_transfer_functions(struct pipe_screen *pscreen) -{ - pscreen->get_tex_transfer = nv30_transfer_new; - pscreen->tex_transfer_destroy = nv30_transfer_del; - pscreen->transfer_map = nv30_transfer_map; - pscreen->transfer_unmap = nv30_transfer_unmap; -} diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c deleted file mode 100644 index 809be3712da..00000000000 --- a/src/gallium/drivers/nv30/nv30_vertprog.c +++ /dev/null @@ -1,842 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_dump.h" - -#include "nv30_context.h" -#include "nv30_state.h" - -/* TODO (at least...): - * 1. Indexed consts + ARL - * 2. Arb. swz/negation - * 3. NV_vp11, NV_vp2, NV_vp3 features - * - extra arith opcodes - * - branching - * - texture sampling - * - indexed attribs - * - indexed results - * 4. bugs - */ - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 8 -#define MASK_Y 4 -#define MASK_Z 2 -#define MASK_W 1 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE 0 -#define DEF_CTEST 0 -#include "nv30_shader.h" - -#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv30_sr_neg((s)) -#define abs(s) nv30_sr_abs((s)) - -struct nv30_vpc { - struct nv30_vertex_program *vp; - - struct nv30_vertex_program_exec *vpi; - - unsigned output_map[PIPE_MAX_SHADER_OUTPUTS]; - - int high_temp; - int temp_temp_count; - - struct nv30_sreg *imm; - unsigned nr_imm; -}; - -static struct nv30_sreg -temp(struct nv30_vpc *vpc) -{ - int idx; - - idx = vpc->temp_temp_count++; - idx += vpc->high_temp + 1; - return nv30_sr(NV30SR_TEMP, idx); -} - -static struct nv30_sreg -constant(struct nv30_vpc *vpc, int pipe, float x, float y, float z, float w) -{ - struct nv30_vertex_program *vp = vpc->vp; - struct nv30_vertex_program_data *vpd; - int idx; - - if (pipe >= 0) { - for (idx = 0; idx < vp->nr_consts; idx++) { - if (vp->consts[idx].index == pipe) - return nv30_sr(NV30SR_CONST, idx); - } - } - - idx = vp->nr_consts++; - vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); - vpd = &vp->consts[idx]; - - vpd->index = pipe; - vpd->value[0] = x; - vpd->value[1] = y; - vpd->value[2] = z; - vpd->value[3] = w; - return nv30_sr(NV30SR_CONST, idx); -} - -#define arith(cc,s,o,d,m,s0,s1,s2) \ - nv30_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2)) - -static void -emit_src(struct nv30_vpc *vpc, uint32_t *hw, int pos, struct nv30_sreg src) -{ - struct nv30_vertex_program *vp = vpc->vp; - uint32_t sr = 0; - - switch (src.type) { - case NV30SR_TEMP: - sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT); - sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT); - break; - case NV30SR_INPUT: - sr |= (NV30_VP_SRC_REG_TYPE_INPUT << - NV30_VP_SRC_REG_TYPE_SHIFT); - vp->ir |= (1 << src.index); - hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT); - break; - case NV30SR_CONST: - sr |= (NV30_VP_SRC_REG_TYPE_CONST << - NV30_VP_SRC_REG_TYPE_SHIFT); - assert(vpc->vpi->const_index == -1 || - vpc->vpi->const_index == src.index); - vpc->vpi->const_index = src.index; - break; - case NV30SR_NONE: - sr |= (NV30_VP_SRC_REG_TYPE_INPUT << - NV30_VP_SRC_REG_TYPE_SHIFT); - break; - default: - assert(0); - } - - if (src.negate) - sr |= NV30_VP_SRC_NEGATE; - - if (src.abs) - hw[0] |= (1 << (21 + pos)); - - sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) | - (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) | - (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) | - (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT)); - -/* - * |VVV| - * d�.�b - * \u/ - * - */ - - switch (pos) { - case 0: - hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >> - NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT; - hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) << - NV30_VP_INST_SRC0L_SHIFT; - break; - case 1: - hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT; - break; - case 2: - hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >> - NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT; - hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) << - NV30_VP_INST_SRC2L_SHIFT; - break; - default: - assert(0); - } -} - -static void -emit_dst(struct nv30_vpc *vpc, uint32_t *hw, int slot, struct nv30_sreg dst) -{ - struct nv30_vertex_program *vp = vpc->vp; - - switch (dst.type) { - case NV30SR_TEMP: - hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT); - break; - case NV30SR_OUTPUT: - switch (dst.index) { - case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; - case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; - case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; - case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; - case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; - case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; - case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; - case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; - case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; - case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; - case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; - case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; - case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; - case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; - default: - break; - } - - hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT); - hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); - - /*XXX: no way this is entirely correct, someone needs to - * figure out what exactly it is. - */ - hw[3] |= 0x800; - break; - default: - assert(0); - } -} - -static void -nv30_vp_arith(struct nv30_vpc *vpc, int slot, int op, - struct nv30_sreg dst, int mask, - struct nv30_sreg s0, struct nv30_sreg s1, - struct nv30_sreg s2) -{ - struct nv30_vertex_program *vp = vpc->vp; - uint32_t *hw; - - vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); - vpc->vpi = &vp->insns[vp->nr_insns - 1]; - memset(vpc->vpi, 0, sizeof(*vpc->vpi)); - vpc->vpi->const_index = -1; - - hw = vpc->vpi->data; - - hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT); - hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) | - (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) | - (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) | - (3 << NV30_VP_INST_COND_SWZ_W_SHIFT)); - - hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT); -// hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK; -// hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT); - - if (dst.type == NV30SR_OUTPUT) { - if (slot) - hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT); - else - hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT); - } else { - if (slot) - hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT); - else - hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT); - } - - emit_dst(vpc, hw, slot, dst); - emit_src(vpc, hw, 0, s0); - emit_src(vpc, hw, 1, s1); - emit_src(vpc, hw, 2, s2); -} - -static INLINE struct nv30_sreg -tgsi_src(struct nv30_vpc *vpc, const struct tgsi_full_src_register *fsrc) { - struct nv30_sreg src; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - src = nv30_sr(NV30SR_INPUT, fsrc->Register.Index); - break; - case TGSI_FILE_CONSTANT: - src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0); - break; - case TGSI_FILE_IMMEDIATE: - src = vpc->imm[fsrc->Register.Index]; - break; - case TGSI_FILE_TEMPORARY: - if (vpc->high_temp < fsrc->Register.Index) - vpc->high_temp = fsrc->Register.Index; - src = nv30_sr(NV30SR_TEMP, fsrc->Register.Index); - break; - default: - NOUVEAU_ERR("bad src file\n"); - break; - } - - src.abs = fsrc->Register.Absolute; - src.negate = fsrc->Register.Negate; - src.swz[0] = fsrc->Register.SwizzleX; - src.swz[1] = fsrc->Register.SwizzleY; - src.swz[2] = fsrc->Register.SwizzleZ; - src.swz[3] = fsrc->Register.SwizzleW; - return src; -} - -static INLINE struct nv30_sreg -tgsi_dst(struct nv30_vpc *vpc, const struct tgsi_full_dst_register *fdst) { - struct nv30_sreg dst; - - switch (fdst->Register.File) { - case TGSI_FILE_OUTPUT: - dst = nv30_sr(NV30SR_OUTPUT, - vpc->output_map[fdst->Register.Index]); - - break; - case TGSI_FILE_TEMPORARY: - dst = nv30_sr(NV30SR_TEMP, fdst->Register.Index); - if (vpc->high_temp < dst.index) - vpc->high_temp = dst.index; - break; - default: - NOUVEAU_ERR("bad dst file\n"); - break; - } - - return dst; -} - -static INLINE int -tgsi_mask(uint tgsi) -{ - int mask = 0; - - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; - return mask; -} - -static boolean -nv30_vertprog_parse_instruction(struct nv30_vpc *vpc, - const struct tgsi_full_instruction *finst) -{ - struct nv30_sreg src[3], dst, tmp; - struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); - int mask; - int ai = -1, ci = -1; - int i; - - if (finst->Instruction.Opcode == TGSI_OPCODE_END) - return TRUE; - - vpc->temp_temp_count = 0; - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - if (fsrc->Register.File == TGSI_FILE_TEMPORARY) { - src[i] = tgsi_src(vpc, fsrc); - } - } - - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - if (ai == -1 || ai == fsrc->Register.Index) { - ai = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - /*XXX: index comparison is broken now that consts come from - * two different register files. - */ - case TGSI_FILE_CONSTANT: - case TGSI_FILE_IMMEDIATE: - if (ci == -1 || ci == fsrc->Register.Index) { - ci = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - case TGSI_FILE_TEMPORARY: - /* handled above */ - break; - default: - NOUVEAU_ERR("bad src file\n"); - return FALSE; - } - } - - dst = tgsi_dst(vpc, &finst->Dst[0]); - mask = tgsi_mask(finst->Dst[0].Register.WriteMask); - - switch (finst->Instruction.Opcode) { - case TGSI_OPCODE_ABS: - arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); - break; - case TGSI_OPCODE_ADD: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); - break; - case TGSI_OPCODE_ARL: - arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_DP3: - arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DP4: - arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DPH: - arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DST: - arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_EX2: - arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_EXP: - arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_FLR: - arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FRC: - arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_LG2: - arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LIT: - arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LOG: - arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_MAD: - arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAX: - arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MIN: - arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MOV: - arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_MUL: - arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_POW: - tmp = temp(vpc); - arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, - swz(src[0], X, X, X, X)); - arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), - swz(src[1], X, X, X, X), none); - arith(vpc, 1, OP_EX2, dst, mask, none, none, - swz(tmp, X, X, X, X)); - break; - case TGSI_OPCODE_RCP: - arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_RET: - break; - case TGSI_OPCODE_RSQ: - arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_SGE: - arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SGT: - arith(vpc, 0, OP_SGT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SLT: - arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SUB: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); - break; - case TGSI_OPCODE_XPD: - tmp = temp(vpc); - arith(vpc, 0, OP_MUL, tmp, mask, - swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), - swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), - neg(tmp)); - break; - default: - NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); - return FALSE; - } - - return TRUE; -} - -static boolean -nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc, - const struct tgsi_full_declaration *fdec) -{ - int hw; - - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - hw = NV30_VP_INST_DEST_POS; - break; - case TGSI_SEMANTIC_COLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_VP_INST_DEST_COL0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_VP_INST_DEST_COL1; - } else { - NOUVEAU_ERR("bad colour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_BCOLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_VP_INST_DEST_BFC0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_VP_INST_DEST_BFC1; - } else { - NOUVEAU_ERR("bad bcolour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_FOG: - hw = NV30_VP_INST_DEST_FOGC; - break; - case TGSI_SEMANTIC_PSIZE: - hw = NV30_VP_INST_DEST_PSZ; - break; - case TGSI_SEMANTIC_GENERIC: - if (fdec->Semantic.Index <= 7) { - hw = NV30_VP_INST_DEST_TC(fdec->Semantic.Index); - } else { - NOUVEAU_ERR("bad generic semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_EDGEFLAG: - NOUVEAU_ERR("cannot handle edgeflag output\n"); - return FALSE; - default: - NOUVEAU_ERR("bad output semantic\n"); - return FALSE; - } - - vpc->output_map[fdec->Range.First] = hw; - return TRUE; -} - -static boolean -nv30_vertprog_prepare(struct nv30_vpc *vpc) -{ - struct tgsi_parse_context p; - int nr_imm = 0; - - tgsi_parse_init(&p, vpc->vp->pipe.tokens); - while (!tgsi_parse_end_of_tokens(&p)) { - const union tgsi_full_token *tok = &p.FullToken; - - tgsi_parse_token(&p); - switch(tok->Token.Type) { - case TGSI_TOKEN_TYPE_IMMEDIATE: - nr_imm++; - break; - default: - break; - } - } - tgsi_parse_free(&p); - - if (nr_imm) { - vpc->imm = CALLOC(nr_imm, sizeof(struct nv30_sreg)); - assert(vpc->imm); - } - - return TRUE; -} - -static void -nv30_vertprog_translate(struct nv30_context *nv30, - struct nv30_vertex_program *vp) -{ - struct tgsi_parse_context parse; - struct nv30_vpc *vpc = NULL; - - tgsi_dump(vp->pipe.tokens,0); - - vpc = CALLOC(1, sizeof(struct nv30_vpc)); - if (!vpc) - return; - vpc->vp = vp; - vpc->high_temp = -1; - - if (!nv30_vertprog_prepare(vpc)) { - FREE(vpc); - return; - } - - tgsi_parse_init(&parse, vp->pipe.tokens); - - while (!tgsi_parse_end_of_tokens(&parse)) { - tgsi_parse_token(&parse); - - switch (parse.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - { - const struct tgsi_full_declaration *fdec; - fdec = &parse.FullToken.FullDeclaration; - switch (fdec->Declaration.File) { - case TGSI_FILE_OUTPUT: - if (!nv30_vertprog_parse_decl_output(vpc, fdec)) - goto out_err; - break; - default: - break; - } - } - break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - { - const struct tgsi_full_immediate *imm; - - imm = &parse.FullToken.FullImmediate; - assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); - assert(imm->Immediate.NrTokens == 4 + 1); - vpc->imm[vpc->nr_imm++] = - constant(vpc, -1, - imm->u[0].Float, - imm->u[1].Float, - imm->u[2].Float, - imm->u[3].Float); - } - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - const struct tgsi_full_instruction *finst; - finst = &parse.FullToken.FullInstruction; - if (!nv30_vertprog_parse_instruction(vpc, finst)) - goto out_err; - } - break; - default: - break; - } - } - - vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST; - vp->translated = TRUE; -out_err: - tgsi_parse_free(&parse); - FREE(vpc); -} - -static boolean -nv30_vertprog_validate(struct nv30_context *nv30) -{ - struct pipe_screen *pscreen = nv30->pipe.screen; - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - struct nv30_vertex_program *vp; - struct pipe_buffer *constbuf; - boolean upload_code = FALSE, upload_data = FALSE; - int i; - - vp = nv30->vertprog; - constbuf = nv30->constbuf[PIPE_SHADER_VERTEX]; - - /* Translate TGSI shader into hw bytecode */ - if (!vp->translated) { - nv30_vertprog_translate(nv30, vp); - if (!vp->translated) - return FALSE; - } - - /* Allocate hw vtxprog exec slots */ - if (!vp->exec) { - struct nouveau_resource *heap = nv30->screen->vp_exec_heap; - struct nouveau_stateobj *so; - uint vplen = vp->nr_insns; - - if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) { - while (heap->next && heap->size < vplen) { - struct nv30_vertex_program *evict; - - evict = heap->next->priv; - nouveau_resource_free(&evict->exec); - } - - if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) - assert(0); - } - - so = so_new(1, 1, 0); - so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1); - so_data (so, vp->exec->start); - so_ref(so, &vp->so); - so_ref(NULL, &so); - - upload_code = TRUE; - } - - /* Allocate hw vtxprog const slots */ - if (vp->nr_consts && !vp->data) { - struct nouveau_resource *heap = nv30->screen->vp_data_heap; - - if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) { - while (heap->next && heap->size < vp->nr_consts) { - struct nv30_vertex_program *evict; - - evict = heap->next->priv; - nouveau_resource_free(&evict->data); - } - - if (nouveau_resource_alloc(heap, vp->nr_consts, vp, - &vp->data)) - assert(0); - } - - /*XXX: handle this some day */ - assert(vp->data->start >= vp->data_start_min); - - upload_data = TRUE; - if (vp->data_start != vp->data->start) - upload_code = TRUE; - } - - /* If exec or data segments moved we need to patch the program to - * fixup offsets and register IDs. - */ - if (vp->exec_start != vp->exec->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv30_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->has_branch_offset) { - assert(0); - } - } - - vp->exec_start = vp->exec->start; - } - - if (vp->nr_consts && vp->data_start != vp->data->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv30_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->const_index >= 0) { - vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK; - vpi->data[1] |= - (vpi->const_index + vp->data->start) << - NV30_VP_INST_CONST_SRC_SHIFT; - - } - } - - vp->data_start = vp->data->start; - } - - /* Update + Upload constant values */ - if (vp->nr_consts) { - float *map = NULL; - - if (constbuf) { - map = pipe_buffer_map(pscreen, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); - } - - for (i = 0; i < vp->nr_consts; i++) { - struct nv30_vertex_program_data *vpd = &vp->consts[i]; - - if (vpd->index >= 0) { - if (!upload_data && - !memcmp(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float))) - continue; - memcpy(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float)); - } - - BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5); - OUT_RING (chan, i + vp->data->start); - OUT_RINGp (chan, (uint32_t *)vpd->value, 4); - } - - if (constbuf) - pipe_buffer_unmap(pscreen, constbuf); - } - - /* Upload vtxprog */ - if (upload_code) { -#if 0 - for (i = 0; i < vp->nr_insns; i++) { - NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n", - i, vp->insns[i].data[0], vp->insns[i].data[1], - vp->insns[i].data[2], vp->insns[i].data[3]); - } -#endif - BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1); - OUT_RING (chan, vp->exec->start); - for (i = 0; i < vp->nr_insns; i++) { - BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_INST(0), 4); - OUT_RINGp (chan, vp->insns[i].data, 4); - } - } - - if (vp->so != nv30->state.hw[NV30_STATE_VERTPROG]) { - so_ref(vp->so, &nv30->state.hw[NV30_STATE_VERTPROG]); - return TRUE; - } - - return FALSE; -} - -void -nv30_vertprog_destroy(struct nv30_context *nv30, struct nv30_vertex_program *vp) -{ - vp->translated = FALSE; - - if (vp->nr_insns) { - FREE(vp->insns); - vp->insns = NULL; - vp->nr_insns = 0; - } - - if (vp->nr_consts) { - FREE(vp->consts); - vp->consts = NULL; - vp->nr_consts = 0; - } - - nouveau_resource_free(&vp->exec); - vp->exec_start = 0; - nouveau_resource_free(&vp->data); - vp->data_start = 0; - vp->data_start_min = 0; - - vp->ir = vp->or = 0; - so_ref(NULL, &vp->so); -} - -struct nv30_state_entry nv30_state_vertprog = { - .validate = nv30_vertprog_validate, - .dirty = { - .pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/, - .hw = NV30_STATE_VERTPROG, - } -}; diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile deleted file mode 100644 index 0ecae2b4913..00000000000 --- a/src/gallium/drivers/nv40/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -LIBNAME = nv40 - -C_SOURCES = \ - nv40_clear.c \ - nv40_context.c \ - nv40_draw.c \ - nv40_fragprog.c \ - nv40_fragtex.c \ - nv40_miptree.c \ - nv40_query.c \ - nv40_screen.c \ - nv40_state.c \ - nv40_state_blend.c \ - nv40_state_emit.c \ - nv40_state_fb.c \ - nv40_state_rasterizer.c \ - nv40_state_scissor.c \ - nv40_state_stipple.c \ - nv40_state_viewport.c \ - nv40_state_zsa.c \ - nv40_surface.c \ - nv40_transfer.c \ - nv40_vbo.c \ - nv40_vertprog.c - -include ../../Makefile.template diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c deleted file mode 100644 index 65dc73e88b3..00000000000 --- a/src/gallium/drivers/nv40/nv40_context.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "draw/draw_context.h" -#include "pipe/p_defines.h" - -#include "nv40_context.h" -#include "nv40_screen.h" - -static void -nv40_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - if (flags & PIPE_FLUSH_TEXTURE_CACHE) { - BEGIN_RING(chan, curie, 0x1fd8, 1); - OUT_RING (chan, 2); - BEGIN_RING(chan, curie, 0x1fd8, 1); - OUT_RING (chan, 1); - } - - FIRE_RING(chan); - if (fence) - *fence = NULL; -} - -static void -nv40_destroy(struct pipe_context *pipe) -{ - struct nv40_context *nv40 = nv40_context(pipe); - unsigned i; - - for (i = 0; i < NV40_STATE_MAX; i++) { - if (nv40->state.hw[i]) - so_ref(NULL, &nv40->state.hw[i]); - } - - if (nv40->draw) - draw_destroy(nv40->draw); - FREE(nv40); -} - -struct pipe_context * -nv40_create(struct pipe_screen *pscreen, void *priv) -{ - struct nv40_screen *screen = nv40_screen(pscreen); - struct pipe_winsys *ws = pscreen->winsys; - struct nv40_context *nv40; - struct nouveau_winsys *nvws = screen->nvws; - - nv40 = CALLOC(1, sizeof(struct nv40_context)); - if (!nv40) - return NULL; - nv40->screen = screen; - - nv40->nvws = nvws; - - nv40->pipe.winsys = ws; - nv40->pipe.priv = priv; - nv40->pipe.screen = pscreen; - nv40->pipe.destroy = nv40_destroy; - nv40->pipe.draw_arrays = nv40_draw_arrays; - nv40->pipe.draw_elements = nv40_draw_elements; - nv40->pipe.clear = nv40_clear; - nv40->pipe.flush = nv40_flush; - - nv40->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv40->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - - screen->base.channel->user_private = nv40; - screen->base.channel->flush_notify = nv40_state_flush_notify; - - nv40_init_query_functions(nv40); - nv40_init_surface_functions(nv40); - nv40_init_state_functions(nv40); - - /* Create, configure, and install fallback swtnl path */ - nv40->draw = draw_create(); - draw_wide_point_threshold(nv40->draw, 9999999.0); - draw_wide_line_threshold(nv40->draw, 9999999.0); - draw_enable_line_stipple(nv40->draw, FALSE); - draw_enable_point_sprites(nv40->draw, FALSE); - draw_set_rasterize_stage(nv40->draw, nv40_draw_render_stage(nv40)); - - return &nv40->pipe; -} diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h deleted file mode 100644 index 97fb6a2ef94..00000000000 --- a/src/gallium/drivers/nv40/nv40_context.h +++ /dev/null @@ -1,239 +0,0 @@ -#ifndef __NV40_CONTEXT_H__ -#define __NV40_CONTEXT_H__ - -#include <stdio.h> - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_inlines.h" - -#include "draw/draw_vertex.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_gldefs.h" -#include "nouveau/nouveau_context.h" -#include "nouveau/nouveau_stateobj.h" - -#include "nv40_state.h" - -#define NOUVEAU_ERR(fmt, args...) \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); -#define NOUVEAU_MSG(fmt, args...) \ - fprintf(stderr, "nouveau: "fmt, ##args); - -enum nv40_state_index { - NV40_STATE_FB = 0, - NV40_STATE_VIEWPORT = 1, - NV40_STATE_BLEND = 2, - NV40_STATE_RAST = 3, - NV40_STATE_ZSA = 4, - NV40_STATE_BCOL = 5, - NV40_STATE_CLIP = 6, - NV40_STATE_SCISSOR = 7, - NV40_STATE_STIPPLE = 8, - NV40_STATE_FRAGPROG = 9, - NV40_STATE_VERTPROG = 10, - NV40_STATE_FRAGTEX0 = 11, - NV40_STATE_FRAGTEX1 = 12, - NV40_STATE_FRAGTEX2 = 13, - NV40_STATE_FRAGTEX3 = 14, - NV40_STATE_FRAGTEX4 = 15, - NV40_STATE_FRAGTEX5 = 16, - NV40_STATE_FRAGTEX6 = 17, - NV40_STATE_FRAGTEX7 = 18, - NV40_STATE_FRAGTEX8 = 19, - NV40_STATE_FRAGTEX9 = 20, - NV40_STATE_FRAGTEX10 = 21, - NV40_STATE_FRAGTEX11 = 22, - NV40_STATE_FRAGTEX12 = 23, - NV40_STATE_FRAGTEX13 = 24, - NV40_STATE_FRAGTEX14 = 25, - NV40_STATE_FRAGTEX15 = 26, - NV40_STATE_VERTTEX0 = 27, - NV40_STATE_VERTTEX1 = 28, - NV40_STATE_VERTTEX2 = 29, - NV40_STATE_VERTTEX3 = 30, - NV40_STATE_VTXBUF = 31, - NV40_STATE_VTXFMT = 32, - NV40_STATE_VTXATTR = 33, - NV40_STATE_SR = 34, - NV40_STATE_MAX = 35 -}; - -#include "nv40_screen.h" - -#define NV40_NEW_BLEND (1 << 0) -#define NV40_NEW_RAST (1 << 1) -#define NV40_NEW_ZSA (1 << 2) -#define NV40_NEW_SAMPLER (1 << 3) -#define NV40_NEW_FB (1 << 4) -#define NV40_NEW_STIPPLE (1 << 5) -#define NV40_NEW_SCISSOR (1 << 6) -#define NV40_NEW_VIEWPORT (1 << 7) -#define NV40_NEW_BCOL (1 << 8) -#define NV40_NEW_VERTPROG (1 << 9) -#define NV40_NEW_FRAGPROG (1 << 10) -#define NV40_NEW_ARRAYS (1 << 11) -#define NV40_NEW_UCP (1 << 12) -#define NV40_NEW_SR (1 << 13) - -struct nv40_rasterizer_state { - struct pipe_rasterizer_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv40_zsa_state { - struct pipe_depth_stencil_alpha_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv40_blend_state { - struct pipe_blend_state pipe; - struct nouveau_stateobj *so; -}; - - -struct nv40_state { - unsigned scissor_enabled; - unsigned stipple_enabled; - unsigned fp_samplers; - - uint64_t dirty; - struct nouveau_stateobj *hw[NV40_STATE_MAX]; -}; - -struct nv40_context { - struct pipe_context pipe; - - struct nouveau_winsys *nvws; - struct nv40_screen *screen; - - struct draw_context *draw; - - /* HW state derived from pipe states */ - struct nv40_state state; - struct { - struct nv40_vertex_program *vertprog; - - unsigned nr_attribs; - unsigned hw[PIPE_MAX_SHADER_INPUTS]; - unsigned draw[PIPE_MAX_SHADER_INPUTS]; - unsigned emit[PIPE_MAX_SHADER_INPUTS]; - } swtnl; - - enum { - HW, SWTNL, SWRAST - } render_mode; - unsigned fallback_swtnl; - unsigned fallback_swrast; - - /* Context state */ - unsigned dirty, draw_dirty; - struct pipe_scissor_state scissor; - unsigned stipple[32]; - struct pipe_clip_state clip; - struct nv40_vertex_program *vertprog; - struct nv40_fragment_program *fragprog; - struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; - unsigned constbuf_nr[PIPE_SHADER_TYPES]; - struct nv40_rasterizer_state *rasterizer; - struct nv40_zsa_state *zsa; - struct nv40_blend_state *blend; - struct pipe_blend_color blend_colour; - struct pipe_stencil_ref stencil_ref; - struct pipe_viewport_state viewport; - struct pipe_framebuffer_state framebuffer; - struct pipe_buffer *idxbuf; - unsigned idxbuf_format; - struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; - struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; - unsigned nr_samplers; - unsigned nr_textures; - unsigned dirty_samplers; - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - unsigned vtxbuf_nr; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; - unsigned vtxelt_nr; -}; - -static INLINE struct nv40_context * -nv40_context(struct pipe_context *pipe) -{ - return (struct nv40_context *)pipe; -} - -struct nv40_state_entry { - boolean (*validate)(struct nv40_context *nv40); - struct { - unsigned pipe; - unsigned hw; - } dirty; -}; - -extern void nv40_init_state_functions(struct nv40_context *nv40); -extern void nv40_init_surface_functions(struct nv40_context *nv40); -extern void nv40_init_query_functions(struct nv40_context *nv40); - -extern void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen); - -/* nv40_draw.c */ -extern struct draw_stage *nv40_draw_render_stage(struct nv40_context *nv40); -extern void nv40_draw_elements_swtnl(struct pipe_context *pipe, - struct pipe_buffer *idxbuf, - unsigned ib_size, unsigned mode, - unsigned start, unsigned count); - -/* nv40_vertprog.c */ -extern void nv40_vertprog_destroy(struct nv40_context *, - struct nv40_vertex_program *); - -/* nv40_fragprog.c */ -extern void nv40_fragprog_destroy(struct nv40_context *, - struct nv40_fragment_program *); - -/* nv40_fragtex.c */ -extern void nv40_fragtex_bind(struct nv40_context *); - -/* nv40_state.c and friends */ -extern boolean nv40_state_validate(struct nv40_context *nv40); -extern boolean nv40_state_validate_swtnl(struct nv40_context *nv40); -extern void nv40_state_emit(struct nv40_context *nv40); -extern void nv40_state_flush_notify(struct nouveau_channel *chan); -extern struct nv40_state_entry nv40_state_rasterizer; -extern struct nv40_state_entry nv40_state_scissor; -extern struct nv40_state_entry nv40_state_stipple; -extern struct nv40_state_entry nv40_state_fragprog; -extern struct nv40_state_entry nv40_state_vertprog; -extern struct nv40_state_entry nv40_state_blend; -extern struct nv40_state_entry nv40_state_blend_colour; -extern struct nv40_state_entry nv40_state_zsa; -extern struct nv40_state_entry nv40_state_viewport; -extern struct nv40_state_entry nv40_state_framebuffer; -extern struct nv40_state_entry nv40_state_fragtex; -extern struct nv40_state_entry nv40_state_vbo; -extern struct nv40_state_entry nv40_state_vtxfmt; -extern struct nv40_state_entry nv40_state_sr; - -/* nv40_vbo.c */ -extern void nv40_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv40_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, - unsigned count); - -/* nv40_clear.c */ -extern void nv40_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil); - -/* nv40_context.c */ -struct pipe_context * -nv40_create(struct pipe_screen *pscreen, void *priv); - -#endif diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c deleted file mode 100644 index 48bd84d16c5..00000000000 --- a/src/gallium/drivers/nv40/nv40_draw.c +++ /dev/null @@ -1,360 +0,0 @@ -#include "pipe/p_shader_tokens.h" -#include "util/u_inlines.h" - -#include "util/u_pack_color.h" - -#include "draw/draw_context.h" -#include "draw/draw_vertex.h" -#include "draw/draw_pipe.h" - -#include "nv40_context.h" -#define NV40_SHADER_NO_FUCKEDNESS -#include "nv40_shader.h" - -/* Simple, but crappy, swtnl path, hopefully we wont need to hit this very - * often at all. Uses "quadro style" vertex submission + a fixed vertex - * layout to avoid the need to generate a vertex program or vtxfmt. - */ - -struct nv40_render_stage { - struct draw_stage stage; - struct nv40_context *nv40; - unsigned prim; -}; - -static INLINE struct nv40_render_stage * -nv40_render_stage(struct draw_stage *stage) -{ - return (struct nv40_render_stage *)stage; -} - -static INLINE void -nv40_render_vertex(struct nv40_context *nv40, const struct vertex_header *v) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned i; - - for (i = 0; i < nv40->swtnl.nr_attribs; i++) { - unsigned idx = nv40->swtnl.draw[i]; - unsigned hw = nv40->swtnl.hw[i]; - - switch (nv40->swtnl.emit[i]) { - case EMIT_OMIT: - break; - case EMIT_1F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_1F(hw), 1); - OUT_RING (chan, fui(v->data[idx][0])); - break; - case EMIT_2F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_2F_X(hw), 2); - OUT_RING (chan, fui(v->data[idx][0])); - OUT_RING (chan, fui(v->data[idx][1])); - break; - case EMIT_3F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_3F_X(hw), 3); - OUT_RING (chan, fui(v->data[idx][0])); - OUT_RING (chan, fui(v->data[idx][1])); - OUT_RING (chan, fui(v->data[idx][2])); - break; - case EMIT_4F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_4F_X(hw), 4); - OUT_RING (chan, fui(v->data[idx][0])); - OUT_RING (chan, fui(v->data[idx][1])); - OUT_RING (chan, fui(v->data[idx][2])); - OUT_RING (chan, fui(v->data[idx][3])); - break; - case EMIT_4UB: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_4UB(hw), 1); - OUT_RING (chan, pack_ub4(float_to_ubyte(v->data[idx][0]), - float_to_ubyte(v->data[idx][1]), - float_to_ubyte(v->data[idx][2]), - float_to_ubyte(v->data[idx][3]))); - break; - default: - assert(0); - break; - } - } -} - -static INLINE void -nv40_render_prim(struct draw_stage *stage, struct prim_header *prim, - unsigned mode, unsigned count) -{ - struct nv40_render_stage *rs = nv40_render_stage(stage); - struct nv40_context *nv40 = rs->nv40; - - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned i; - - /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */ - if (AVAIL_RING(chan) < ((count * 20) + 6)) { - if (rs->prim != NV40TCL_BEGIN_END_STOP) { - NOUVEAU_ERR("AIII, missed flush\n"); - assert(0); - } - FIRE_RING(chan); - nv40_state_emit(nv40); - } - - /* Switch primitive modes if necessary */ - if (rs->prim != mode) { - if (rs->prim != NV40TCL_BEGIN_END_STOP) { - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, NV40TCL_BEGIN_END_STOP); - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, mode); - rs->prim = mode; - } - - /* Emit vertex data */ - for (i = 0; i < count; i++) - nv40_render_vertex(nv40, prim->v[i]); - - /* If it's likely we'll need to empty the push buffer soon, finish - * off the primitive now. - */ - if (AVAIL_RING(chan) < ((count * 20) + 6)) { - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, NV40TCL_BEGIN_END_STOP); - rs->prim = NV40TCL_BEGIN_END_STOP; - } -} - -static void -nv40_render_point(struct draw_stage *draw, struct prim_header *prim) -{ - nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_POINTS, 1); -} - -static void -nv40_render_line(struct draw_stage *draw, struct prim_header *prim) -{ - nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_LINES, 2); -} - -static void -nv40_render_tri(struct draw_stage *draw, struct prim_header *prim) -{ - nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_TRIANGLES, 3); -} - -static void -nv40_render_flush(struct draw_stage *draw, unsigned flags) -{ - struct nv40_render_stage *rs = nv40_render_stage(draw); - struct nv40_context *nv40 = rs->nv40; - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - if (rs->prim != NV40TCL_BEGIN_END_STOP) { - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, NV40TCL_BEGIN_END_STOP); - rs->prim = NV40TCL_BEGIN_END_STOP; - } -} - -static void -nv40_render_reset_stipple_counter(struct draw_stage *draw) -{ -} - -static void -nv40_render_destroy(struct draw_stage *draw) -{ - FREE(draw); -} - -static INLINE void -emit_mov(struct nv40_vertex_program *vp, - unsigned dst, unsigned src, unsigned vor, unsigned mask) -{ - struct nv40_vertex_program_exec *inst; - - vp->insns = realloc(vp->insns, - sizeof(struct nv40_vertex_program_exec) * - ++vp->nr_insns); - inst = &vp->insns[vp->nr_insns - 1]; - - inst->data[0] = 0x401f9c6c; - inst->data[1] = 0x0040000d | (src << 8); - inst->data[2] = 0x8106c083; - inst->data[3] = 0x6041ff80 | (dst << 2) | (mask << 13); - inst->const_index = -1; - inst->has_branch_offset = FALSE; - - vp->ir |= (1 << src); - if (vor != ~0) - vp->or |= (1 << vor); -} - -static struct nv40_vertex_program * -create_drawvp(struct nv40_context *nv40) -{ - struct nv40_vertex_program *vp = CALLOC_STRUCT(nv40_vertex_program); - unsigned i; - - emit_mov(vp, NV40_VP_INST_DEST_POS, 0, ~0, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_COL0, 3, 0, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_COL1, 4, 1, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_BFC0, 3, 2, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_BFC1, 4, 3, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_FOGC, 5, 4, 0x8); - for (i = 0; i < 8; i++) - emit_mov(vp, NV40_VP_INST_DEST_TC(i), 8 + i, 14 + i, 0xf); - - vp->insns[vp->nr_insns - 1].data[3] |= 1; - vp->translated = TRUE; - return vp; -} - -struct draw_stage * -nv40_draw_render_stage(struct nv40_context *nv40) -{ - struct nv40_render_stage *render = CALLOC_STRUCT(nv40_render_stage); - - if (!nv40->swtnl.vertprog) - nv40->swtnl.vertprog = create_drawvp(nv40); - - render->nv40 = nv40; - render->stage.draw = nv40->draw; - render->stage.point = nv40_render_point; - render->stage.line = nv40_render_line; - render->stage.tri = nv40_render_tri; - render->stage.flush = nv40_render_flush; - render->stage.reset_stipple_counter = nv40_render_reset_stipple_counter; - render->stage.destroy = nv40_render_destroy; - - return &render->stage; -} - -void -nv40_draw_elements_swtnl(struct pipe_context *pipe, - struct pipe_buffer *idxbuf, unsigned idxbuf_size, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct pipe_screen *pscreen = pipe->screen; - unsigned i; - void *map; - - if (!nv40_state_validate_swtnl(nv40)) - return; - nv40->state.dirty &= ~(1ULL << NV40_STATE_VTXBUF); - nv40_state_emit(nv40); - - for (i = 0; i < nv40->vtxbuf_nr; i++) { - map = pipe_buffer_map(pscreen, nv40->vtxbuf[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_vertex_buffer(nv40->draw, i, map); - } - - if (idxbuf) { - map = pipe_buffer_map(pscreen, idxbuf, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(nv40->draw, idxbuf_size, map); - } else { - draw_set_mapped_element_buffer(nv40->draw, 0, NULL); - } - - if (nv40->constbuf[PIPE_SHADER_VERTEX]) { - const unsigned nr = nv40->constbuf_nr[PIPE_SHADER_VERTEX]; - - map = pipe_buffer_map(pscreen, - nv40->constbuf[PIPE_SHADER_VERTEX], - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_constant_buffer(nv40->draw, PIPE_SHADER_VERTEX, 0, - map, nr); - } - - draw_arrays(nv40->draw, mode, start, count); - - for (i = 0; i < nv40->vtxbuf_nr; i++) - pipe_buffer_unmap(pscreen, nv40->vtxbuf[i].buffer); - - if (idxbuf) - pipe_buffer_unmap(pscreen, idxbuf); - - if (nv40->constbuf[PIPE_SHADER_VERTEX]) - pipe_buffer_unmap(pscreen, nv40->constbuf[PIPE_SHADER_VERTEX]); - - draw_flush(nv40->draw); - pipe->flush(pipe, 0, NULL); -} - -static INLINE void -emit_attrib(struct nv40_context *nv40, unsigned hw, unsigned emit, - unsigned semantic, unsigned index) -{ - unsigned draw_out = draw_find_shader_output(nv40->draw, semantic, index); - unsigned a = nv40->swtnl.nr_attribs++; - - nv40->swtnl.hw[a] = hw; - nv40->swtnl.emit[a] = emit; - nv40->swtnl.draw[a] = draw_out; -} - -static boolean -nv40_state_vtxfmt_validate(struct nv40_context *nv40) -{ - struct nv40_fragment_program *fp = nv40->fragprog; - unsigned colour = 0, texcoords = 0, fog = 0, i; - - /* Determine needed fragprog inputs */ - for (i = 0; i < fp->info.num_inputs; i++) { - switch (fp->info.input_semantic_name[i]) { - case TGSI_SEMANTIC_POSITION: - break; - case TGSI_SEMANTIC_COLOR: - colour |= (1 << fp->info.input_semantic_index[i]); - break; - case TGSI_SEMANTIC_GENERIC: - texcoords |= (1 << fp->info.input_semantic_index[i]); - break; - case TGSI_SEMANTIC_FOG: - fog = 1; - break; - default: - assert(0); - } - } - - nv40->swtnl.nr_attribs = 0; - - /* Map draw vtxprog output to hw attribute IDs */ - for (i = 0; i < 2; i++) { - if (!(colour & (1 << i))) - continue; - emit_attrib(nv40, 3 + i, EMIT_4UB, TGSI_SEMANTIC_COLOR, i); - } - - for (i = 0; i < 8; i++) { - if (!(texcoords & (1 << i))) - continue; - emit_attrib(nv40, 8 + i, EMIT_4F, TGSI_SEMANTIC_GENERIC, i); - } - - if (fog) { - emit_attrib(nv40, 5, EMIT_1F, TGSI_SEMANTIC_FOG, 0); - } - - emit_attrib(nv40, 0, EMIT_3F, TGSI_SEMANTIC_POSITION, 0); - - return FALSE; -} - -struct nv40_state_entry nv40_state_vtxfmt = { - .validate = nv40_state_vtxfmt_validate, - .dirty = { - .pipe = NV40_NEW_ARRAYS | NV40_NEW_FRAGPROG, - .hw = 0 - } -}; - diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c deleted file mode 100644 index 8ed4a67dd03..00000000000 --- a/src/gallium/drivers/nv40/nv40_query.c +++ /dev/null @@ -1,127 +0,0 @@ -#include "pipe/p_context.h" - -#include "nv40_context.h" - -struct nv40_query { - struct nouveau_resource *object; - unsigned type; - boolean ready; - uint64_t result; -}; - -static INLINE struct nv40_query * -nv40_query(struct pipe_query *pipe) -{ - return (struct nv40_query *)pipe; -} - -static struct pipe_query * -nv40_query_create(struct pipe_context *pipe, unsigned query_type) -{ - struct nv40_query *q; - - q = CALLOC(1, sizeof(struct nv40_query)); - q->type = query_type; - - return (struct pipe_query *)q; -} - -static void -nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv40_query *q = nv40_query(pq); - - if (q->object) - nouveau_resource_free(&q->object); - FREE(q); -} - -static void -nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_query *q = nv40_query(pq); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - /* Happens when end_query() is called, then another begin_query() - * without querying the result in-between. For now we'll wait for - * the existing query to notify completion, but it could be better. - */ - if (q->object) { - uint64_t tmp; - pipe->get_query_result(pipe, pq, 1, &tmp); - } - - if (nouveau_resource_alloc(nv40->screen->query_heap, 1, NULL, &q->object)) - assert(0); - nouveau_notifier_reset(nv40->screen->query, q->object->start); - - BEGIN_RING(chan, curie, NV40TCL_QUERY_RESET, 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, curie, NV40TCL_QUERY_UNK17CC, 1); - OUT_RING (chan, 1); - - q->ready = FALSE; -} - -static void -nv40_query_end(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_query *q = nv40_query(pq); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - BEGIN_RING(chan, curie, NV40TCL_QUERY_GET, 1); - OUT_RING (chan, (0x01 << NV40TCL_QUERY_GET_UNK24_SHIFT) | - ((q->object->start * 32) << NV40TCL_QUERY_GET_OFFSET_SHIFT)); - FIRE_RING(chan); -} - -static boolean -nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq, - boolean wait, uint64_t *result) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_query *q = nv40_query(pq); - - assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - if (!q->ready) { - unsigned status; - - status = nouveau_notifier_status(nv40->screen->query, - q->object->start); - if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { - if (wait == FALSE) - return FALSE; - nouveau_notifier_wait_status(nv40->screen->query, - q->object->start, - NV_NOTIFY_STATE_STATUS_COMPLETED, - 0); - } - - q->result = nouveau_notifier_return_val(nv40->screen->query, - q->object->start); - q->ready = TRUE; - nouveau_resource_free(&q->object); - } - - *result = q->result; - return TRUE; -} - -void -nv40_init_query_functions(struct nv40_context *nv40) -{ - nv40->pipe.create_query = nv40_query_create; - nv40->pipe.destroy_query = nv40_query_destroy; - nv40->pipe.begin_query = nv40_query_begin; - nv40->pipe.end_query = nv40_query_end; - nv40->pipe.get_query_result = nv40_query_result; -} diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c deleted file mode 100644 index b216c5e38c9..00000000000 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ /dev/null @@ -1,320 +0,0 @@ -#include "pipe/p_screen.h" - -#include "nv40_context.h" -#include "nv40_screen.h" - -#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf -#define NV4X_GRCLASS4497_CHIPSETS 0x00005450 -#define NV6X_GRCLASS4497_CHIPSETS 0x00000088 - -static int -nv40_screen_get_param(struct pipe_screen *pscreen, int param) -{ - struct nv40_screen *screen = nv40_screen(pscreen); - - switch (param) { - case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 16; - case PIPE_CAP_NPOT_TEXTURES: - return 1; - case PIPE_CAP_TWO_SIDED_STENCIL: - return 1; - case PIPE_CAP_GLSL: - return 0; - case PIPE_CAP_ANISOTROPIC_FILTER: - return 1; - case PIPE_CAP_POINT_SPRITE: - return 1; - case PIPE_CAP_MAX_RENDER_TARGETS: - return 4; - case PIPE_CAP_OCCLUSION_QUERY: - return 1; - case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 1; - case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 13; - case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 10; - case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 13; - case PIPE_CAP_TEXTURE_MIRROR_CLAMP: - case PIPE_CAP_TEXTURE_MIRROR_REPEAT: - return 1; - case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; /* We have 4 - but unsupported currently */ - case PIPE_CAP_TGSI_CONT_SUPPORTED: - return 0; - case PIPE_CAP_BLEND_EQUATION_SEPARATE: - return 1; - case NOUVEAU_CAP_HW_VTXBUF: - return 1; - case NOUVEAU_CAP_HW_IDXBUF: - if (screen->curie->grclass == NV40TCL) - return 1; - return 0; - case PIPE_CAP_INDEP_BLEND_ENABLE: - return 0; - case PIPE_CAP_INDEP_BLEND_FUNC: - return 0; - case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: - return 1; - case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: - return 0; - case PIPE_CAP_MAX_COMBINED_SAMPLERS: - return 16; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0; - } -} - -static float -nv40_screen_get_paramf(struct pipe_screen *pscreen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_LINE_WIDTH: - case PIPE_CAP_MAX_LINE_WIDTH_AA: - return 10.0; - case PIPE_CAP_MAX_POINT_WIDTH: - case PIPE_CAP_MAX_POINT_WIDTH_AA: - return 64.0; - case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 16.0; - case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: - return 16.0; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0.0; - } -} - -static boolean -nv40_screen_surface_format_supported(struct pipe_screen *pscreen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned tex_usage, unsigned geom_flags) -{ - if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { - switch (format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - return TRUE; - default: - break; - } - } else - if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { - switch (format) { - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - case PIPE_FORMAT_Z16_UNORM: - return TRUE; - default: - break; - } - } else { - switch (format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B5G5R5A1_UNORM: - case PIPE_FORMAT_B4G4R4A4_UNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - case PIPE_FORMAT_R16_SNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_I8_UNORM: - case PIPE_FORMAT_L8A8_UNORM: - case PIPE_FORMAT_Z16_UNORM: - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_DXT1_RGB: - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: - return TRUE; - default: - break; - } - } - - return FALSE; -} - -static struct pipe_buffer * -nv40_surface_buffer(struct pipe_surface *surf) -{ - struct nv40_miptree *mt = (struct nv40_miptree *)surf->texture; - - return mt->buffer; -} - -static void -nv40_screen_destroy(struct pipe_screen *pscreen) -{ - struct nv40_screen *screen = nv40_screen(pscreen); - unsigned i; - - for (i = 0; i < NV40_STATE_MAX; i++) { - if (screen->state[i]) - so_ref(NULL, &screen->state[i]); - } - - nouveau_resource_destroy(&screen->vp_exec_heap); - nouveau_resource_destroy(&screen->vp_data_heap); - nouveau_resource_destroy(&screen->query_heap); - nouveau_notifier_free(&screen->query); - nouveau_notifier_free(&screen->sync); - nouveau_grobj_free(&screen->curie); - nv04_surface_2d_takedown(&screen->eng2d); - - nouveau_screen_fini(&screen->base); - - FREE(pscreen); -} - -struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) -{ - struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); - struct nouveau_channel *chan; - struct pipe_screen *pscreen; - struct nouveau_stateobj *so; - unsigned curie_class = 0; - int ret; - - if (!screen) - return NULL; - pscreen = &screen->base.base; - - ret = nouveau_screen_init(&screen->base, dev); - if (ret) { - nv40_screen_destroy(pscreen); - return NULL; - } - chan = screen->base.channel; - - pscreen->winsys = ws; - pscreen->destroy = nv40_screen_destroy; - pscreen->get_param = nv40_screen_get_param; - pscreen->get_paramf = nv40_screen_get_paramf; - pscreen->is_format_supported = nv40_screen_surface_format_supported; - pscreen->context_create = nv40_create; - - nv40_screen_init_miptree_functions(pscreen); - nv40_screen_init_transfer_functions(pscreen); - - /* 3D object */ - switch (dev->chipset & 0xf0) { - case 0x40: - if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f))) - curie_class = NV40TCL; - else - if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) - curie_class = NV44TCL; - break; - case 0x60: - if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) - curie_class = NV44TCL; - break; - } - - if (!curie_class) { - NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", dev->chipset); - return NULL; - } - - ret = nouveau_grobj_alloc(chan, 0xbeef3097, curie_class, &screen->curie); - if (ret) { - NOUVEAU_ERR("Error creating 3D object: %d\n", ret); - return FALSE; - } - - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(&screen->base); - screen->eng2d->buf = nv40_surface_buffer; - - /* Notifier for sync purposes */ - ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); - if (ret) { - NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv40_screen_destroy(pscreen); - return NULL; - } - - /* Query objects */ - ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query); - if (ret) { - NOUVEAU_ERR("Error initialising query objects: %d\n", ret); - nv40_screen_destroy(pscreen); - return NULL; - } - - nouveau_resource_init(&screen->query_heap, 0, 32); - if (ret) { - NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); - nv40_screen_destroy(pscreen); - return NULL; - } - - /* Vtxprog resources */ - if (nouveau_resource_init(&screen->vp_exec_heap, 0, 512) || - nouveau_resource_init(&screen->vp_data_heap, 0, 256)) { - nv40_screen_destroy(pscreen); - return NULL; - } - - /* Static curie initialisation */ - so = so_new(16, 25, 0); - so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1); - so_data (so, screen->sync->handle); - so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->gart->handle); - so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1); - so_data (so, chan->vram->handle); - so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->gart->handle); - so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2); - so_data (so, 0); - so_data (so, screen->query->handle); - so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - - so_method(so, screen->curie, 0x1ea4, 3); - so_data (so, 0x00000010); - so_data (so, 0x01000100); - so_data (so, 0xff800006); - - /* vtxprog output routing */ - so_method(so, screen->curie, 0x1fc4, 1); - so_data (so, 0x06144321); - so_method(so, screen->curie, 0x1fc8, 2); - so_data (so, 0xedcba987); - so_data (so, 0x00000021); - so_method(so, screen->curie, 0x1fd0, 1); - so_data (so, 0x00171615); - so_method(so, screen->curie, 0x1fd4, 1); - so_data (so, 0x001b1a19); - - so_method(so, screen->curie, 0x1ef8, 1); - so_data (so, 0x0020ffff); - so_method(so, screen->curie, 0x1d64, 1); - so_data (so, 0x00d30000); - so_method(so, screen->curie, 0x1e94, 1); - so_data (so, 0x00000001); - - so_emit(chan, so); - so_ref(NULL, &so); - nouveau_pushbuf_flush(chan, 0); - - return pscreen; -} - diff --git a/src/gallium/drivers/nv40/nv40_shader.h b/src/gallium/drivers/nv40/nv40_shader.h deleted file mode 100644 index 854dccf5486..00000000000 --- a/src/gallium/drivers/nv40/nv40_shader.h +++ /dev/null @@ -1,556 +0,0 @@ -#ifndef __NV40_SHADER_H__ -#define __NV40_SHADER_H__ - -/* Vertex programs instruction set - * - * The NV40 instruction set is very similar to NV30. Most fields are in - * a slightly different position in the instruction however. - * - * Merged instructions - * In some cases it is possible to put two instructions into one opcode - * slot. The rules for when this is OK is not entirely clear to me yet. - * - * There are separate writemasks and dest temp register fields for each - * grouping of instructions. There is however only one field with the - * ID of a result register. Writing to temp/result regs is selected by - * setting VEC_RESULT/SCA_RESULT. - * - * Temporary registers - * The source/dest temp register fields have been extended by 1 bit, to - * give a total of 32 temporary registers. - * - * Relative Addressing - * NV40 can use an address register to index into vertex attribute regs. - * This is done by putting the offset value into INPUT_SRC and setting - * the INDEX_INPUT flag. - * - * Conditional execution (see NV_vertex_program{2,3} for details) - * There is a second condition code register on NV40, it's use is enabled - * by setting the COND_REG_SELECT_1 flag. - * - * Texture lookup - * TODO - */ - -/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */ -#define NV40_VP_INST_VEC_RESULT (1 << 30) -/* uncertain.. */ -#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29) -/* use address reg as index into attribs */ -#define NV40_VP_INST_INDEX_INPUT (1 << 27) -#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25) -#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24) -#define NV40_VP_INST_SRC2_ABS (1 << 23) -#define NV40_VP_INST_SRC1_ABS (1 << 22) -#define NV40_VP_INST_SRC0_ABS (1 << 21) -#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15 -#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15) -#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13) -#define NV40_VP_INST_COND_SHIFT 10 -#define NV40_VP_INST_COND_MASK (0x7 << 10) -# define NV40_VP_INST_COND_FL 0 -# define NV40_VP_INST_COND_LT 1 -# define NV40_VP_INST_COND_EQ 2 -# define NV40_VP_INST_COND_LE 3 -# define NV40_VP_INST_COND_GT 4 -# define NV40_VP_INST_COND_NE 5 -# define NV40_VP_INST_COND_GE 6 -# define NV40_VP_INST_COND_TR 7 -#define NV40_VP_INST_COND_SWZ_X_SHIFT 8 -#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8) -#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6 -#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6) -#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4 -#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4) -#define NV40_VP_INST_COND_SWZ_W_SHIFT 2 -#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2) -#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2 -#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2) -#define NV40_VP_INST_ADDR_SWZ_SHIFT 0 -#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0) -#define NV40_VP_INST0_KNOWN ( \ - NV40_VP_INST_INDEX_INPUT | \ - NV40_VP_INST_COND_REG_SELECT_1 | \ - NV40_VP_INST_ADDR_REG_SELECT_1 | \ - NV40_VP_INST_SRC2_ABS | \ - NV40_VP_INST_SRC1_ABS | \ - NV40_VP_INST_SRC0_ABS | \ - NV40_VP_INST_VEC_DEST_TEMP_MASK | \ - NV40_VP_INST_COND_TEST_ENABLE | \ - NV40_VP_INST_COND_MASK | \ - NV40_VP_INST_COND_SWZ_ALL_MASK | \ - NV40_VP_INST_ADDR_SWZ_MASK) - -/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */ -#define NV40_VP_INST_VEC_OPCODE_SHIFT 22 -#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22) -# define NV40_VP_INST_OP_NOP 0x00 -# define NV40_VP_INST_OP_MOV 0x01 -# define NV40_VP_INST_OP_MUL 0x02 -# define NV40_VP_INST_OP_ADD 0x03 -# define NV40_VP_INST_OP_MAD 0x04 -# define NV40_VP_INST_OP_DP3 0x05 -# define NV40_VP_INST_OP_DPH 0x06 -# define NV40_VP_INST_OP_DP4 0x07 -# define NV40_VP_INST_OP_DST 0x08 -# define NV40_VP_INST_OP_MIN 0x09 -# define NV40_VP_INST_OP_MAX 0x0A -# define NV40_VP_INST_OP_SLT 0x0B -# define NV40_VP_INST_OP_SGE 0x0C -# define NV40_VP_INST_OP_ARL 0x0D -# define NV40_VP_INST_OP_FRC 0x0E -# define NV40_VP_INST_OP_FLR 0x0F -# define NV40_VP_INST_OP_SEQ 0x10 -# define NV40_VP_INST_OP_SFL 0x11 -# define NV40_VP_INST_OP_SGT 0x12 -# define NV40_VP_INST_OP_SLE 0x13 -# define NV40_VP_INST_OP_SNE 0x14 -# define NV40_VP_INST_OP_STR 0x15 -# define NV40_VP_INST_OP_SSG 0x16 -# define NV40_VP_INST_OP_ARR 0x17 -# define NV40_VP_INST_OP_ARA 0x18 -# define NV40_VP_INST_OP_TXL 0x19 -#define NV40_VP_INST_SCA_OPCODE_SHIFT 27 -#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27) -# define NV40_VP_INST_OP_NOP 0x00 -# define NV40_VP_INST_OP_MOV 0x01 -# define NV40_VP_INST_OP_RCP 0x02 -# define NV40_VP_INST_OP_RCC 0x03 -# define NV40_VP_INST_OP_RSQ 0x04 -# define NV40_VP_INST_OP_EXP 0x05 -# define NV40_VP_INST_OP_LOG 0x06 -# define NV40_VP_INST_OP_LIT 0x07 -# define NV40_VP_INST_OP_BRA 0x09 -# define NV40_VP_INST_OP_CAL 0x0B -# define NV40_VP_INST_OP_RET 0x0C -# define NV40_VP_INST_OP_LG2 0x0D -# define NV40_VP_INST_OP_EX2 0x0E -# define NV40_VP_INST_OP_SIN 0x0F -# define NV40_VP_INST_OP_COS 0x10 -# define NV40_VP_INST_OP_PUSHA 0x13 -# define NV40_VP_INST_OP_POPA 0x14 -#define NV40_VP_INST_CONST_SRC_SHIFT 12 -#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12) -#define NV40_VP_INST_INPUT_SRC_SHIFT 8 -#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8) -# define NV40_VP_INST_IN_POS 0 -# define NV40_VP_INST_IN_WEIGHT 1 -# define NV40_VP_INST_IN_NORMAL 2 -# define NV40_VP_INST_IN_COL0 3 -# define NV40_VP_INST_IN_COL1 4 -# define NV40_VP_INST_IN_FOGC 5 -# define NV40_VP_INST_IN_TC0 8 -# define NV40_VP_INST_IN_TC(n) (8+n) -#define NV40_VP_INST_SRC0H_SHIFT 0 -#define NV40_VP_INST_SRC0H_MASK (0xFF << 0) -#define NV40_VP_INST1_KNOWN ( \ - NV40_VP_INST_VEC_OPCODE_MASK | \ - NV40_VP_INST_SCA_OPCODE_MASK | \ - NV40_VP_INST_CONST_SRC_MASK | \ - NV40_VP_INST_INPUT_SRC_MASK | \ - NV40_VP_INST_SRC0H_MASK \ - ) - -/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */ -#define NV40_VP_INST_SRC0L_SHIFT 23 -#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23) -#define NV40_VP_INST_SRC1_SHIFT 6 -#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6) -#define NV40_VP_INST_SRC2H_SHIFT 0 -#define NV40_VP_INST_SRC2H_MASK (0x3F << 0) -#define NV40_VP_INST_IADDRH_SHIFT 0 -#define NV40_VP_INST_IADDRH_MASK (0x1F << 0) - -/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */ -#define NV40_VP_INST_IADDRL_SHIFT 29 -#define NV40_VP_INST_IADDRL_MASK (7 << 29) -#define NV40_VP_INST_SRC2L_SHIFT 21 -#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21) -#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17 -#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17) -# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20) -# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19) -# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18) -# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17) -#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13 -#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13) -# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16) -# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15) -# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14) -# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13) -#define NV40_VP_INST_SCA_RESULT (1 << 12) -#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7 -#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7) -#define NV40_VP_INST_DEST_SHIFT 2 -#define NV40_VP_INST_DEST_MASK (31 << 2) -# define NV40_VP_INST_DEST_POS 0 -# define NV40_VP_INST_DEST_COL0 1 -# define NV40_VP_INST_DEST_COL1 2 -# define NV40_VP_INST_DEST_BFC0 3 -# define NV40_VP_INST_DEST_BFC1 4 -# define NV40_VP_INST_DEST_FOGC 5 -# define NV40_VP_INST_DEST_PSZ 6 -# define NV40_VP_INST_DEST_TC0 7 -# define NV40_VP_INST_DEST_TC(n) (7+n) -# define NV40_VP_INST_DEST_TEMP 0x1F -#define NV40_VP_INST_INDEX_CONST (1 << 1) -#define NV40_VP_INST_LAST (1 << 0) -#define NV40_VP_INST3_KNOWN ( \ - NV40_VP_INST_SRC2L_MASK |\ - NV40_VP_INST_SCA_WRITEMASK_MASK |\ - NV40_VP_INST_VEC_WRITEMASK_MASK |\ - NV40_VP_INST_SCA_DEST_TEMP_MASK |\ - NV40_VP_INST_DEST_MASK |\ - NV40_VP_INST_INDEX_CONST) - -/* Useful to split the source selection regs into their pieces */ -#define NV40_VP_SRC0_HIGH_SHIFT 9 -#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00 -#define NV40_VP_SRC0_LOW_MASK 0x000001FF -#define NV40_VP_SRC2_HIGH_SHIFT 11 -#define NV40_VP_SRC2_HIGH_MASK 0x0001F800 -#define NV40_VP_SRC2_LOW_MASK 0x000007FF - -/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */ -#define NV40_VP_SRC_NEGATE (1 << 16) -#define NV40_VP_SRC_SWZ_X_SHIFT 14 -#define NV40_VP_SRC_SWZ_X_MASK (3 << 14) -#define NV40_VP_SRC_SWZ_Y_SHIFT 12 -#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12) -#define NV40_VP_SRC_SWZ_Z_SHIFT 10 -#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10) -#define NV40_VP_SRC_SWZ_W_SHIFT 8 -#define NV40_VP_SRC_SWZ_W_MASK (3 << 8) -#define NV40_VP_SRC_SWZ_ALL_SHIFT 8 -#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8) -#define NV40_VP_SRC_TEMP_SRC_SHIFT 2 -#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2) -#define NV40_VP_SRC_REG_TYPE_SHIFT 0 -#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0) -# define NV40_VP_SRC_REG_TYPE_UNK0 0 -# define NV40_VP_SRC_REG_TYPE_TEMP 1 -# define NV40_VP_SRC_REG_TYPE_INPUT 2 -# define NV40_VP_SRC_REG_TYPE_CONST 3 - - -/* - * Each fragment program opcode appears to be comprised of 4 32-bit values. - * - * 0 - Opcode, output reg/mask, ATTRIB source - * 1 - Source 0 - * 2 - Source 1 - * 3 - Source 2 - * - * There appears to be no special difference between result regs and temp regs. - * result.color == R0.xyzw - * result.depth == R1.z - * When the fragprog contains instructions to write depth, - * NV30_TCL_PRIMITIVE_3D_UNK1D78=0 otherwise it is set to 1. - * - * Constants are inserted directly after the instruction that uses them. - * - * It appears that it's not possible to use two input registers in one - * instruction as the input sourcing is done in the instruction dword - * and not the source selection dwords. As such instructions such as: - * - * ADD result.color, fragment.color, fragment.texcoord[0]; - * - * must be split into two MOV's and then an ADD (nvidia does this) but - * I'm not sure why it's not just one MOV and then source the second input - * in the ADD instruction.. - * - * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary - * negation requires multiplication with a const. - * - * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO and - * SWIZZLE_ONE. - * - * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as - * SWIZZLE_ZERO is implemented simply by not writing to the relevant components - * of the destination. - * - * Looping - * Loops appear to be fairly expensive on NV40 at least, the proprietary - * driver goes to a lot of effort to avoid using the native looping - * instructions. If the total number of *executed* instructions between - * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop. - * The maximum loop count is 255. - * - * Conditional execution - * TODO - * - * Non-native instructions: - * LIT - * LRP - MAD+MAD - * SUB - ADD, negate second source - * RSQ - LG2 + EX2 - * POW - LG2 + MUL + EX2 - * SCS - COS + SIN - * XPD - * DP2 - MUL + ADD - * NRM - */ - -//== Opcode / Destination selection == -#define NV40_FP_OP_PROGRAM_END (1 << 0) -#define NV40_FP_OP_OUT_REG_SHIFT 1 -#define NV40_FP_OP_OUT_REG_MASK (63 << 1) -/* Needs to be set when writing outputs to get expected result.. */ -#define NV40_FP_OP_OUT_REG_HALF (1 << 7) -#define NV40_FP_OP_COND_WRITE_ENABLE (1 << 8) -#define NV40_FP_OP_OUTMASK_SHIFT 9 -#define NV40_FP_OP_OUTMASK_MASK (0xF << 9) -# define NV40_FP_OP_OUT_X (1 << 9) -# define NV40_FP_OP_OUT_Y (1 <<10) -# define NV40_FP_OP_OUT_Z (1 <<11) -# define NV40_FP_OP_OUT_W (1 <<12) -/* Uncertain about these, especially the input_src values.. it's possible that - * they can be dynamically changed. - */ -#define NV40_FP_OP_INPUT_SRC_SHIFT 13 -#define NV40_FP_OP_INPUT_SRC_MASK (15 << 13) -# define NV40_FP_OP_INPUT_SRC_POSITION 0x0 -# define NV40_FP_OP_INPUT_SRC_COL0 0x1 -# define NV40_FP_OP_INPUT_SRC_COL1 0x2 -# define NV40_FP_OP_INPUT_SRC_FOGC 0x3 -# define NV40_FP_OP_INPUT_SRC_TC0 0x4 -# define NV40_FP_OP_INPUT_SRC_TC(n) (0x4 + n) -# define NV40_FP_OP_INPUT_SRC_FACING 0xE -#define NV40_FP_OP_TEX_UNIT_SHIFT 17 -#define NV40_FP_OP_TEX_UNIT_MASK (0xF << 17) -#define NV40_FP_OP_PRECISION_SHIFT 22 -#define NV40_FP_OP_PRECISION_MASK (3 << 22) -# define NV40_FP_PRECISION_FP32 0 -# define NV40_FP_PRECISION_FP16 1 -# define NV40_FP_PRECISION_FX12 2 -#define NV40_FP_OP_OPCODE_SHIFT 24 -#define NV40_FP_OP_OPCODE_MASK (0x3F << 24) -# define NV40_FP_OP_OPCODE_NOP 0x00 -# define NV40_FP_OP_OPCODE_MOV 0x01 -# define NV40_FP_OP_OPCODE_MUL 0x02 -# define NV40_FP_OP_OPCODE_ADD 0x03 -# define NV40_FP_OP_OPCODE_MAD 0x04 -# define NV40_FP_OP_OPCODE_DP3 0x05 -# define NV40_FP_OP_OPCODE_DP4 0x06 -# define NV40_FP_OP_OPCODE_DST 0x07 -# define NV40_FP_OP_OPCODE_MIN 0x08 -# define NV40_FP_OP_OPCODE_MAX 0x09 -# define NV40_FP_OP_OPCODE_SLT 0x0A -# define NV40_FP_OP_OPCODE_SGE 0x0B -# define NV40_FP_OP_OPCODE_SLE 0x0C -# define NV40_FP_OP_OPCODE_SGT 0x0D -# define NV40_FP_OP_OPCODE_SNE 0x0E -# define NV40_FP_OP_OPCODE_SEQ 0x0F -# define NV40_FP_OP_OPCODE_FRC 0x10 -# define NV40_FP_OP_OPCODE_FLR 0x11 -# define NV40_FP_OP_OPCODE_KIL 0x12 -# define NV40_FP_OP_OPCODE_PK4B 0x13 -# define NV40_FP_OP_OPCODE_UP4B 0x14 -/* DDX/DDY can only write to XY */ -# define NV40_FP_OP_OPCODE_DDX 0x15 -# define NV40_FP_OP_OPCODE_DDY 0x16 -# define NV40_FP_OP_OPCODE_TEX 0x17 -# define NV40_FP_OP_OPCODE_TXP 0x18 -# define NV40_FP_OP_OPCODE_TXD 0x19 -# define NV40_FP_OP_OPCODE_RCP 0x1A -# define NV40_FP_OP_OPCODE_EX2 0x1C -# define NV40_FP_OP_OPCODE_LG2 0x1D -# define NV40_FP_OP_OPCODE_STR 0x20 -# define NV40_FP_OP_OPCODE_SFL 0x21 -# define NV40_FP_OP_OPCODE_COS 0x22 -# define NV40_FP_OP_OPCODE_SIN 0x23 -# define NV40_FP_OP_OPCODE_PK2H 0x24 -# define NV40_FP_OP_OPCODE_UP2H 0x25 -# define NV40_FP_OP_OPCODE_PK4UB 0x27 -# define NV40_FP_OP_OPCODE_UP4UB 0x28 -# define NV40_FP_OP_OPCODE_PK2US 0x29 -# define NV40_FP_OP_OPCODE_UP2US 0x2A -# define NV40_FP_OP_OPCODE_DP2A 0x2E -# define NV40_FP_OP_OPCODE_TXL 0x2F -# define NV40_FP_OP_OPCODE_TXB 0x31 -# define NV40_FP_OP_OPCODE_DIV 0x3A -# define NV40_FP_OP_OPCODE_UNK_LIT 0x3C -/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/ -# define NV40_FP_OP_BRA_OPCODE_BRK 0x0 -# define NV40_FP_OP_BRA_OPCODE_CAL 0x1 -# define NV40_FP_OP_BRA_OPCODE_IF 0x2 -# define NV40_FP_OP_BRA_OPCODE_LOOP 0x3 -# define NV40_FP_OP_BRA_OPCODE_REP 0x4 -# define NV40_FP_OP_BRA_OPCODE_RET 0x5 -#define NV40_FP_OP_OUT_SAT (1 << 31) - -/* high order bits of SRC0 */ -#define NV40_FP_OP_OUT_ABS (1 << 29) -#define NV40_FP_OP_COND_SWZ_W_SHIFT 27 -#define NV40_FP_OP_COND_SWZ_W_MASK (3 << 27) -#define NV40_FP_OP_COND_SWZ_Z_SHIFT 25 -#define NV40_FP_OP_COND_SWZ_Z_MASK (3 << 25) -#define NV40_FP_OP_COND_SWZ_Y_SHIFT 23 -#define NV40_FP_OP_COND_SWZ_Y_MASK (3 << 23) -#define NV40_FP_OP_COND_SWZ_X_SHIFT 21 -#define NV40_FP_OP_COND_SWZ_X_MASK (3 << 21) -#define NV40_FP_OP_COND_SWZ_ALL_SHIFT 21 -#define NV40_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) -#define NV40_FP_OP_COND_SHIFT 18 -#define NV40_FP_OP_COND_MASK (0x07 << 18) -# define NV40_FP_OP_COND_FL 0 -# define NV40_FP_OP_COND_LT 1 -# define NV40_FP_OP_COND_EQ 2 -# define NV40_FP_OP_COND_LE 3 -# define NV40_FP_OP_COND_GT 4 -# define NV40_FP_OP_COND_NE 5 -# define NV40_FP_OP_COND_GE 6 -# define NV40_FP_OP_COND_TR 7 - -/* high order bits of SRC1 */ -#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31) -#define NV40_FP_OP_DST_SCALE_SHIFT 28 -#define NV40_FP_OP_DST_SCALE_MASK (3 << 28) -#define NV40_FP_OP_DST_SCALE_1X 0 -#define NV40_FP_OP_DST_SCALE_2X 1 -#define NV40_FP_OP_DST_SCALE_4X 2 -#define NV40_FP_OP_DST_SCALE_8X 3 -#define NV40_FP_OP_DST_SCALE_INV_2X 5 -#define NV40_FP_OP_DST_SCALE_INV_4X 6 -#define NV40_FP_OP_DST_SCALE_INV_8X 7 - -/* SRC1 LOOP */ -#define NV40_FP_OP_LOOP_INCR_SHIFT 19 -#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19) -#define NV40_FP_OP_LOOP_INDEX_SHIFT 10 -#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10) -#define NV40_FP_OP_LOOP_COUNT_SHIFT 2 -#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2) - -/* SRC1 IF */ -#define NV40_FP_OP_ELSE_ID_SHIFT 2 -#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2) - -/* SRC1 CAL */ -#define NV40_FP_OP_IADDR_SHIFT 2 -#define NV40_FP_OP_IADDR_MASK (0xFF << 2) - -/* SRC1 REP - * I have no idea why there are 3 count values here.. but they - * have always been filled with the same value in my tests so - * far.. - */ -#define NV40_FP_OP_REP_COUNT1_SHIFT 2 -#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2) -#define NV40_FP_OP_REP_COUNT2_SHIFT 10 -#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10) -#define NV40_FP_OP_REP_COUNT3_SHIFT 19 -#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19) - -/* SRC2 REP/IF */ -#define NV40_FP_OP_END_ID_SHIFT 2 -#define NV40_FP_OP_END_ID_MASK (0xFF << 2) - -// SRC2 high-order -#define NV40_FP_OP_INDEX_INPUT (1 << 30) -#define NV40_FP_OP_ADDR_INDEX_SHIFT 19 -#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19) - -//== Register selection == -#define NV40_FP_REG_TYPE_SHIFT 0 -#define NV40_FP_REG_TYPE_MASK (3 << 0) -# define NV40_FP_REG_TYPE_TEMP 0 -# define NV40_FP_REG_TYPE_INPUT 1 -# define NV40_FP_REG_TYPE_CONST 2 -#define NV40_FP_REG_SRC_SHIFT 2 -#define NV40_FP_REG_SRC_MASK (63 << 2) -#define NV40_FP_REG_SRC_HALF (1 << 8) -#define NV40_FP_REG_SWZ_ALL_SHIFT 9 -#define NV40_FP_REG_SWZ_ALL_MASK (255 << 9) -#define NV40_FP_REG_SWZ_X_SHIFT 9 -#define NV40_FP_REG_SWZ_X_MASK (3 << 9) -#define NV40_FP_REG_SWZ_Y_SHIFT 11 -#define NV40_FP_REG_SWZ_Y_MASK (3 << 11) -#define NV40_FP_REG_SWZ_Z_SHIFT 13 -#define NV40_FP_REG_SWZ_Z_MASK (3 << 13) -#define NV40_FP_REG_SWZ_W_SHIFT 15 -#define NV40_FP_REG_SWZ_W_MASK (3 << 15) -# define NV40_FP_SWIZZLE_X 0 -# define NV40_FP_SWIZZLE_Y 1 -# define NV40_FP_SWIZZLE_Z 2 -# define NV40_FP_SWIZZLE_W 3 -#define NV40_FP_REG_NEGATE (1 << 17) - -#ifndef NV40_SHADER_NO_FUCKEDNESS -#define NV40SR_NONE 0 -#define NV40SR_OUTPUT 1 -#define NV40SR_INPUT 2 -#define NV40SR_TEMP 3 -#define NV40SR_CONST 4 - -struct nv40_sreg { - int type; - int index; - - int dst_scale; - - int negate; - int abs; - int swz[4]; - - int cc_update; - int cc_update_reg; - int cc_test; - int cc_test_reg; - int cc_swz[4]; -}; - -static INLINE struct nv40_sreg -nv40_sr(int type, int index) -{ - struct nv40_sreg temp = { - .type = type, - .index = index, - .dst_scale = DEF_SCALE, - .abs = 0, - .negate = 0, - .swz = { 0, 1, 2, 3 }, - .cc_update = 0, - .cc_update_reg = 0, - .cc_test = DEF_CTEST, - .cc_test_reg = 0, - .cc_swz = { 0, 1, 2, 3 }, - }; - return temp; -} - -static INLINE struct nv40_sreg -nv40_sr_swz(struct nv40_sreg src, int x, int y, int z, int w) -{ - struct nv40_sreg dst = src; - - dst.swz[SWZ_X] = src.swz[x]; - dst.swz[SWZ_Y] = src.swz[y]; - dst.swz[SWZ_Z] = src.swz[z]; - dst.swz[SWZ_W] = src.swz[w]; - return dst; -} - -static INLINE struct nv40_sreg -nv40_sr_neg(struct nv40_sreg src) -{ - src.negate = !src.negate; - return src; -} - -static INLINE struct nv40_sreg -nv40_sr_abs(struct nv40_sreg src) -{ - src.abs = 1; - return src; -} - -static INLINE struct nv40_sreg -nv40_sr_scale(struct nv40_sreg src, int scale) -{ - src.dst_scale = scale; - return src; -} -#endif - -#endif diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c deleted file mode 100644 index 4f28675e64c..00000000000 --- a/src/gallium/drivers/nv40/nv40_state.c +++ /dev/null @@ -1,743 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" - -#include "draw/draw_context.h" - -#include "tgsi/tgsi_parse.h" - -#include "nv40_context.h" -#include "nv40_state.h" - -static void * -nv40_blend_state_create(struct pipe_context *pipe, - const struct pipe_blend_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nouveau_grobj *curie = nv40->screen->curie; - struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso)); - struct nouveau_stateobj *so = so_new(5, 8, 0); - - if (cso->rt[0].blend_enable) { - so_method(so, curie, NV40TCL_BLEND_ENABLE, 3); - so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | - nvgl_blend_func(cso->rt[0].rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rt[0].rgb_dst_factor)); - so_method(so, curie, NV40TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 | - nvgl_blend_eqn(cso->rt[0].rgb_func)); - } else { - so_method(so, curie, NV40TCL_BLEND_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, curie, NV40TCL_COLOR_MASK, 1); - so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); - - if (cso->logicop_enable) { - so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2); - so_data (so, 1); - so_data (so, nvgl_logicop_func(cso->logicop_func)); - } else { - so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, curie, NV40TCL_DITHER_ENABLE, 1); - so_data (so, cso->dither ? 1 : 0); - - so_ref(so, &bso->so); - so_ref(NULL, &so); - bso->pipe = *cso; - return (void *)bso; -} - -static void -nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->blend = hwcso; - nv40->dirty |= NV40_NEW_BLEND; -} - -static void -nv40_blend_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_blend_state *bso = hwcso; - - so_ref(NULL, &bso->so); - FREE(bso); -} - - -static INLINE unsigned -wrap_mode(unsigned wrap) { - unsigned ret; - - switch (wrap) { - case PIPE_TEX_WRAP_REPEAT: - ret = NV40TCL_TEX_WRAP_S_REPEAT; - break; - case PIPE_TEX_WRAP_MIRROR_REPEAT: - ret = NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT; - break; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_CLAMP: - ret = NV40TCL_TEX_WRAP_S_CLAMP; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP; - break; - default: - NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); - ret = NV40TCL_TEX_WRAP_S_REPEAT; - break; - } - - return ret >> NV40TCL_TEX_WRAP_S_SHIFT; -} - -static void * -nv40_sampler_state_create(struct pipe_context *pipe, - const struct pipe_sampler_state *cso) -{ - struct nv40_sampler_state *ps; - uint32_t filter = 0; - - ps = MALLOC(sizeof(struct nv40_sampler_state)); - - ps->fmt = 0; - if (!cso->normalized_coords) - ps->fmt |= NV40TCL_TEX_FORMAT_RECT; - - ps->wrap = ((wrap_mode(cso->wrap_s) << NV40TCL_TEX_WRAP_S_SHIFT) | - (wrap_mode(cso->wrap_t) << NV40TCL_TEX_WRAP_T_SHIFT) | - (wrap_mode(cso->wrap_r) << NV40TCL_TEX_WRAP_R_SHIFT)); - - ps->en = 0; - if (cso->max_anisotropy >= 2) { - /* no idea, binary driver sets it, works without it.. meh.. */ - ps->wrap |= (1 << 5); - - if (cso->max_anisotropy >= 16) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X; - } else - if (cso->max_anisotropy >= 12) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X; - } else - if (cso->max_anisotropy >= 10) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X; - } else - if (cso->max_anisotropy >= 8) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X; - } else - if (cso->max_anisotropy >= 6) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X; - } else - if (cso->max_anisotropy >= 4) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X; - } else { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X; - } - } - - switch (cso->mag_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - filter |= NV40TCL_TEX_FILTER_MAG_LINEAR; - break; - case PIPE_TEX_FILTER_NEAREST: - default: - filter |= NV40TCL_TEX_FILTER_MAG_NEAREST; - break; - } - - switch (cso->min_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV40TCL_TEX_FILTER_MIN_LINEAR; - break; - } - break; - case PIPE_TEX_FILTER_NEAREST: - default: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV40TCL_TEX_FILTER_MIN_NEAREST; - break; - } - break; - } - - ps->filt = filter; - - { - float limit; - - limit = CLAMP(cso->lod_bias, -16.0, 15.0); - ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; - - limit = CLAMP(cso->max_lod, 0.0, 15.0); - ps->en |= (int)(limit * 256.0) << 7; - - limit = CLAMP(cso->min_lod, 0.0, 15.0); - ps->en |= (int)(limit * 256.0) << 19; - } - - - if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - switch (cso->compare_func) { - case PIPE_FUNC_NEVER: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NEVER; - break; - case PIPE_FUNC_GREATER: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GREATER; - break; - case PIPE_FUNC_EQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_EQUAL; - break; - case PIPE_FUNC_GEQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GEQUAL; - break; - case PIPE_FUNC_LESS: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LESS; - break; - case PIPE_FUNC_NOTEQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL; - break; - case PIPE_FUNC_LEQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LEQUAL; - break; - case PIPE_FUNC_ALWAYS: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_ALWAYS; - break; - default: - break; - } - } - - ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | - (float_to_ubyte(cso->border_color[0]) << 16) | - (float_to_ubyte(cso->border_color[1]) << 8) | - (float_to_ubyte(cso->border_color[2]) << 0)); - - return (void *)ps; -} - -static void -nv40_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) -{ - struct nv40_context *nv40 = nv40_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - nv40->tex_sampler[unit] = sampler[unit]; - nv40->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv40->nr_samplers; unit++) { - nv40->tex_sampler[unit] = NULL; - nv40->dirty_samplers |= (1 << unit); - } - - nv40->nr_samplers = nr; - nv40->dirty |= NV40_NEW_SAMPLER; -} - -static void -nv40_sampler_state_delete(struct pipe_context *pipe, void *hwcso) -{ - FREE(hwcso); -} - -static void -nv40_set_sampler_texture(struct pipe_context *pipe, unsigned nr, - struct pipe_texture **miptree) -{ - struct nv40_context *nv40 = nv40_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - pipe_texture_reference((struct pipe_texture **) - &nv40->tex_miptree[unit], miptree[unit]); - nv40->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv40->nr_textures; unit++) { - pipe_texture_reference((struct pipe_texture **) - &nv40->tex_miptree[unit], NULL); - nv40->dirty_samplers |= (1 << unit); - } - - nv40->nr_textures = nr; - nv40->dirty |= NV40_NEW_SAMPLER; -} - -static void * -nv40_rasterizer_state_create(struct pipe_context *pipe, - const struct pipe_rasterizer_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); - struct nouveau_stateobj *so = so_new(9, 19, 0); - struct nouveau_grobj *curie = nv40->screen->curie; - - /*XXX: ignored: - * light_twoside - * point_smooth -nohw - * multisample - */ - - so_method(so, curie, NV40TCL_SHADE_MODEL, 1); - so_data (so, cso->flatshade ? NV40TCL_SHADE_MODEL_FLAT : - NV40TCL_SHADE_MODEL_SMOOTH); - - so_method(so, curie, NV40TCL_LINE_WIDTH, 2); - so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff); - so_data (so, cso->line_smooth ? 1 : 0); - so_method(so, curie, NV40TCL_LINE_STIPPLE_ENABLE, 2); - so_data (so, cso->line_stipple_enable ? 1 : 0); - so_data (so, (cso->line_stipple_pattern << 16) | - cso->line_stipple_factor); - - so_method(so, curie, NV40TCL_POINT_SIZE, 1); - so_data (so, fui(cso->point_size)); - - so_method(so, curie, NV40TCL_POLYGON_MODE_FRONT, 6); - if (cso->front_winding == PIPE_WINDING_CCW) { - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV40TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_CW: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV40TCL_FRONT_FACE_CCW); - } else { - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_CW: - so_data(so, NV40TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV40TCL_FRONT_FACE_CW); - } - so_data(so, cso->poly_smooth ? 1 : 0); - so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); - - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, cso->poly_stipple_enable ? 1 : 0); - - so_method(so, curie, NV40TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) - so_data(so, 1); - else - so_data(so, 0); - if (cso->offset_cw || cso->offset_ccw) { - so_method(so, curie, NV40TCL_POLYGON_OFFSET_FACTOR, 2); - so_data (so, fui(cso->offset_scale)); - so_data (so, fui(cso->offset_units * 2)); - } - - so_method(so, curie, NV40TCL_POINT_SPRITE, 1); - if (cso->point_quad_rasterization) { - unsigned psctl = (1 << 0), i; - - for (i = 0; i < 8; i++) { - if ((cso->sprite_coord_enable >> i) & 1) - psctl |= (1 << (8 + i)); - } - - so_data(so, psctl); - } else { - so_data(so, 0); - } - - so_ref(so, &rsso->so); - so_ref(NULL, &so); - rsso->pipe = *cso; - return (void *)rsso; -} - -static void -nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->rasterizer = hwcso; - nv40->dirty |= NV40_NEW_RAST; - nv40->draw_dirty |= NV40_NEW_RAST; -} - -static void -nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_rasterizer_state *rsso = hwcso; - - so_ref(NULL, &rsso->so); - FREE(rsso); -} - -static void * -nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, - const struct pipe_depth_stencil_alpha_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); - struct nouveau_stateobj *so = so_new(6, 20, 0); - struct nouveau_grobj *curie = nv40->screen->curie; - - so_method(so, curie, NV40TCL_DEPTH_FUNC, 3); - so_data (so, nvgl_comparison_op(cso->depth.func)); - so_data (so, cso->depth.writemask ? 1 : 0); - so_data (so, cso->depth.enabled ? 1 : 0); - - so_method(so, curie, NV40TCL_ALPHA_TEST_ENABLE, 3); - so_data (so, cso->alpha.enabled ? 1 : 0); - so_data (so, nvgl_comparison_op(cso->alpha.func)); - so_data (so, float_to_ubyte(cso->alpha.ref_value)); - - if (cso->stencil[0].enabled) { - so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 3); - so_data (so, cso->stencil[0].enabled ? 1 : 0); - so_data (so, cso->stencil[0].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[0].func)); - so_method(so, curie, NV40TCL_STENCIL_FRONT_FUNC_MASK, 4); - so_data (so, cso->stencil[0].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); - } else { - so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1); - so_data (so, 0); - } - - if (cso->stencil[1].enabled) { - so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 3); - so_data (so, cso->stencil[1].enabled ? 1 : 0); - so_data (so, cso->stencil[1].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[1].func)); - so_method(so, curie, NV40TCL_STENCIL_BACK_FUNC_MASK, 4); - so_data (so, cso->stencil[1].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); - } else { - so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &zsaso->so); - so_ref(NULL, &so); - zsaso->pipe = *cso; - return (void *)zsaso; -} - -static void -nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->zsa = hwcso; - nv40->dirty |= NV40_NEW_ZSA; -} - -static void -nv40_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_zsa_state *zsaso = hwcso; - - so_ref(NULL, &zsaso->so); - FREE(zsaso); -} - -static void * -nv40_vp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_vertex_program *vp; - - vp = CALLOC(1, sizeof(struct nv40_vertex_program)); - vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - vp->draw = draw_create_vertex_shader(nv40->draw, &vp->pipe); - - return (void *)vp; -} - -static void -nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->vertprog = hwcso; - nv40->dirty |= NV40_NEW_VERTPROG; - nv40->draw_dirty |= NV40_NEW_VERTPROG; -} - -static void -nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_vertex_program *vp = hwcso; - - draw_delete_vertex_shader(nv40->draw, vp->draw); - nv40_vertprog_destroy(nv40, vp); - FREE((void*)vp->pipe.tokens); - FREE(vp); -} - -static void * -nv40_fp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - struct nv40_fragment_program *fp; - - fp = CALLOC(1, sizeof(struct nv40_fragment_program)); - fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - - tgsi_scan_shader(fp->pipe.tokens, &fp->info); - - return (void *)fp; -} - -static void -nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->fragprog = hwcso; - nv40->dirty |= NV40_NEW_FRAGPROG; -} - -static void -nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_fragment_program *fp = hwcso; - - nv40_fragprog_destroy(nv40, fp); - FREE((void*)fp->pipe.tokens); - FREE(fp); -} - -static void -nv40_set_blend_color(struct pipe_context *pipe, - const struct pipe_blend_color *bcol) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->blend_colour = *bcol; - nv40->dirty |= NV40_NEW_BCOL; -} - - static void -nv40_set_stencil_ref(struct pipe_context *pipe, - const struct pipe_stencil_ref *sr) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->stencil_ref = *sr; - nv40->dirty |= NV40_NEW_SR; -} - -static void -nv40_set_clip_state(struct pipe_context *pipe, - const struct pipe_clip_state *clip) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->clip = *clip; - nv40->dirty |= NV40_NEW_UCP; - nv40->draw_dirty |= NV40_NEW_UCP; -} - -static void -nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf ) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->constbuf[shader] = buf; - nv40->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); - - if (shader == PIPE_SHADER_VERTEX) { - nv40->dirty |= NV40_NEW_VERTPROG; - } else - if (shader == PIPE_SHADER_FRAGMENT) { - nv40->dirty |= NV40_NEW_FRAGPROG; - } -} - -static void -nv40_set_framebuffer_state(struct pipe_context *pipe, - const struct pipe_framebuffer_state *fb) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->framebuffer = *fb; - nv40->dirty |= NV40_NEW_FB; -} - -static void -nv40_set_polygon_stipple(struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - memcpy(nv40->stipple, stipple->stipple, 4 * 32); - nv40->dirty |= NV40_NEW_STIPPLE; -} - -static void -nv40_set_scissor_state(struct pipe_context *pipe, - const struct pipe_scissor_state *s) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->scissor = *s; - nv40->dirty |= NV40_NEW_SCISSOR; -} - -static void -nv40_set_viewport_state(struct pipe_context *pipe, - const struct pipe_viewport_state *vpt) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->viewport = *vpt; - nv40->dirty |= NV40_NEW_VIEWPORT; - nv40->draw_dirty |= NV40_NEW_VIEWPORT; -} - -static void -nv40_set_vertex_buffers(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_buffer *vb) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - memcpy(nv40->vtxbuf, vb, sizeof(*vb) * count); - nv40->vtxbuf_nr = count; - - nv40->dirty |= NV40_NEW_ARRAYS; - nv40->draw_dirty |= NV40_NEW_ARRAYS; -} - -static void -nv40_set_vertex_elements(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_element *ve) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - memcpy(nv40->vtxelt, ve, sizeof(*ve) * count); - nv40->vtxelt_nr = count; - - nv40->dirty |= NV40_NEW_ARRAYS; - nv40->draw_dirty |= NV40_NEW_ARRAYS; -} - -void -nv40_init_state_functions(struct nv40_context *nv40) -{ - nv40->pipe.create_blend_state = nv40_blend_state_create; - nv40->pipe.bind_blend_state = nv40_blend_state_bind; - nv40->pipe.delete_blend_state = nv40_blend_state_delete; - - nv40->pipe.create_sampler_state = nv40_sampler_state_create; - nv40->pipe.bind_fragment_sampler_states = nv40_sampler_state_bind; - nv40->pipe.delete_sampler_state = nv40_sampler_state_delete; - nv40->pipe.set_fragment_sampler_textures = nv40_set_sampler_texture; - - nv40->pipe.create_rasterizer_state = nv40_rasterizer_state_create; - nv40->pipe.bind_rasterizer_state = nv40_rasterizer_state_bind; - nv40->pipe.delete_rasterizer_state = nv40_rasterizer_state_delete; - - nv40->pipe.create_depth_stencil_alpha_state = - nv40_depth_stencil_alpha_state_create; - nv40->pipe.bind_depth_stencil_alpha_state = - nv40_depth_stencil_alpha_state_bind; - nv40->pipe.delete_depth_stencil_alpha_state = - nv40_depth_stencil_alpha_state_delete; - - nv40->pipe.create_vs_state = nv40_vp_state_create; - nv40->pipe.bind_vs_state = nv40_vp_state_bind; - nv40->pipe.delete_vs_state = nv40_vp_state_delete; - - nv40->pipe.create_fs_state = nv40_fp_state_create; - nv40->pipe.bind_fs_state = nv40_fp_state_bind; - nv40->pipe.delete_fs_state = nv40_fp_state_delete; - - nv40->pipe.set_blend_color = nv40_set_blend_color; - nv40->pipe.set_stencil_ref = nv40_set_stencil_ref; - nv40->pipe.set_clip_state = nv40_set_clip_state; - nv40->pipe.set_constant_buffer = nv40_set_constant_buffer; - nv40->pipe.set_framebuffer_state = nv40_set_framebuffer_state; - nv40->pipe.set_polygon_stipple = nv40_set_polygon_stipple; - nv40->pipe.set_scissor_state = nv40_set_scissor_state; - nv40->pipe.set_viewport_state = nv40_set_viewport_state; - - nv40->pipe.set_vertex_buffers = nv40_set_vertex_buffers; - nv40->pipe.set_vertex_elements = nv40_set_vertex_elements; -} - diff --git a/src/gallium/drivers/nv40/nv40_state_blend.c b/src/gallium/drivers/nv40/nv40_state_blend.c deleted file mode 100644 index 3ff00a37f66..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_blend.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_blend_validate(struct nv40_context *nv40) -{ - so_ref(nv40->blend->so, &nv40->state.hw[NV40_STATE_BLEND]); - return TRUE; -} - -struct nv40_state_entry nv40_state_blend = { - .validate = nv40_state_blend_validate, - .dirty = { - .pipe = NV40_NEW_BLEND, - .hw = NV40_STATE_BLEND - } -}; - -static boolean -nv40_state_blend_colour_validate(struct nv40_context *nv40) -{ - struct nouveau_stateobj *so = so_new(1, 1, 0); - struct pipe_blend_color *bcol = &nv40->blend_colour; - - so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1); - so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | - (float_to_ubyte(bcol->color[0]) << 16) | - (float_to_ubyte(bcol->color[1]) << 8) | - (float_to_ubyte(bcol->color[2]) << 0))); - - so_ref(so, &nv40->state.hw[NV40_STATE_BCOL]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_blend_colour = { - .validate = nv40_state_blend_colour_validate, - .dirty = { - .pipe = NV40_NEW_BCOL, - .hw = NV40_STATE_BCOL - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c deleted file mode 100644 index 8990f303ce4..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_emit.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "nv40_context.h" -#include "nv40_state.h" -#include "draw/draw_context.h" - -static struct nv40_state_entry *render_states[] = { - &nv40_state_framebuffer, - &nv40_state_rasterizer, - &nv40_state_scissor, - &nv40_state_stipple, - &nv40_state_fragprog, - &nv40_state_fragtex, - &nv40_state_vertprog, - &nv40_state_blend, - &nv40_state_blend_colour, - &nv40_state_zsa, - &nv40_state_sr, - &nv40_state_viewport, - &nv40_state_vbo, - NULL -}; - -static struct nv40_state_entry *swtnl_states[] = { - &nv40_state_framebuffer, - &nv40_state_rasterizer, - &nv40_state_scissor, - &nv40_state_stipple, - &nv40_state_fragprog, - &nv40_state_fragtex, - &nv40_state_vertprog, - &nv40_state_blend, - &nv40_state_blend_colour, - &nv40_state_zsa, - &nv40_state_sr, - &nv40_state_viewport, - &nv40_state_vtxfmt, - NULL -}; - -static void -nv40_state_do_validate(struct nv40_context *nv40, - struct nv40_state_entry **states) -{ - while (*states) { - struct nv40_state_entry *e = *states; - - if (nv40->dirty & e->dirty.pipe) { - if (e->validate(nv40)) - nv40->state.dirty |= (1ULL << e->dirty.hw); - } - - states++; - } - nv40->dirty = 0; -} - -void -nv40_state_emit(struct nv40_context *nv40) -{ - struct nv40_state *state = &nv40->state; - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned i; - uint64_t states; - - /* XXX: race conditions - */ - if (nv40 != screen->cur_ctx) { - for (i = 0; i < NV40_STATE_MAX; i++) { - if (state->hw[i] && screen->state[i] != state->hw[i]) - state->dirty |= (1ULL << i); - } - - screen->cur_ctx = nv40; - } - - for (i = 0, states = state->dirty; states; i++) { - if (!(states & (1ULL << i))) - continue; - so_ref (state->hw[i], &nv40->screen->state[i]); - if (state->hw[i]) - so_emit(chan, nv40->screen->state[i]); - states &= ~(1ULL << i); - } - - if (state->dirty & ((1ULL << NV40_STATE_FRAGPROG) | - (1ULL << NV40_STATE_FRAGTEX0))) { - BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); - OUT_RING (chan, 2); - BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); - OUT_RING (chan, 1); - } - - state->dirty = 0; -} - -void -nv40_state_flush_notify(struct nouveau_channel *chan) -{ - struct nv40_context *nv40 = chan->user_private; - struct nv40_state *state = &nv40->state; - unsigned i, samplers; - - so_emit_reloc_markers(chan, state->hw[NV40_STATE_FB]); - for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { - if (!(samplers & (1 << i))) - continue; - so_emit_reloc_markers(chan, - state->hw[NV40_STATE_FRAGTEX0+i]); - samplers &= ~(1ULL << i); - } - so_emit_reloc_markers(chan, state->hw[NV40_STATE_FRAGPROG]); - if (state->hw[NV40_STATE_VTXBUF] && nv40->render_mode == HW) - so_emit_reloc_markers(chan, state->hw[NV40_STATE_VTXBUF]); -} - -boolean -nv40_state_validate(struct nv40_context *nv40) -{ - boolean was_sw = nv40->fallback_swtnl ? TRUE : FALSE; - - if (nv40->render_mode != HW) { - /* Don't even bother trying to go back to hw if none - * of the states that caused swtnl previously have changed. - */ - if ((nv40->fallback_swtnl & nv40->dirty) - != nv40->fallback_swtnl) - return FALSE; - - /* Attempt to go to hwtnl again */ - nv40->pipe.flush(&nv40->pipe, 0, NULL); - nv40->dirty |= (NV40_NEW_VIEWPORT | - NV40_NEW_VERTPROG | - NV40_NEW_ARRAYS); - nv40->render_mode = HW; - } - - nv40_state_do_validate(nv40, render_states); - if (nv40->fallback_swtnl || nv40->fallback_swrast) - return FALSE; - - if (was_sw) - NOUVEAU_ERR("swtnl->hw\n"); - - return TRUE; -} - -boolean -nv40_state_validate_swtnl(struct nv40_context *nv40) -{ - struct draw_context *draw = nv40->draw; - - /* Setup for swtnl */ - if (nv40->render_mode == HW) { - NOUVEAU_ERR("hw->swtnl 0x%08x\n", nv40->fallback_swtnl); - nv40->pipe.flush(&nv40->pipe, 0, NULL); - nv40->dirty |= (NV40_NEW_VIEWPORT | - NV40_NEW_VERTPROG | - NV40_NEW_ARRAYS); - nv40->render_mode = SWTNL; - } - - if (nv40->draw_dirty & NV40_NEW_VERTPROG) - draw_bind_vertex_shader(draw, nv40->vertprog->draw); - - if (nv40->draw_dirty & NV40_NEW_RAST) - draw_set_rasterizer_state(draw, &nv40->rasterizer->pipe); - - if (nv40->draw_dirty & NV40_NEW_UCP) - draw_set_clip_state(draw, &nv40->clip); - - if (nv40->draw_dirty & NV40_NEW_VIEWPORT) - draw_set_viewport_state(draw, &nv40->viewport); - - if (nv40->draw_dirty & NV40_NEW_ARRAYS) { - draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf); - draw_set_vertex_elements(draw, nv40->vtxelt_nr, nv40->vtxelt); - } - - nv40_state_do_validate(nv40, swtnl_states); - if (nv40->fallback_swrast) { - NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nv40->fallback_swrast); - return FALSE; - } - - nv40->draw_dirty = 0; - return TRUE; -} - diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c deleted file mode 100644 index fd3fdfddc09..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_fb.c +++ /dev/null @@ -1,175 +0,0 @@ -#include "nv40_context.h" -#include "nouveau/nouveau_util.h" - -static struct pipe_buffer * -nv40_do_surface_buffer(struct pipe_surface *surface) -{ - struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture; - return mt->buffer; -} - -#define nv40_surface_buffer(ps) nouveau_bo(nv40_do_surface_buffer(ps)) - -static boolean -nv40_state_framebuffer_validate(struct nv40_context *nv40) -{ - struct nouveau_channel *chan = nv40->screen->base.channel; - struct nouveau_grobj *curie = nv40->screen->curie; - struct pipe_framebuffer_state *fb = &nv40->framebuffer; - struct nv04_surface *rt[4], *zeta; - uint32_t rt_enable, rt_format; - int i, colour_format = 0, zeta_format = 0; - struct nouveau_stateobj *so = so_new(18, 24, 10); - unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; - unsigned w = fb->width; - unsigned h = fb->height; - - rt_enable = 0; - for (i = 0; i < fb->nr_cbufs; i++) { - if (colour_format) { - assert(colour_format == fb->cbufs[i]->format); - } else { - colour_format = fb->cbufs[i]->format; - rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i); - rt[i] = (struct nv04_surface *)fb->cbufs[i]; - } - } - - if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 | - NV40TCL_RT_ENABLE_COLOR3)) - rt_enable |= NV40TCL_RT_ENABLE_MRT; - - if (fb->zsbuf) { - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); - for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); - - rt_format = NV40TCL_RT_FORMAT_TYPE_SWIZZLED | - log2i(fb->width) << NV40TCL_RT_FORMAT_LOG2_WIDTH_SHIFT | - log2i(fb->height) << NV40TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT; - } - else - rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR; - - switch (colour_format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - rt_format |= NV40TCL_RT_FORMAT_COLOR_X8R8G8B8; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - case 0: - rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5; - break; - default: - assert(0); - } - - switch (zeta_format) { - case PIPE_FORMAT_Z16_UNORM: - rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16; - break; - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - case 0: - rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8; - break; - default: - assert(0); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { - so_method(so, curie, NV40TCL_DMA_COLOR0, 1); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR0_PITCH, 2); - so_data (so, rt[0]->pitch); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), - rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { - so_method(so, curie, NV40TCL_DMA_COLOR1, 1); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), - rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_data (so, rt[1]->pitch); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { - so_method(so, curie, NV40TCL_DMA_COLOR2, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR2_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), - rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_method(so, curie, NV40TCL_COLOR2_PITCH, 1); - so_data (so, rt[2]->pitch); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { - so_method(so, curie, NV40TCL_DMA_COLOR3, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR3_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), - rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_method(so, curie, NV40TCL_COLOR3_PITCH, 1); - so_data (so, rt[3]->pitch); - } - - if (zeta_format) { - so_method(so, curie, NV40TCL_DMA_ZETA, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_ZETA_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), - zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_method(so, curie, NV40TCL_ZETA_PITCH, 1); - so_data (so, zeta->pitch); - } - - so_method(so, curie, NV40TCL_RT_ENABLE, 1); - so_data (so, rt_enable); - so_method(so, curie, NV40TCL_RT_HORIZ, 3); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_data (so, rt_format); - so_method(so, curie, NV40TCL_VIEWPORT_HORIZ, 2); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_method(so, curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2); - so_data (so, ((w - 1) << 16) | 0); - so_data (so, ((h - 1) << 16) | 0); - so_method(so, curie, 0x1d88, 1); - so_data (so, (1 << 12) | h); - - so_ref(so, &nv40->state.hw[NV40_STATE_FB]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_framebuffer = { - .validate = nv40_state_framebuffer_validate, - .dirty = { - .pipe = NV40_NEW_FB, - .hw = NV40_STATE_FB - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_rasterizer.c b/src/gallium/drivers/nv40/nv40_state_rasterizer.c deleted file mode 100644 index 9ecda5990f0..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_rasterizer.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_rasterizer_validate(struct nv40_context *nv40) -{ - so_ref(nv40->rasterizer->so, - &nv40->state.hw[NV40_STATE_RAST]); - return TRUE; -} - -struct nv40_state_entry nv40_state_rasterizer = { - .validate = nv40_state_rasterizer_validate, - .dirty = { - .pipe = NV40_NEW_RAST, - .hw = NV40_STATE_RAST - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_scissor.c b/src/gallium/drivers/nv40/nv40_state_scissor.c deleted file mode 100644 index 753a505e934..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_scissor.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_scissor_validate(struct nv40_context *nv40) -{ - struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe; - struct pipe_scissor_state *s = &nv40->scissor; - struct nouveau_stateobj *so; - - if (nv40->state.hw[NV40_STATE_SCISSOR] && - (rast->scissor == 0 && nv40->state.scissor_enabled == 0)) - return FALSE; - nv40->state.scissor_enabled = rast->scissor; - - so = so_new(1, 2, 0); - so_method(so, nv40->screen->curie, NV40TCL_SCISSOR_HORIZ, 2); - if (nv40->state.scissor_enabled) { - so_data (so, ((s->maxx - s->minx) << 16) | s->minx); - so_data (so, ((s->maxy - s->miny) << 16) | s->miny); - } else { - so_data (so, 4096 << 16); - so_data (so, 4096 << 16); - } - - so_ref(so, &nv40->state.hw[NV40_STATE_SCISSOR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_scissor = { - .validate = nv40_state_scissor_validate, - .dirty = { - .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST, - .hw = NV40_STATE_SCISSOR - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_stipple.c b/src/gallium/drivers/nv40/nv40_state_stipple.c deleted file mode 100644 index 2b371ebfec0..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_stipple.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_stipple_validate(struct nv40_context *nv40) -{ - struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe; - struct nouveau_grobj *curie = nv40->screen->curie; - struct nouveau_stateobj *so; - - if (nv40->state.hw[NV40_STATE_STIPPLE] && - (rast->poly_stipple_enable == 0 && nv40->state.stipple_enabled == 0)) - return FALSE; - - if (rast->poly_stipple_enable) { - unsigned i; - - so = so_new(2, 33, 0); - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 1); - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32); - for (i = 0; i < 32; i++) - so_data(so, nv40->stipple[i]); - } else { - so = so_new(1, 1, 0); - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &nv40->state.hw[NV40_STATE_STIPPLE]); - return TRUE; -} - -struct nv40_state_entry nv40_state_stipple = { - .validate = nv40_state_stipple_validate, - .dirty = { - .pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST, - .hw = NV40_STATE_STIPPLE, - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c deleted file mode 100644 index 3aacb00f996..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_viewport.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_viewport_validate(struct nv40_context *nv40) -{ - struct pipe_viewport_state *vpt = &nv40->viewport; - struct nouveau_stateobj *so; - - if (nv40->state.hw[NV40_STATE_VIEWPORT] && - !(nv40->dirty & NV40_NEW_VIEWPORT)) - return FALSE; - - so = so_new(2, 9, 0); - so_method(so, nv40->screen->curie, - NV40TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(vpt->translate[0])); - so_data (so, fui(vpt->translate[1])); - so_data (so, fui(vpt->translate[2])); - so_data (so, fui(vpt->translate[3])); - so_data (so, fui(vpt->scale[0])); - so_data (so, fui(vpt->scale[1])); - so_data (so, fui(vpt->scale[2])); - so_data (so, fui(vpt->scale[3])); - so_method(so, nv40->screen->curie, 0x1d78, 1); - so_data (so, 1); - - so_ref(so, &nv40->state.hw[NV40_STATE_VIEWPORT]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_viewport = { - .validate = nv40_state_viewport_validate, - .dirty = { - .pipe = NV40_NEW_VIEWPORT | NV40_NEW_RAST, - .hw = NV40_STATE_VIEWPORT - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_zsa.c b/src/gallium/drivers/nv40/nv40_state_zsa.c deleted file mode 100644 index 9cbe7da6db1..00000000000 --- a/src/gallium/drivers/nv40/nv40_state_zsa.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_zsa_validate(struct nv40_context *nv40) -{ - so_ref(nv40->zsa->so, - &nv40->state.hw[NV40_STATE_ZSA]); - return TRUE; -} - -struct nv40_state_entry nv40_state_zsa = { - .validate = nv40_state_zsa_validate, - .dirty = { - .pipe = NV40_NEW_ZSA, - .hw = NV40_STATE_ZSA - } -}; - -static boolean -nv40_state_sr_validate(struct nv40_context *nv40) -{ - struct nouveau_stateobj *so = so_new(2, 2, 0); - struct pipe_stencil_ref *sr = &nv40->stencil_ref; - - so_method(so, nv40->screen->curie, NV40TCL_STENCIL_FRONT_FUNC_REF, 1); - so_data (so, sr->ref_value[0]); - so_method(so, nv40->screen->curie, NV40TCL_STENCIL_BACK_FUNC_REF, 1); - so_data (so, sr->ref_value[1]); - - so_ref(so, &nv40->state.hw[NV40_STATE_SR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_sr = { - .validate = nv40_state_sr_validate, - .dirty = { - .pipe = NV40_NEW_SR, - .hw = NV40_STATE_SR - } -}; diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c deleted file mode 100644 index 02ecfd7bbb7..00000000000 --- a/src/gallium/drivers/nv40/nv40_surface.c +++ /dev/null @@ -1,64 +0,0 @@ - -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_defines.h" -#include "util/u_inlines.h" - -#include "util/u_tile.h" - -#include "nv40_context.h" - -static void -nv40_surface_copy(struct pipe_context *pipe, - struct pipe_surface *dest, unsigned destx, unsigned desty, - struct pipe_surface *src, unsigned srcx, unsigned srcy, - unsigned width, unsigned height) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv04_surface_2d *eng2d = nv40->screen->eng2d; - - eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); -} - -static void -nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, - unsigned destx, unsigned desty, unsigned width, - unsigned height, unsigned value) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv04_surface_2d *eng2d = nv40->screen->eng2d; - - eng2d->fill(eng2d, dest, destx, desty, width, height, value); -} - -void -nv40_init_surface_functions(struct nv40_context *nv40) -{ - nv40->pipe.surface_copy = nv40_surface_copy; - nv40->pipe.surface_fill = nv40_surface_fill; -} diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c deleted file mode 100644 index 7812460d2ed..00000000000 --- a/src/gallium/drivers/nv40/nv40_vbo.c +++ /dev/null @@ -1,565 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "util/u_format.h" - -#include "nv40_context.h" -#include "nv40_state.h" - -#include "nouveau/nouveau_channel.h" -#include "nouveau/nouveau_pushbuf.h" -#include "nouveau/nouveau_util.h" - -#define FORCE_SWTNL 0 - -static INLINE int -nv40_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) -{ - switch (pipe) { - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - *fmt = NV40TCL_VTXFMT_TYPE_FLOAT; - break; - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R8G8B8A8_UNORM: - *fmt = NV40TCL_VTXFMT_TYPE_UBYTE; - break; - case PIPE_FORMAT_R16_SSCALED: - case PIPE_FORMAT_R16G16_SSCALED: - case PIPE_FORMAT_R16G16B16_SSCALED: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *fmt = NV40TCL_VTXFMT_TYPE_USHORT; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - switch (pipe) { - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R16_SSCALED: - *ncomp = 1; - break; - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R16G16_SSCALED: - *ncomp = 2; - break; - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R16G16B16_SSCALED: - *ncomp = 3; - break; - case PIPE_FORMAT_R8G8B8A8_UNORM: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *ncomp = 4; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - return 0; -} - -static boolean -nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib, - unsigned ib_size) -{ - struct pipe_screen *pscreen = &nv40->screen->base.base; - unsigned type; - - if (!ib) { - nv40->idxbuf = NULL; - nv40->idxbuf_format = 0xdeadbeef; - return FALSE; - } - - if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) - return FALSE; - - switch (ib_size) { - case 2: - type = NV40TCL_IDXBUF_FORMAT_TYPE_U16; - break; - case 4: - type = NV40TCL_IDXBUF_FORMAT_TYPE_U32; - break; - default: - return FALSE; - } - - if (ib != nv40->idxbuf || - type != nv40->idxbuf_format) { - nv40->dirty |= NV40_NEW_ARRAYS; - nv40->idxbuf = ib; - nv40->idxbuf_format = type; - } - - return TRUE; -} - -static boolean -nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so, - int attrib, struct pipe_vertex_element *ve, - struct pipe_vertex_buffer *vb) -{ - struct pipe_screen *pscreen = nv40->pipe.screen; - struct nouveau_grobj *curie = nv40->screen->curie; - unsigned type, ncomp; - void *map; - - if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) - return FALSE; - - map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); - map += vb->buffer_offset + ve->src_offset; - - switch (type) { - case NV40TCL_VTXFMT_TYPE_FLOAT: - { - float *v = map; - - switch (ncomp) { - case 4: - so_method(so, curie, NV40TCL_VTX_ATTR_4F_X(attrib), 4); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - so_data (so, fui(v[3])); - break; - case 3: - so_method(so, curie, NV40TCL_VTX_ATTR_3F_X(attrib), 3); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - break; - case 2: - so_method(so, curie, NV40TCL_VTX_ATTR_2F_X(attrib), 2); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - break; - case 1: - so_method(so, curie, NV40TCL_VTX_ATTR_1F(attrib), 1); - so_data (so, fui(v[0])); - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - } - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - - pipe_buffer_unmap(pscreen, vb->buffer); - - return TRUE; -} - -void -nv40_draw_arrays(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned restart; - - nv40_vbo_set_idxbuf(nv40, NULL, 0); - if (FORCE_SWTNL || !nv40_state_validate(nv40)) { - nv40_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count); - return; - } - - while (count) { - unsigned vc, nr; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, curie, NV40TCL_VB_VERTEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_VERTEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } - - pipe->flush(pipe, 0, NULL); -} - -static INLINE void -nv40_draw_elements_u08(struct nv40_context *nv40, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - while (count) { - uint8_t *elts = (uint8_t *)ib + start; - unsigned vc, push, restart; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, curie, NV40TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv40_draw_elements_u16(struct nv40_context *nv40, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - while (count) { - uint16_t *elts = (uint16_t *)ib + start; - unsigned vc, push, restart; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, curie, NV40TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv40_draw_elements_u32(struct nv40_context *nv40, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - while (count) { - uint32_t *elts = (uint32_t *)ib + start; - unsigned vc, push, restart; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - while (vc) { - push = MIN2(vc, 2047); - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_ELEMENT_U32, push); - OUT_RINGp (chan, elts, push); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static void -nv40_draw_elements_inline(struct pipe_context *pipe, - struct pipe_buffer *ib, unsigned ib_size, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct pipe_screen *pscreen = pipe->screen; - void *map; - - map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); - if (!ib) { - NOUVEAU_ERR("failed mapping ib\n"); - return; - } - - switch (ib_size) { - case 1: - nv40_draw_elements_u08(nv40, map, mode, start, count); - break; - case 2: - nv40_draw_elements_u16(nv40, map, mode, start, count); - break; - case 4: - nv40_draw_elements_u32(nv40, map, mode, start, count); - break; - default: - NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); - break; - } - - pipe_buffer_unmap(pscreen, ib); -} - -static void -nv40_draw_elements_vbo(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned restart; - - while (count) { - unsigned nr, vc; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, curie, NV40TCL_VB_INDEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_INDEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } -} - -void -nv40_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, unsigned indexSize, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - boolean idxbuf; - - idxbuf = nv40_vbo_set_idxbuf(nv40, indexBuffer, indexSize); - if (FORCE_SWTNL || !nv40_state_validate(nv40)) { - nv40_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count); - return; - } - - if (idxbuf) { - nv40_draw_elements_vbo(pipe, mode, start, count); - } else { - nv40_draw_elements_inline(pipe, indexBuffer, indexSize, - mode, start, count); - } - - pipe->flush(pipe, 0, NULL); -} - -static boolean -nv40_vbo_validate(struct nv40_context *nv40) -{ - struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; - struct nouveau_grobj *curie = nv40->screen->curie; - struct pipe_buffer *ib = nv40->idxbuf; - unsigned ib_format = nv40->idxbuf_format; - unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - int hw; - - vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt_nr); - vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt_nr); - - for (hw = 0; hw < nv40->vtxelt_nr; hw++) { - struct pipe_vertex_element *ve; - struct pipe_vertex_buffer *vb; - unsigned type, ncomp; - - ve = &nv40->vtxelt[hw]; - vb = &nv40->vtxbuf[ve->vertex_buffer_index]; - - if (!vb->stride) { - if (!sattr) - sattr = so_new(16, 16 * 4, 0); - - if (nv40_vbo_static_attrib(nv40, sattr, hw, ve, vb)) { - so_data(vtxbuf, 0); - so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT); - continue; - } - } - - if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { - nv40->fallback_swtnl |= NV40_NEW_ARRAYS; - so_ref(NULL, &vtxbuf); - so_ref(NULL, &vtxfmt); - return FALSE; - } - - so_reloc(vtxbuf, nouveau_bo(vb->buffer), - vb->buffer_offset + ve->src_offset, - vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, - 0, NV40TCL_VTXBUF_ADDRESS_DMA1); - so_data (vtxfmt, ((vb->stride << NV40TCL_VTXFMT_STRIDE_SHIFT) | - (ncomp << NV40TCL_VTXFMT_SIZE_SHIFT) | type)); - } - - if (ib) { - struct nouveau_bo *bo = nouveau_bo(ib); - - so_method(vtxbuf, curie, NV40TCL_IDXBUF_ADDRESS, 2); - so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, - 0, NV40TCL_IDXBUF_FORMAT_DMA1); - } - - so_method(vtxbuf, curie, 0x1710, 1); - so_data (vtxbuf, 0); - - so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]); - so_ref(NULL, &vtxbuf); - nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF); - so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]); - so_ref(NULL, &vtxfmt); - nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT); - so_ref(sattr, &nv40->state.hw[NV40_STATE_VTXATTR]); - so_ref(NULL, &sattr); - nv40->state.dirty |= (1ULL << NV40_STATE_VTXATTR); - return FALSE; -} - -struct nv40_state_entry nv40_state_vbo = { - .validate = nv40_vbo_validate, - .dirty = { - .pipe = NV40_NEW_ARRAYS, - .hw = 0, - } -}; - diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile index 612aea28a34..5d622e1c13c 100644 --- a/src/gallium/drivers/nv50/Makefile +++ b/src/gallium/drivers/nv50/Makefile @@ -16,6 +16,7 @@ C_SOURCES = \ nv50_surface.c \ nv50_tex.c \ nv50_transfer.c \ - nv50_vbo.c + nv50_vbo.c \ + nv50_push.c include ../../Makefile.template diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c index e0b2d2880b0..8afc95c9fc6 100644 --- a/src/gallium/drivers/nv50/nv50_clear.c +++ b/src/gallium/drivers/nv50/nv50_clear.c @@ -36,7 +36,7 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned mode = 0, i; - if (!nv50_state_validate(nv50)) + if (!nv50_state_validate(nv50, 64)) return; if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 7be12fcdef4..aa14e17872d 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -46,43 +46,13 @@ static void nv50_destroy(struct pipe_context *pipe) { struct nv50_context *nv50 = nv50_context(pipe); + int i; - if (nv50->state.fb) - so_ref(NULL, &nv50->state.fb); - if (nv50->state.blend) - so_ref(NULL, &nv50->state.blend); - if (nv50->state.blend_colour) - so_ref(NULL, &nv50->state.blend_colour); - if (nv50->state.zsa) - so_ref(NULL, &nv50->state.zsa); - if (nv50->state.rast) - so_ref(NULL, &nv50->state.rast); - if (nv50->state.stipple) - so_ref(NULL, &nv50->state.stipple); - if (nv50->state.scissor) - so_ref(NULL, &nv50->state.scissor); - if (nv50->state.viewport) - so_ref(NULL, &nv50->state.viewport); - if (nv50->state.tsc_upload) - so_ref(NULL, &nv50->state.tsc_upload); - if (nv50->state.tic_upload) - so_ref(NULL, &nv50->state.tic_upload); - if (nv50->state.vertprog) - so_ref(NULL, &nv50->state.vertprog); - if (nv50->state.fragprog) - so_ref(NULL, &nv50->state.fragprog); - if (nv50->state.geomprog) - so_ref(NULL, &nv50->state.geomprog); - if (nv50->state.fp_linkage) - so_ref(NULL, &nv50->state.fp_linkage); - if (nv50->state.gp_linkage) - so_ref(NULL, &nv50->state.gp_linkage); - if (nv50->state.vtxfmt) - so_ref(NULL, &nv50->state.vtxfmt); - if (nv50->state.vtxbuf) - so_ref(NULL, &nv50->state.vtxbuf); - if (nv50->state.vtxattr) - so_ref(NULL, &nv50->state.vtxattr); + for (i = 0; i < 64; i++) { + if (!nv50->state.hw[i]) + continue; + so_ref(NULL, &nv50->state.hw[i]); + } draw_destroy(nv50->draw); @@ -123,11 +93,11 @@ nv50_create(struct pipe_screen *pscreen, void *priv) nv50->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; screen->base.channel->user_private = nv50; - screen->base.channel->flush_notify = nv50_state_flush_notify; nv50_init_surface_functions(nv50); nv50_init_state_functions(nv50); nv50_init_query_functions(nv50); + nv50_init_transfer_functions(nv50); nv50->draw = draw_create(); assert(nv50->draw); diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index c540594b949..bc7831d9aca 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -72,6 +72,23 @@ struct nv50_sampler_stateobj { unsigned tsc[8]; }; +struct nv50_sampler_view { + struct pipe_sampler_view pipe; + uint32_t tic[8]; +}; + +struct nv50_vtxelt_stateobj { + struct pipe_vertex_element pipe[16]; + unsigned num_elements; + uint32_t hw[16]; +}; + +static INLINE struct nv50_sampler_view * +nv50_sampler_view(struct pipe_sampler_view *view) +{ + return (struct nv50_sampler_view *)view; +} + static INLINE unsigned get_tile_height(uint32_t tile_mode) { @@ -90,10 +107,12 @@ struct nv50_miptree_level { unsigned tile_mode; }; +#define NV50_MAX_TEXTURE_LEVELS 16 + struct nv50_miptree { struct nouveau_miptree base; - struct nv50_miptree_level level[PIPE_MAX_TEXTURE_LEVELS]; + struct nv50_miptree_level level[NV50_MAX_TEXTURE_LEVELS]; int image_nr; int total_size; }; @@ -115,30 +134,12 @@ nv50_surface(struct pipe_surface *pt) } struct nv50_state { - unsigned dirty; + struct nouveau_stateobj *hw[64]; + uint64_t hw_dirty; - struct nouveau_stateobj *fb; - struct nouveau_stateobj *blend; - struct nouveau_stateobj *blend_colour; - struct nouveau_stateobj *zsa; - struct nouveau_stateobj *stencil_ref; - struct nouveau_stateobj *rast; - struct nouveau_stateobj *stipple; - struct nouveau_stateobj *scissor; - unsigned scissor_enabled; - struct nouveau_stateobj *viewport; - struct nouveau_stateobj *tsc_upload; - struct nouveau_stateobj *tic_upload; - unsigned miptree_nr[PIPE_SHADER_TYPES]; - struct nouveau_stateobj *vertprog; - struct nouveau_stateobj *fragprog; - struct nouveau_stateobj *geomprog; - struct nouveau_stateobj *fp_linkage; - struct nouveau_stateobj *gp_linkage; - struct nouveau_stateobj *vtxfmt; + unsigned sampler_view_nr[3]; struct nouveau_stateobj *vtxbuf; struct nouveau_stateobj *vtxattr; - struct nouveau_stateobj *instbuf; unsigned vtxelt_nr; }; @@ -167,14 +168,13 @@ struct nv50_context { struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; unsigned vtxbuf_nr; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; - unsigned vtxelt_nr; - struct nv50_sampler_stateobj *sampler[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; - unsigned sampler_nr[PIPE_SHADER_TYPES]; - struct nv50_miptree *miptree[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; - unsigned miptree_nr[PIPE_SHADER_TYPES]; + struct nv50_vtxelt_stateobj *vtxelt; + struct nv50_sampler_stateobj *sampler[3][PIPE_MAX_SAMPLERS]; + unsigned sampler_nr[3]; + struct pipe_sampler_view *sampler_views[3][PIPE_MAX_SAMPLERS]; + unsigned sampler_view_nr[3]; - uint16_t vbo_fifo; + unsigned vbo_fifo; }; static INLINE struct nv50_context * @@ -186,6 +186,7 @@ nv50_context(struct pipe_context *pipe) extern void nv50_init_surface_functions(struct nv50_context *nv50); extern void nv50_init_state_functions(struct nv50_context *nv50); extern void nv50_init_query_functions(struct nv50_context *nv50); +extern void nv50_init_transfer_functions(struct nv50_context *nv50); extern void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen); @@ -216,24 +217,36 @@ extern void nv50_draw_elements_instanced(struct pipe_context *pipe, unsigned count, unsigned startInstance, unsigned instanceCount); -extern void nv50_vbo_validate(struct nv50_context *nv50); +extern void nv50_vtxelt_construct(struct nv50_vtxelt_stateobj *cso); +extern struct nouveau_stateobj *nv50_vbo_validate(struct nv50_context *nv50); + +/* nv50_push.c */ +extern void +nv50_push_elements_instanced(struct pipe_context *, struct pipe_buffer *, + unsigned idxsize, unsigned mode, unsigned start, + unsigned count, unsigned i_start, + unsigned i_count); /* nv50_clear.c */ extern void nv50_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil); /* nv50_program.c */ -extern void nv50_vertprog_validate(struct nv50_context *nv50); -extern void nv50_fragprog_validate(struct nv50_context *nv50); -extern void nv50_geomprog_validate(struct nv50_context *nv50); -extern void nv50_fp_linkage_validate(struct nv50_context *nv50); -extern void nv50_gp_linkage_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_vertprog_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_fragprog_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_geomprog_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_fp_linkage_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_gp_linkage_validate(struct nv50_context *nv50); extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p); /* nv50_state_validate.c */ -extern boolean nv50_state_validate(struct nv50_context *nv50); -extern void nv50_state_flush_notify(struct nouveau_channel *chan); +extern boolean nv50_state_validate(struct nv50_context *nv50, unsigned dwords); extern void nv50_so_init_sifc(struct nv50_context *nv50, struct nouveau_stateobj *so, @@ -241,7 +254,9 @@ extern void nv50_so_init_sifc(struct nv50_context *nv50, unsigned offset, unsigned size); /* nv50_tex.c */ -extern void nv50_tex_validate(struct nv50_context *); +extern boolean nv50_tex_construct(struct nv50_sampler_view *view); +extern void nv50_tex_relocs(struct nv50_context *); +extern struct nouveau_stateobj *nv50_tex_validate(struct nv50_context *); /* nv50_transfer.c */ extern void @@ -255,4 +270,35 @@ nv50_upload_sifc(struct nv50_context *nv50, struct pipe_context * nv50_create(struct pipe_screen *pscreen, void *priv); +static INLINE unsigned +nv50_prim(unsigned mode) +{ + switch (mode) { + case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS; + case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES; + case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP; + case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP; + case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES; + case PIPE_PRIM_TRIANGLE_STRIP: + return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP; + case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN; + case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS; + case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP; + case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON; + case PIPE_PRIM_LINES_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY; + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY; + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY; + default: + break; + } + + NOUVEAU_ERR("invalid primitive type %d\n", mode); + return NV50TCL_VERTEX_BEGIN_POINTS; +} + #endif diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index 3f9d869d7a4..e091cae6024 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -104,7 +104,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) tile_flags = 0x7400; break; default: - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) && + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) && util_format_get_blocksizebits(pt->format) == 32) tile_flags = 0x7a00; else @@ -255,9 +255,10 @@ void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen) { pscreen->texture_create = nv50_miptree_create; - pscreen->texture_blanket = nv50_miptree_blanket; pscreen->texture_destroy = nv50_miptree_destroy; pscreen->get_tex_surface = nv50_miptree_surface_new; pscreen->tex_surface_destroy = nv50_miptree_surface_del; + + nouveau_screen(pscreen)->texture_blanket = nv50_miptree_blanket; } diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 2372cbbef69..c857816b31a 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -4270,7 +4270,7 @@ nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) FREE(up); } -void +struct nouveau_stateobj * nv50_vertprog_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4286,6 +4286,9 @@ nv50_vertprog_validate(struct nv50_context *nv50) nv50_program_validate_data(nv50, p); nv50_program_validate_code(nv50, p); + if (!(nv50->dirty & NV50_NEW_VERTPROG)) + return NULL; + so = so_new(5, 7, 2); so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | @@ -4301,11 +4304,10 @@ nv50_vertprog_validate(struct nv50_context *nv50) so_data (so, p->cfg.high_temp); so_method(so, tesla, NV50TCL_VP_START_ID, 1); so_data (so, 0); /* program start offset */ - so_ref(so, &nv50->state.vertprog); - so_ref(NULL, &so); + return so; } -void +struct nouveau_stateobj * nv50_fragprog_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4321,6 +4323,9 @@ nv50_fragprog_validate(struct nv50_context *nv50) nv50_program_validate_data(nv50, p); nv50_program_validate_code(nv50, p); + if (!(nv50->dirty & NV50_NEW_FRAGPROG)) + return NULL; + so = so_new(6, 7, 2); so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | @@ -4337,11 +4342,10 @@ nv50_fragprog_validate(struct nv50_context *nv50) so_data (so, p->cfg.regs[3]); so_method(so, tesla, NV50TCL_FP_START_ID, 1); so_data (so, 0); /* program start offset */ - so_ref(so, &nv50->state.fragprog); - so_ref(NULL, &so); + return so; } -void +struct nouveau_stateobj * nv50_geomprog_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4357,6 +4361,9 @@ nv50_geomprog_validate(struct nv50_context *nv50) nv50_program_validate_data(nv50, p); nv50_program_validate_code(nv50, p); + if (!(nv50->dirty & NV50_NEW_GEOMPROG)) + return NULL; + so = so_new(6, 7, 2); so_method(so, tesla, NV50TCL_GP_ADDRESS_HIGH, 2); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | @@ -4373,8 +4380,7 @@ nv50_geomprog_validate(struct nv50_context *nv50) so_data (so, p->cfg.vert_count); so_method(so, tesla, NV50TCL_GP_START_ID, 1); so_data (so, 0); - so_ref(so, &nv50->state.geomprog); - so_ref(NULL, &so); + return so; } static uint32_t @@ -4454,7 +4460,7 @@ nv50_vec4_map(uint32_t *map32, int mid, uint8_t zval, uint32_t lin[4], return mid; } -void +struct nouveau_stateobj * nv50_fp_linkage_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4580,8 +4586,7 @@ nv50_fp_linkage_validate(struct nv50_context *nv50) so_method(so, tesla, NV50TCL_GP_ENABLE, 1); so_data (so, (vp->type == PIPE_SHADER_GEOMETRY) ? 1 : 0); - so_ref(so, &nv50->state.fp_linkage); - so_ref(NULL, &so); + return so; } static int @@ -4615,7 +4620,7 @@ construct_vp_gp_mapping(uint32_t *map32, int m, return m; } -void +struct nouveau_stateobj * nv50_gp_linkage_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4625,10 +4630,8 @@ nv50_gp_linkage_validate(struct nv50_context *nv50) uint32_t map[16]; int m = 0; - if (!gp) { - so_ref(NULL, &nv50->state.gp_linkage); - return; - } + if (!gp) + return NULL; memset(map, 0, sizeof(map)); m = construct_vp_gp_mapping(map, m, vp, gp); @@ -4646,8 +4649,7 @@ nv50_gp_linkage_validate(struct nv50_context *nv50) so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), m); so_datap (so, map, m); - so_ref(so, &nv50->state.gp_linkage); - so_ref(NULL, &so); + return so; } void diff --git a/src/gallium/drivers/nv50/nv50_push.c b/src/gallium/drivers/nv50/nv50_push.c new file mode 100644 index 00000000000..96a1f32d304 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_push.c @@ -0,0 +1,326 @@ +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/u_inlines.h" +#include "util/u_format.h" + +#include "nouveau/nouveau_util.h" +#include "nv50_context.h" + +struct push_context { + struct nv50_context *nv50; + + unsigned vtx_size; + + void *idxbuf; + unsigned idxsize; + + float edgeflag; + int edgeflag_attr; + + struct { + void *map; + unsigned stride; + unsigned divisor; + unsigned step; + void (*push)(struct nouveau_channel *, void *); + } attr[16]; + unsigned attr_nr; +}; + +static void +emit_b32_1(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); +} + +static void +emit_b32_2(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); + OUT_RING(chan, v[1]); +} + +static void +emit_b32_3(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); + OUT_RING(chan, v[1]); + OUT_RING(chan, v[2]); +} + +static void +emit_b32_4(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); + OUT_RING(chan, v[1]); + OUT_RING(chan, v[2]); + OUT_RING(chan, v[3]); +} + +static void +emit_b16_1(struct nouveau_channel *chan, void *data) +{ + uint16_t *v = data; + + OUT_RING(chan, v[0]); +} + +static void +emit_b16_3(struct nouveau_channel *chan, void *data) +{ + uint16_t *v = data; + + OUT_RING(chan, (v[1] << 16) | v[0]); + OUT_RING(chan, v[2]); +} + +static void +emit_b08_1(struct nouveau_channel *chan, void *data) +{ + uint8_t *v = data; + + OUT_RING(chan, v[0]); +} + +static void +emit_b08_3(struct nouveau_channel *chan, void *data) +{ + uint8_t *v = data; + + OUT_RING(chan, (v[2] << 16) | (v[1] << 8) | v[0]); +} + +static INLINE void +emit_vertex(struct push_context *ctx, unsigned n) +{ + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + int i; + + if (ctx->edgeflag_attr < 16) { + float *edgeflag = ctx->attr[ctx->edgeflag_attr].map + + ctx->attr[ctx->edgeflag_attr].stride * n; + + if (*edgeflag != ctx->edgeflag) { + BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (chan, *edgeflag ? 1 : 0); + ctx->edgeflag = *edgeflag; + } + } + + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, ctx->vtx_size); + for (i = 0; i < ctx->attr_nr; i++) + ctx->attr[i].push(chan, ctx->attr[i].map + ctx->attr[i].stride * n); +} + +static void +emit_edgeflag(void *priv, boolean enabled) +{ + struct push_context *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + + BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (chan, enabled ? 1 : 0); +} + +static void +emit_elt08(void *priv, unsigned start, unsigned count) +{ + struct push_context *ctx = priv; + uint8_t *idxbuf = ctx->idxbuf; + + while (count--) + emit_vertex(ctx, idxbuf[start++]); +} + +static void +emit_elt16(void *priv, unsigned start, unsigned count) +{ + struct push_context *ctx = priv; + uint16_t *idxbuf = ctx->idxbuf; + + while (count--) + emit_vertex(ctx, idxbuf[start++]); +} + +static void +emit_elt32(void *priv, unsigned start, unsigned count) +{ + struct push_context *ctx = priv; + uint32_t *idxbuf = ctx->idxbuf; + + while (count--) + emit_vertex(ctx, idxbuf[start++]); +} + +static void +emit_verts(void *priv, unsigned start, unsigned count) +{ + while (count--) + emit_vertex(priv, start++); +} + +void +nv50_push_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *idxbuf, unsigned idxsize, + unsigned mode, unsigned start, unsigned count, + unsigned i_start, unsigned i_count) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct push_context ctx; + const unsigned p_overhead = 4 + /* begin/end */ + 4; /* potential edgeflag enable/disable */ + const unsigned v_overhead = 1 + /* VERTEX_DATA packet header */ + 2; /* potential edgeflag modification */ + struct u_split_prim s; + unsigned vtx_size; + boolean nzi = FALSE; + int i; + + ctx.nv50 = nv50; + ctx.attr_nr = 0; + ctx.idxbuf = NULL; + ctx.vtx_size = 0; + ctx.edgeflag = 0.5f; + ctx.edgeflag_attr = nv50->vertprog->cfg.edgeflag_in; + + /* map vertex buffers, determine vertex size */ + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; + struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; + struct nouveau_bo *bo = nouveau_bo(vb->buffer); + unsigned size, nr_components, n; + + if (!(nv50->vbo_fifo & (1 << i))) + continue; + n = ctx.attr_nr++; + + if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) { + assert(bo->map); + return; + } + ctx.attr[n].map = bo->map + vb->buffer_offset + ve->src_offset; + nouveau_bo_unmap(bo); + + ctx.attr[n].stride = vb->stride; + ctx.attr[n].divisor = ve->instance_divisor; + if (ctx.attr[n].divisor) { + ctx.attr[n].step = i_start % ve->instance_divisor; + ctx.attr[n].map += i_start * vb->stride; + } + + size = util_format_get_component_bits(ve->src_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + nr_components = util_format_get_nr_components(ve->src_format); + switch (size) { + case 8: + switch (nr_components) { + case 1: ctx.attr[n].push = emit_b08_1; break; + case 2: ctx.attr[n].push = emit_b16_1; break; + case 3: ctx.attr[n].push = emit_b08_3; break; + case 4: ctx.attr[n].push = emit_b32_1; break; + } + ctx.vtx_size++; + break; + case 16: + switch (nr_components) { + case 1: ctx.attr[n].push = emit_b16_1; break; + case 2: ctx.attr[n].push = emit_b32_1; break; + case 3: ctx.attr[n].push = emit_b16_3; break; + case 4: ctx.attr[n].push = emit_b32_2; break; + } + ctx.vtx_size += (nr_components + 1) >> 1; + break; + case 32: + switch (nr_components) { + case 1: ctx.attr[n].push = emit_b32_1; break; + case 2: ctx.attr[n].push = emit_b32_2; break; + case 3: ctx.attr[n].push = emit_b32_3; break; + case 4: ctx.attr[n].push = emit_b32_4; break; + } + ctx.vtx_size += nr_components; + break; + default: + assert(0); + return; + } + } + vtx_size = ctx.vtx_size + v_overhead; + + /* map index buffer, if present */ + if (idxbuf) { + struct nouveau_bo *bo = nouveau_bo(idxbuf); + + if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) { + assert(bo->map); + return; + } + ctx.idxbuf = bo->map; + ctx.idxsize = idxsize; + nouveau_bo_unmap(bo); + } + + s.priv = &ctx; + s.edge = emit_edgeflag; + if (idxbuf) { + if (idxsize == 1) + s.emit = emit_elt08; + else + if (idxsize == 2) + s.emit = emit_elt16; + else + s.emit = emit_elt32; + } else + s.emit = emit_verts; + + /* per-instance loop */ + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, i_start); + while (i_count--) { + unsigned max_verts; + boolean done; + + for (i = 0; i < ctx.attr_nr; i++) { + if (!ctx.attr[i].divisor || + ctx.attr[i].divisor != ++ctx.attr[i].step) + continue; + ctx.attr[i].step = 0; + ctx.attr[i].map += ctx.attr[i].stride; + } + + u_split_prim_init(&s, mode, start, count); + do { + if (AVAIL_RING(chan) < p_overhead + (6 * vtx_size)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, p_overhead + (6 * vtx_size))) { + assert(0); + return; + } + } + + max_verts = AVAIL_RING(chan); + max_verts -= p_overhead; + max_verts /= vtx_size; + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(s.mode) | (nzi ? (1 << 28) : 0)); + done = u_split_prim_next(&s, max_verts); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } while (!done); + + nzi = TRUE; + } +} diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index eed6031eafa..d7f5863fb71 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -95,6 +95,8 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, static int nv50_screen_get_param(struct pipe_screen *pscreen, int param) { + struct nv50_screen *screen = nv50_screen(pscreen); + switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: return 32; @@ -132,9 +134,9 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; case NOUVEAU_CAP_HW_VTXBUF: - return 1; + return screen->force_push ? 0 : 1; case NOUVEAU_CAP_HW_IDXBUF: - return 1; + return screen->force_push ? 0 : 1; case PIPE_CAP_INDEP_BLEND_ENABLE: return 1; case PIPE_CAP_INDEP_BLEND_FUNC: @@ -202,28 +204,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen) FREE(screen); } -static int -nv50_pre_pipebuffer_map(struct pipe_screen *pscreen, struct pipe_buffer *pb, - unsigned usage) -{ - struct nv50_screen *screen = nv50_screen(pscreen); - struct nv50_context *ctx = screen->cur_ctx; - - if (!(pb->usage & PIPE_BUFFER_USAGE_VERTEX)) - return 0; - - /* Our vtxbuf got mapped, it can no longer be considered part of current - * state, remove it to avoid emitting reloc markers. - */ - if (ctx && ctx->state.vtxbuf && so_bo_is_reloc(ctx->state.vtxbuf, - nouveau_bo(pb))) { - so_ref(NULL, &ctx->state.vtxbuf); - ctx->dirty |= NV50_NEW_ARRAYS; - } - - return 0; -} - struct pipe_screen * nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { @@ -252,10 +232,8 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->get_paramf = nv50_screen_get_paramf; pscreen->is_format_supported = nv50_screen_is_format_supported; pscreen->context_create = nv50_create; - screen->base.pre_pipebuffer_map_callback = nv50_pre_pipebuffer_map; nv50_screen_init_miptree_functions(pscreen); - nv50_transfer_init_screen_functions(pscreen); /* DMA engine object */ ret = nouveau_grobj_alloc(chan, 0xbeef5039, @@ -464,7 +442,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); so_data (so, 0x00000131 | (NV50_CB_PFP << 12)); - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32, + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4), &screen->tic); if (ret) { nv50_screen_destroy(pscreen); @@ -476,9 +454,9 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, PIPE_SHADER_TYPES * 32 - 1); + so_data (so, 3 * 32 - 1); - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, PIPE_SHADER_TYPES*32*32, + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4), &screen->tsc); if (ret) { nv50_screen_destroy(pscreen); @@ -508,10 +486,6 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_method(so, screen->tesla, NV50TCL_LINKED_TSC, 1); so_data (so, 1); - /* activate first scissor rectangle */ - so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE(0), 1); - so_data (so, 1); - so_method(so, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1); so_data (so, 1); /* default edgeflag to TRUE */ @@ -520,6 +494,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_ref (NULL, &so); nouveau_pushbuf_flush(chan, 0); + screen->force_push = debug_get_bool_option("NV50_ALWAYS_PUSH", FALSE); return pscreen; } diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 2687b721277..ec19ea655b1 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -28,6 +28,8 @@ struct nv50_screen { struct nouveau_bo *tsc; struct nouveau_stateobj *static_init; + + boolean force_push; }; static INLINE struct nv50_screen * @@ -36,6 +38,4 @@ nv50_screen(struct pipe_screen *screen) return (struct nv50_screen *)screen; } -void nv50_transfer_init_screen_functions(struct pipe_screen *); - #endif diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 7d304907b65..c1628089285 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -238,6 +238,9 @@ nv50_sampler_state_create(struct pipe_context *pipe, return (void *)sso; } +/* type == 0 for VPs, 1 for GPs, 2 for FPs, which is how the + * relevant tesla methods are indexed (NV50TCL_BIND_TSC etc.) + */ static INLINE void nv50_sampler_state_bind(struct pipe_context *pipe, unsigned type, unsigned nr, void **sampler) @@ -253,13 +256,13 @@ nv50_sampler_state_bind(struct pipe_context *pipe, unsigned type, static void nv50_vp_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **s) { - nv50_sampler_state_bind(pipe, PIPE_SHADER_VERTEX, nr, s); + nv50_sampler_state_bind(pipe, 0, nr, s); } static void nv50_fp_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **s) { - nv50_sampler_state_bind(pipe, PIPE_SHADER_FRAGMENT, nr, s); + nv50_sampler_state_bind(pipe, 2, nr, s); } static void @@ -269,40 +272,74 @@ nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso) } static INLINE void -nv50_set_sampler_texture(struct pipe_context *pipe, unsigned type, - unsigned nr, struct pipe_texture **pt) +nv50_set_sampler_views(struct pipe_context *pipe, unsigned p, + unsigned nr, + struct pipe_sampler_view **views) { struct nv50_context *nv50 = nv50_context(pipe); unsigned i; for (i = 0; i < nr; i++) - pipe_texture_reference((void *)&nv50->miptree[type][i], pt[i]); - for (i = nr; i < nv50->miptree_nr[type]; i++) - pipe_texture_reference((void *)&nv50->miptree[type][i], NULL); + pipe_sampler_view_reference(&nv50->sampler_views[p][i], + views[i]); + + for (i = nr; i < nv50->sampler_view_nr[p]; i++) + pipe_sampler_view_reference(&nv50->sampler_views[p][i], NULL); - nv50->miptree_nr[type] = nr; + nv50->sampler_view_nr[p] = nr; nv50->dirty |= NV50_NEW_TEXTURE; } static void -nv50_set_vp_sampler_textures(struct pipe_context *pipe, - unsigned nr, struct pipe_texture **pt) +nv50_set_vp_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) { - nv50_set_sampler_texture(pipe, PIPE_SHADER_VERTEX, nr, pt); + nv50_set_sampler_views(pipe, 0, nr, views); } static void -nv50_set_fp_sampler_textures(struct pipe_context *pipe, - unsigned nr, struct pipe_texture **pt) +nv50_set_fp_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) +{ + nv50_set_sampler_views(pipe, 2, nr, views); +} + +static void +nv50_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(nv50_sampler_view(view)); +} + +static struct pipe_sampler_view * +nv50_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) { - nv50_set_sampler_texture(pipe, PIPE_SHADER_FRAGMENT, nr, pt); + struct nv50_sampler_view *view = CALLOC_STRUCT(nv50_sampler_view); + + view->pipe = *templ; + view->pipe.reference.count = 1; + view->pipe.texture = NULL; + pipe_texture_reference(&view->pipe.texture, texture); + view->pipe.context = pipe; + + if (!nv50_tex_construct(view)) { + nv50_sampler_view_destroy(pipe, &view->pipe); + return NULL; + } + return &view->pipe; } + static void * nv50_rasterizer_state_create(struct pipe_context *pipe, const struct pipe_rasterizer_state *cso) { - struct nouveau_stateobj *so = so_new(15, 21, 0); + struct nouveau_stateobj *so = so_new(16, 22, 0); struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla; struct nv50_rasterizer_stateobj *rso = CALLOC_STRUCT(nv50_rasterizer_stateobj); @@ -314,6 +351,9 @@ nv50_rasterizer_state_create(struct pipe_context *pipe, * - point_sprite / sprite_coord_mode */ + so_method(so, tesla, NV50TCL_SCISSOR_ENABLE(0), 1); + so_data (so, cso->scissor); + so_method(so, tesla, NV50TCL_SHADE_MODEL, 1); so_data (so, cso->flatshade ? NV50TCL_SHADE_MODEL_FLAT : NV50TCL_SHADE_MODEL_SMOOTH); @@ -720,15 +760,34 @@ nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count, nv50->dirty |= NV50_NEW_ARRAYS; } +static void * +nv50_vtxelts_state_create(struct pipe_context *pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct nv50_vtxelt_stateobj *cso = CALLOC_STRUCT(nv50_vtxelt_stateobj); + + assert(num_elements < 16); /* not doing fallbacks yet */ + cso->num_elements = num_elements; + memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); + + nv50_vtxelt_construct(cso); + + return (void *)cso; +} + static void -nv50_set_vertex_elements(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_element *ve) +nv50_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) { - struct nv50_context *nv50 = nv50_context(pipe); + FREE(hwcso); +} - memcpy(nv50->vtxelt, ve, sizeof(*ve) * count); - nv50->vtxelt_nr = count; +static void +nv50_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nv50_context *nv50 = nv50_context(pipe); + nv50->vtxelt = hwcso; nv50->dirty |= NV50_NEW_ARRAYS; } @@ -743,8 +802,10 @@ nv50_init_state_functions(struct nv50_context *nv50) nv50->pipe.delete_sampler_state = nv50_sampler_state_delete; nv50->pipe.bind_fragment_sampler_states = nv50_fp_sampler_state_bind; nv50->pipe.bind_vertex_sampler_states = nv50_vp_sampler_state_bind; - nv50->pipe.set_fragment_sampler_textures = nv50_set_fp_sampler_textures; - nv50->pipe.set_vertex_sampler_textures = nv50_set_vp_sampler_textures; + nv50->pipe.set_fragment_sampler_views = nv50_set_fp_sampler_views; + nv50->pipe.set_vertex_sampler_views = nv50_set_vp_sampler_views; + nv50->pipe.create_sampler_view = nv50_create_sampler_view; + nv50->pipe.sampler_view_destroy = nv50_sampler_view_destroy; nv50->pipe.create_rasterizer_state = nv50_rasterizer_state_create; nv50->pipe.bind_rasterizer_state = nv50_rasterizer_state_bind; @@ -778,7 +839,10 @@ nv50_init_state_functions(struct nv50_context *nv50) nv50->pipe.set_scissor_state = nv50_set_scissor_state; nv50->pipe.set_viewport_state = nv50_set_viewport_state; + nv50->pipe.create_vertex_elements_state = nv50_vtxelts_state_create; + nv50->pipe.delete_vertex_elements_state = nv50_vtxelts_state_delete; + nv50->pipe.bind_vertex_elements_state = nv50_vtxelts_state_bind; + nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers; - nv50->pipe.set_vertex_elements = nv50_set_vertex_elements; } diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index c974cc92dcc..63d73b5ce83 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -25,8 +25,8 @@ #include "nv50_context.h" #include "nouveau/nouveau_stateobj.h" -static void -nv50_state_validate_fb(struct nv50_context *nv50) +static struct nouveau_stateobj * +validate_fb(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; struct nouveau_stateobj *so = so_new(32, 79, 18); @@ -167,12 +167,7 @@ nv50_state_validate_fb(struct nv50_context *nv50) so_data (so, w << 16); so_data (so, h << 16); - /* we set scissors to framebuffer size when they're 'turned off' */ - nv50->dirty |= NV50_NEW_SCISSOR; - so_ref(NULL, &nv50->state.scissor); - - so_ref(so, &nv50->state.fb); - so_ref(NULL, &so); + return so; } static void @@ -199,263 +194,254 @@ nv50_validate_samplers(struct nv50_context *nv50, struct nouveau_stateobj *so, } } -static void -nv50_state_emit(struct nv50_context *nv50) +static struct nouveau_stateobj * +validate_blend(struct nv50_context *nv50) { - struct nv50_screen *screen = nv50->screen; - struct nouveau_channel *chan = screen->base.channel; + struct nouveau_stateobj *so = NULL; + so_ref(nv50->blend->so, &so); + return so; +} - /* XXX: this is racy for multiple contexts active on separate - * threads. - */ - if (screen->cur_ctx != nv50) { - if (nv50->state.fb) - nv50->state.dirty |= NV50_NEW_FRAMEBUFFER; - if (nv50->state.blend) - nv50->state.dirty |= NV50_NEW_BLEND; - if (nv50->state.zsa) - nv50->state.dirty |= NV50_NEW_ZSA; - if (nv50->state.vertprog) - nv50->state.dirty |= NV50_NEW_VERTPROG; - if (nv50->state.fragprog) - nv50->state.dirty |= NV50_NEW_FRAGPROG; - if (nv50->state.geomprog) - nv50->state.dirty |= NV50_NEW_GEOMPROG; - if (nv50->state.rast) - nv50->state.dirty |= NV50_NEW_RASTERIZER; - if (nv50->state.blend_colour) - nv50->state.dirty |= NV50_NEW_BLEND_COLOUR; - if (nv50->state.stencil_ref) - nv50->state.dirty |= NV50_NEW_STENCIL_REF; - if (nv50->state.stipple) - nv50->state.dirty |= NV50_NEW_STIPPLE; - if (nv50->state.scissor) - nv50->state.dirty |= NV50_NEW_SCISSOR; - if (nv50->state.viewport) - nv50->state.dirty |= NV50_NEW_VIEWPORT; - if (nv50->state.tsc_upload) - nv50->state.dirty |= NV50_NEW_SAMPLER; - if (nv50->state.tic_upload) - nv50->state.dirty |= NV50_NEW_TEXTURE; - if (nv50->state.vtxfmt && nv50->state.vtxbuf) - nv50->state.dirty |= NV50_NEW_ARRAYS; - screen->cur_ctx = nv50; - } +static struct nouveau_stateobj * +validate_zsa(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->zsa->so, &so); + return so; +} - if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER) - so_emit(chan, nv50->state.fb); - if (nv50->state.dirty & NV50_NEW_BLEND) - so_emit(chan, nv50->state.blend); - if (nv50->state.dirty & NV50_NEW_ZSA) - so_emit(chan, nv50->state.zsa); - if (nv50->state.dirty & NV50_NEW_VERTPROG) - so_emit(chan, nv50->state.vertprog); - if (nv50->state.dirty & NV50_NEW_FRAGPROG) - so_emit(chan, nv50->state.fragprog); - if (nv50->state.dirty & NV50_NEW_GEOMPROG && nv50->state.geomprog) - so_emit(chan, nv50->state.geomprog); - if (nv50->state.dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | - NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER)) - so_emit(chan, nv50->state.fp_linkage); - if ((nv50->state.dirty & (NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG)) - && nv50->state.gp_linkage) - so_emit(chan, nv50->state.gp_linkage); - if (nv50->state.dirty & NV50_NEW_RASTERIZER) - so_emit(chan, nv50->state.rast); - if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR) - so_emit(chan, nv50->state.blend_colour); - if (nv50->state.dirty & NV50_NEW_STENCIL_REF) - so_emit(chan, nv50->state.stencil_ref); - if (nv50->state.dirty & NV50_NEW_STIPPLE) - so_emit(chan, nv50->state.stipple); - if (nv50->state.dirty & NV50_NEW_SCISSOR) - so_emit(chan, nv50->state.scissor); - if (nv50->state.dirty & NV50_NEW_VIEWPORT) - so_emit(chan, nv50->state.viewport); - if (nv50->state.dirty & NV50_NEW_SAMPLER) - so_emit(chan, nv50->state.tsc_upload); - if (nv50->state.dirty & NV50_NEW_TEXTURE) - so_emit(chan, nv50->state.tic_upload); - if (nv50->state.dirty & NV50_NEW_ARRAYS) { - so_emit(chan, nv50->state.vtxfmt); - so_emit(chan, nv50->state.vtxbuf); - if (nv50->state.vtxattr) - so_emit(chan, nv50->state.vtxattr); - } - nv50->state.dirty = 0; +static struct nouveau_stateobj * +validate_rast(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->rasterizer->so, &so); + return so; } -void -nv50_state_flush_notify(struct nouveau_channel *chan) +static struct nouveau_stateobj * +validate_blend_colour(struct nv50_context *nv50) { - struct nv50_context *nv50 = chan->user_private; + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so_new(1, 4, 0); + + so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4); + so_data (so, fui(nv50->blend_colour.color[0])); + so_data (so, fui(nv50->blend_colour.color[1])); + so_data (so, fui(nv50->blend_colour.color[2])); + so_data (so, fui(nv50->blend_colour.color[3])); + return so; +} - if (nv50->state.tic_upload && !(nv50->dirty & NV50_NEW_TEXTURE)) - so_emit(chan, nv50->state.tic_upload); +static struct nouveau_stateobj * +validate_stencil_ref(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so = so_new(2, 2, 0); - so_emit_reloc_markers(chan, nv50->state.fb); - so_emit_reloc_markers(chan, nv50->state.vertprog); - so_emit_reloc_markers(chan, nv50->state.fragprog); - so_emit_reloc_markers(chan, nv50->state.vtxbuf); - so_emit_reloc_markers(chan, nv50->screen->static_init); + so_method(so, tesla, NV50TCL_STENCIL_FRONT_FUNC_REF, 1); + so_data (so, nv50->stencil_ref.ref_value[0]); + so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 1); + so_data (so, nv50->stencil_ref.ref_value[1]); + return so; +} - if (nv50->state.instbuf) - so_emit_reloc_markers(chan, nv50->state.instbuf); +static struct nouveau_stateobj * +validate_stipple(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so_new(1, 32, 0); + int i; + + so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32); + for (i = 0; i < 32; i++) + so_data(so, util_bswap32(nv50->stipple.stipple[i])); + return so; } -boolean -nv50_state_validate(struct nv50_context *nv50) +static struct nouveau_stateobj * +validate_scissor(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; + struct pipe_scissor_state *s = &nv50->scissor; struct nouveau_stateobj *so; - unsigned i; - if (nv50->dirty & NV50_NEW_FRAMEBUFFER) - nv50_state_validate_fb(nv50); + so = so_new(1, 2, 0); + so_method(so, tesla, NV50TCL_SCISSOR_HORIZ(0), 2); + so_data (so, (s->maxx << 16) | s->minx); + so_data (so, (s->maxy << 16) | s->miny); + return so; +} + +static struct nouveau_stateobj * +validate_viewport(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so_new(5, 9, 0); + + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE_X(0), 3); + so_data (so, fui(nv50->viewport.translate[0])); + so_data (so, fui(nv50->viewport.translate[1])); + so_data (so, fui(nv50->viewport.translate[2])); + so_method(so, tesla, NV50TCL_VIEWPORT_SCALE_X(0), 3); + so_data (so, fui(nv50->viewport.scale[0])); + so_data (so, fui(nv50->viewport.scale[1])); + so_data (so, fui(nv50->viewport.scale[2])); + + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); + so_data (so, 1); + /* 0x0000 = remove whole primitive only (xyz) + * 0x1018 = remove whole primitive only (xy), clamp z + * 0x1080 = clip primitive (xyz) + * 0x1098 = clip primitive (xy), clamp z + */ + so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); + so_data (so, 0x1080); + /* no idea what 0f90 does */ + so_method(so, tesla, 0x0f90, 1); + so_data (so, 0); + + return so; +} - if (nv50->dirty & NV50_NEW_BLEND) - so_ref(nv50->blend->so, &nv50->state.blend); +static struct nouveau_stateobj * +validate_sampler(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so; + unsigned nr = 0, i; - if (nv50->dirty & NV50_NEW_ZSA) - so_ref(nv50->zsa->so, &nv50->state.zsa); + for (i = 0; i < 3; ++i) + nr += nv50->sampler_nr[i]; - if (nv50->dirty & (NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB)) - nv50_vertprog_validate(nv50); + so = so_new(1 + 5 * 3, 1 + 19 * 3 + nr * 8, 3 * 2); - if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB)) - nv50_fragprog_validate(nv50); + nv50_validate_samplers(nv50, so, 0); /* VP */ + nv50_validate_samplers(nv50, so, 2); /* FP */ - if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB)) - nv50_geomprog_validate(nv50); + so_method(so, tesla, 0x1334, 1); /* flush TSC */ + so_data (so, 0); - if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | - NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER)) - nv50_fp_linkage_validate(nv50); + return so; +} - if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_VERTPROG)) - nv50_gp_linkage_validate(nv50); +static struct nouveau_stateobj * +validate_vtxbuf(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->state.vtxbuf, &so); + return so; +} - if (nv50->dirty & NV50_NEW_RASTERIZER) - so_ref(nv50->rasterizer->so, &nv50->state.rast); +static struct nouveau_stateobj * +validate_vtxattr(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->state.vtxattr, &so); + return so; +} - if (nv50->dirty & NV50_NEW_BLEND_COLOUR) { - so = so_new(1, 4, 0); - so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4); - so_data (so, fui(nv50->blend_colour.color[0])); - so_data (so, fui(nv50->blend_colour.color[1])); - so_data (so, fui(nv50->blend_colour.color[2])); - so_data (so, fui(nv50->blend_colour.color[3])); - so_ref(so, &nv50->state.blend_colour); - so_ref(NULL, &so); - } +struct state_validate { + struct nouveau_stateobj *(*func)(struct nv50_context *nv50); + unsigned states; +} validate_list[] = { + { validate_fb , NV50_NEW_FRAMEBUFFER }, + { validate_blend , NV50_NEW_BLEND }, + { validate_zsa , NV50_NEW_ZSA }, + { nv50_vertprog_validate , NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB }, + { nv50_fragprog_validate , NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB }, + { nv50_geomprog_validate , NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB }, + { nv50_fp_linkage_validate, NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG | + NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER }, + { nv50_gp_linkage_validate, NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG }, + { validate_rast , NV50_NEW_RASTERIZER }, + { validate_blend_colour , NV50_NEW_BLEND_COLOUR }, + { validate_stencil_ref , NV50_NEW_STENCIL_REF }, + { validate_stipple , NV50_NEW_STIPPLE }, + { validate_scissor , NV50_NEW_SCISSOR }, + { validate_viewport , NV50_NEW_VIEWPORT }, + { validate_sampler , NV50_NEW_SAMPLER }, + { nv50_tex_validate , NV50_NEW_TEXTURE | NV50_NEW_SAMPLER }, + { nv50_vbo_validate , NV50_NEW_ARRAYS }, + { validate_vtxbuf , NV50_NEW_ARRAYS }, + { validate_vtxattr , NV50_NEW_ARRAYS }, + {} +}; +#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0])) - if (nv50->dirty & NV50_NEW_STENCIL_REF) { - so = so_new(2, 2, 0); - so_method(so, tesla, NV50TCL_STENCIL_FRONT_FUNC_REF, 1); - so_data (so, nv50->stencil_ref.ref_value[0]); - so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 1); - so_data (so, nv50->stencil_ref.ref_value[1]); - so_ref(so, &nv50->state.stencil_ref); - so_ref(NULL, &so); - } +boolean +nv50_state_validate(struct nv50_context *nv50, unsigned wait_dwords) +{ + struct nouveau_channel *chan = nv50->screen->base.channel; + struct nouveau_grobj *tesla = nv50->screen->tesla; + unsigned nr_relocs = 128, nr_dwords = wait_dwords + 128 + 4; + int ret, i; - if (nv50->dirty & NV50_NEW_STIPPLE) { - so = so_new(1, 32, 0); - so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32); - for (i = 0; i < 32; i++) - so_data(so, util_bswap32(nv50->stipple.stipple[i])); - so_ref(so, &nv50->state.stipple); - so_ref(NULL, &so); - } + for (i = 0; i < validate_list_len; i++) { + struct state_validate *validate = &validate_list[i]; + struct nouveau_stateobj *so; - if (nv50->dirty & (NV50_NEW_SCISSOR | NV50_NEW_RASTERIZER)) { - struct pipe_rasterizer_state *rast = &nv50->rasterizer->pipe; - struct pipe_scissor_state *s = &nv50->scissor; + if (!(nv50->dirty & validate->states)) + continue; - if (nv50->state.scissor && - (rast->scissor == 0 && nv50->state.scissor_enabled == 0)) - goto scissor_uptodate; - nv50->state.scissor_enabled = rast->scissor; + so = validate->func(nv50); + if (!so) + continue; - so = so_new(1, 2, 0); - so_method(so, tesla, NV50TCL_SCISSOR_HORIZ(0), 2); - if (nv50->state.scissor_enabled) { - so_data(so, (s->maxx << 16) | s->minx); - so_data(so, (s->maxy << 16) | s->miny); - } else { - so_data(so, (nv50->framebuffer.width << 16)); - so_data(so, (nv50->framebuffer.height << 16)); - } - so_ref(so, &nv50->state.scissor); - so_ref(NULL, &so); - nv50->state.dirty |= NV50_NEW_SCISSOR; - } -scissor_uptodate: - - if (nv50->dirty & (NV50_NEW_VIEWPORT | NV50_NEW_RASTERIZER)) { - if (nv50->state.viewport && - !(nv50->dirty & NV50_NEW_VIEWPORT)) - goto viewport_uptodate; - - so = so_new(5, 9, 0); - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE_X(0), 3); - so_data (so, fui(nv50->viewport.translate[0])); - so_data (so, fui(nv50->viewport.translate[1])); - so_data (so, fui(nv50->viewport.translate[2])); - so_method(so, tesla, NV50TCL_VIEWPORT_SCALE_X(0), 3); - so_data (so, fui(nv50->viewport.scale[0])); - so_data (so, fui(nv50->viewport.scale[1])); - so_data (so, fui(nv50->viewport.scale[2])); - - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); - so_data (so, 1); - /* 0x0000 = remove whole primitive only (xyz) - * 0x1018 = remove whole primitive only (xy), clamp z - * 0x1080 = clip primitive (xyz) - * 0x1098 = clip primitive (xy), clamp z - */ - so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); - so_data (so, 0x1080); - /* no idea what 0f90 does */ - so_method(so, tesla, 0x0f90, 1); - so_data (so, 0); + nr_dwords += (so->total + so->cur); + nr_relocs += so->cur_reloc; - so_ref(so, &nv50->state.viewport); + so_ref(so, &nv50->state.hw[i]); so_ref(NULL, &so); - nv50->state.dirty |= NV50_NEW_VIEWPORT; + nv50->state.hw_dirty |= (1 << i); } -viewport_uptodate: - - if (nv50->dirty & NV50_NEW_SAMPLER) { - unsigned nr = 0; - - for (i = 0; i < PIPE_SHADER_TYPES; ++i) - nr += nv50->sampler_nr[i]; + nv50->dirty = 0; - so = so_new(1 + 5 * PIPE_SHADER_TYPES, - 1 + 19 * PIPE_SHADER_TYPES + nr * 8, - PIPE_SHADER_TYPES * 2); + if (nv50->screen->cur_ctx != nv50) { + for (i = 0; i < validate_list_len; i++) { + if (!nv50->state.hw[i] || + (nv50->state.hw_dirty & (1 << i))) + continue; - nv50_validate_samplers(nv50, so, PIPE_SHADER_VERTEX); - nv50_validate_samplers(nv50, so, PIPE_SHADER_FRAGMENT); + nr_dwords += (nv50->state.hw[i]->total + + nv50->state.hw[i]->cur); + nr_relocs += nv50->state.hw[i]->cur_reloc; + nv50->state.hw_dirty |= (1 << i); + } - so_method(so, tesla, 0x1334, 1); /* flush TSC */ - so_data (so, 0); + nv50->screen->cur_ctx = nv50; + } - so_ref(so, &nv50->state.tsc_upload); - so_ref(NULL, &so); + ret = MARK_RING(chan, nr_dwords, nr_relocs); + if (ret) { + debug_printf("MARK_RING(%d, %d) failed: %d\n", + nr_dwords, nr_relocs, ret); + return FALSE; } - if (nv50->dirty & (NV50_NEW_TEXTURE | NV50_NEW_SAMPLER)) - nv50_tex_validate(nv50); + while (nv50->state.hw_dirty) { + i = ffs(nv50->state.hw_dirty) - 1; + nv50->state.hw_dirty &= ~(1 << i); - if (nv50->dirty & NV50_NEW_ARRAYS) - nv50_vbo_validate(nv50); + so_emit(chan, nv50->state.hw[i]); + } - nv50->state.dirty |= nv50->dirty; - nv50->dirty = 0; - nv50_state_emit(nv50); + /* Yes, really, we need to do this. If a buffer that is referenced + * on the hardware isn't part of changed state above, without doing + * this the kernel is given no clue that the buffer is being used + * still. This can cause all sorts of fun issues. + */ + nv50_tex_relocs(nv50); + so_emit_reloc_markers(chan, nv50->state.hw[0]); /* fb */ + so_emit_reloc_markers(chan, nv50->state.hw[3]); /* vp */ + so_emit_reloc_markers(chan, nv50->state.hw[4]); /* fp */ + so_emit_reloc_markers(chan, nv50->state.hw[17]); /* vb */ + so_emit_reloc_markers(chan, nv50->screen->static_init); + /* No idea.. */ + BEGIN_RING(chan, tesla, 0x142c, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, tesla, 0x142c, 1); + OUT_RING (chan, 0); return TRUE; } diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index cabd148bc5b..6467c48a32a 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -28,6 +28,7 @@ #include "util/u_inlines.h" #include "util/u_tile.h" +#include "util/u_format.h" static INLINE int nv50_format(enum pipe_format format) @@ -37,10 +38,35 @@ nv50_format(enum pipe_format format) return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM; case PIPE_FORMAT_B8G8R8X8_UNORM: return NV50_2D_DST_FORMAT_X8R8G8B8_UNORM; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return NV50_2D_DST_FORMAT_A8R8G8B8_SRGB; + case PIPE_FORMAT_B8G8R8X8_SRGB: + return NV50_2D_DST_FORMAT_X8R8G8B8_SRGB; case PIPE_FORMAT_B5G6R5_UNORM: return NV50_2D_DST_FORMAT_R5G6B5_UNORM; + case PIPE_FORMAT_B5G5R5A1_UNORM: + return NV50_2D_DST_FORMAT_A1R5G5B5_UNORM; case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8_UNORM: return NV50_2D_DST_FORMAT_R8_UNORM; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return NV50_2D_DST_FORMAT_R32G32B32A32_FLOAT; + case PIPE_FORMAT_R32G32B32_FLOAT: + return NV50_2D_DST_FORMAT_R32G32B32X32_FLOAT; + case PIPE_FORMAT_Z32_FLOAT: + return NV50_2D_DST_FORMAT_R32_FLOAT; + + /* only because we require src format == dst format: */ + case PIPE_FORMAT_R16G16_SNORM: + case PIPE_FORMAT_R16G16_UNORM: + case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_Z24S8_UNORM: + return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM; + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_B4G4R4A4_UNORM: + return NV50_2D_DST_FORMAT_R16_UNORM; + default: return -1; } @@ -57,8 +83,11 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD); format = nv50_format(ps->format); - if (format < 0) + if (format < 0) { + NOUVEAU_ERR("invalid/unsupported surface format: %s\n", + util_format_name(ps->format)); return 1; + } if (!bo->tile_flags) { MARK_RING (chan, 9, 2); /* flush on lack of space or relocs */ diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index de0560e20cd..85ab947c006 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -24,30 +24,21 @@ #include "nv50_texture.h" #include "nouveau/nouveau_stateobj.h" +#include "nouveau/nouveau_reloc.h" #include "util/u_format.h" #define _MIXED(pf, t0, t1, t2, t3, cr, cg, cb, ca, f) \ -{ \ - PIPE_FORMAT_##pf, \ +[PIPE_FORMAT_##pf] = ( \ NV50TIC_0_0_MAPR_##cr | NV50TIC_0_0_TYPER_##t0 | \ NV50TIC_0_0_MAPG_##cg | NV50TIC_0_0_TYPEG_##t1 | \ NV50TIC_0_0_MAPB_##cb | NV50TIC_0_0_TYPEB_##t2 | \ NV50TIC_0_0_MAPA_##ca | NV50TIC_0_0_TYPEA_##t3 | \ - NV50TIC_0_0_FMT_##f \ -} + NV50TIC_0_0_FMT_##f) #define _(pf, t, cr, cg, cb, ca, f) _MIXED(pf, t, t, t, t, cr, cg, cb, ca, f) -struct nv50_texture_format { - enum pipe_format pf; - uint32_t hw; -}; - -#define NV50_TEX_FORMAT_LIST_SIZE \ - (sizeof(nv50_tex_format_list) / sizeof(struct nv50_texture_format)) - -static const struct nv50_texture_format nv50_tex_format_list[] = +static const uint32_t nv50_texture_formats[PIPE_FORMAT_COUNT] = { _(B8G8R8A8_UNORM, UNORM, C2, C1, C0, C3, 8_8_8_8), _(B8G8R8A8_SRGB, UNORM, C2, C1, C0, C3, 8_8_8_8), @@ -59,10 +50,12 @@ static const struct nv50_texture_format nv50_tex_format_list[] = _(B5G6R5_UNORM, UNORM, C2, C1, C0, ONE, 5_6_5), _(L8_UNORM, UNORM, C0, C0, C0, ONE, 8), + _(L8_SRGB, UNORM, C0, C0, C0, ONE, 8), _(A8_UNORM, UNORM, ZERO, ZERO, ZERO, C0, 8), _(I8_UNORM, UNORM, C0, C0, C0, C0, 8), _(L8A8_UNORM, UNORM, C0, C0, C0, C1, 8_8), + _(L8A8_SRGB, UNORM, C0, C0, C0, C1, 8_8), _(DXT1_RGB, UNORM, C0, C1, C2, ONE, DXT1), _(DXT1_RGBA, UNORM, C0, C1, C2, C3, DXT1), @@ -80,149 +73,207 @@ static const struct nv50_texture_format nv50_tex_format_list[] = _(R16G16_UNORM, UNORM, C0, C1, ZERO, ONE, 16_16), _MIXED(Z32_FLOAT, FLOAT, UINT, UINT, UINT, C0, C0, C0, ONE, 32_DEPTH) - }; #undef _ #undef _MIXED -static int -nv50_tex_construct(struct nv50_context *nv50, struct nouveau_stateobj *so, - struct nv50_miptree *mt, int unit, unsigned p) +static INLINE uint32_t +nv50_tic_swizzle(uint32_t tc, unsigned swz) +{ + switch (swz) { + case PIPE_SWIZZLE_RED: + return (tc & NV50TIC_0_0_MAPR_MASK) >> NV50TIC_0_0_MAPR_SHIFT; + case PIPE_SWIZZLE_GREEN: + return (tc & NV50TIC_0_0_MAPG_MASK) >> NV50TIC_0_0_MAPG_SHIFT; + case PIPE_SWIZZLE_BLUE: + return (tc & NV50TIC_0_0_MAPB_MASK) >> NV50TIC_0_0_MAPB_SHIFT; + case PIPE_SWIZZLE_ALPHA: + return (tc & NV50TIC_0_0_MAPA_MASK) >> NV50TIC_0_0_MAPA_SHIFT; + case PIPE_SWIZZLE_ONE: + return 7; + case PIPE_SWIZZLE_ZERO: + default: + return 0; + } +} + +boolean +nv50_tex_construct(struct nv50_sampler_view *view) { - unsigned i; - uint32_t mode; const struct util_format_description *desc; + struct nv50_miptree *mt = nv50_miptree(view->pipe.texture); + uint32_t swz[4], *tic = view->tic; - for (i = 0; i < NV50_TEX_FORMAT_LIST_SIZE; i++) - if (nv50_tex_format_list[i].pf == mt->base.base.format) - break; - if (i == NV50_TEX_FORMAT_LIST_SIZE) - return 1; - - if (nv50->sampler[p][unit]->normalized) - mode = 0x50001000 | (1 << 31); - else { - mode = 0x50001000 | (7 << 14); - assert(mt->base.base.target == PIPE_TEXTURE_2D); - } + tic[0] = nv50_texture_formats[view->pipe.format]; - mode |= ((mt->base.bo->tile_mode & 0x0f) << 22) | - ((mt->base.bo->tile_mode & 0xf0) << 21); + swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r); + swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g); + swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b); + swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a); + view->tic[0] = (tic[0] & ~NV50TIC_0_0_SWIZZLE_MASK) | + (swz[0] << NV50TIC_0_0_MAPR_SHIFT) | + (swz[1] << NV50TIC_0_0_MAPG_SHIFT) | + (swz[2] << NV50TIC_0_0_MAPB_SHIFT) | + (swz[3] << NV50TIC_0_0_MAPA_SHIFT); - desc = util_format_description(mt->base.base.format); - assert(desc); + tic[2] = 0x50001000; + tic[2] |= ((mt->base.bo->tile_mode & 0x0f) << 22) | + ((mt->base.bo->tile_mode & 0xf0) << 21); + desc = util_format_description(mt->base.base.format); if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) - mode |= 0x0400; + tic[2] |= NV50TIC_0_2_COLORSPACE_SRGB; switch (mt->base.base.target) { case PIPE_TEXTURE_1D: + tic[2] |= NV50TIC_0_2_TARGET_1D; break; case PIPE_TEXTURE_2D: - mode |= (1 << 14); + tic[2] |= NV50TIC_0_2_TARGET_2D; break; case PIPE_TEXTURE_3D: - mode |= (2 << 14); + tic[2] |= NV50TIC_0_2_TARGET_3D; break; case PIPE_TEXTURE_CUBE: - mode |= (3 << 14); + tic[2] |= NV50TIC_0_2_TARGET_CUBE; break; default: - assert(!"unsupported texture target"); - break; + NOUVEAU_ERR("invalid texture target: %d\n", + mt->base.base.target); + return FALSE; } - so_data (so, nv50_tex_format_list[i].hw); - so_reloc(so, mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | - NOUVEAU_BO_RD, 0, 0); - so_data (so, mode); - so_data (so, 0x00300000); - so_data (so, mt->base.base.width0 | (1 << 31)); - so_data (so, (mt->base.base.last_level << 28) | - (mt->base.base.depth0 << 16) | mt->base.base.height0); - so_data (so, 0x03000000); - so_data (so, mt->base.base.last_level << 4); - - return 0; -} + tic[3] = 0x00300000; + + tic[4] = (1 << 31) | mt->base.base.width0; + tic[5] = (mt->base.base.last_level << 28) | + (mt->base.base.depth0 << 16) | mt->base.base.height0; -#ifndef NV50TCL_BIND_TIC -#define NV50TCL_BIND_TIC(n) (0x1448 + 8 * n) -#endif + tic[6] = 0x03000000; -static boolean + tic[7] = (view->pipe.last_level << 4) | view->pipe.first_level; + + return TRUE; +} + +static int nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so, unsigned p) { - static const unsigned p_remap[PIPE_SHADER_TYPES] = { 0, 2, 1 }; - struct nouveau_grobj *eng2d = nv50->screen->eng2d; struct nouveau_grobj *tesla = nv50->screen->tesla; - unsigned unit, j, p_hw = p_remap[p]; + unsigned unit, j; + + const unsigned rll = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW; + const unsigned rlh = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH + | NOUVEAU_BO_OR; nv50_so_init_sifc(nv50, so, nv50->screen->tic, NOUVEAU_BO_VRAM, - p * (32 * 8 * 4), nv50->miptree_nr[p] * 8 * 4); + p * (32 * 8 * 4), nv50->sampler_view_nr[p] * 8 * 4); - for (unit = 0; unit < nv50->miptree_nr[p]; ++unit) { - struct nv50_miptree *mt = nv50->miptree[p][unit]; + for (unit = 0; unit < nv50->sampler_view_nr[p]; ++unit) { + struct nv50_sampler_view *view = + nv50_sampler_view(nv50->sampler_views[p][unit]); so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8); - if (mt) { - if (nv50_tex_construct(nv50, so, mt, unit, p)) - return FALSE; + if (view) { + uint32_t tic2 = view->tic[2]; + struct nv50_miptree *mt = + nv50_miptree(view->pipe.texture); + + if (nv50->sampler[p][unit]->normalized) + tic2 |= NV50TIC_0_2_NORMALIZED_COORDS; + + so_data (so, view->tic[0]); + so_reloc (so, mt->base.bo, 0, rll, 0, 0); + so_reloc (so, mt->base.bo, 0, rlh, tic2, tic2); + so_datap (so, &view->tic[3], 5); + /* Set TEX insn $t src binding $unit in program type p * to TIC, TSC entry (32 * p + unit), mark valid (1). */ - so_method(so, tesla, NV50TCL_BIND_TIC(p_hw), 1); + so_method(so, tesla, NV50TCL_BIND_TIC(p), 1); so_data (so, ((32 * p + unit) << 9) | (unit << 1) | 1); } else { for (j = 0; j < 8; ++j) so_data(so, 0); - so_method(so, tesla, NV50TCL_BIND_TIC(p_hw), 1); + so_method(so, tesla, NV50TCL_BIND_TIC(p), 1); so_data (so, (unit << 1) | 0); } } - for (; unit < nv50->state.miptree_nr[p]; unit++) { + for (; unit < nv50->state.sampler_view_nr[p]; unit++) { /* Make other bindings invalid. */ - so_method(so, tesla, NV50TCL_BIND_TIC(p_hw), 1); + so_method(so, tesla, NV50TCL_BIND_TIC(p), 1); so_data (so, (unit << 1) | 0); } - nv50->state.miptree_nr[p] = nv50->miptree_nr[p]; + nv50->state.sampler_view_nr[p] = nv50->sampler_view_nr[p]; return TRUE; } void +nv50_tex_relocs(struct nv50_context *nv50) +{ + struct nouveau_channel *chan = nv50->screen->tesla->channel; + int p, unit; + + p = PIPE_SHADER_FRAGMENT; + for (unit = 0; unit < nv50->sampler_view_nr[p]; unit++) { + struct pipe_sampler_view *view = nv50->sampler_views[p][unit]; + if (!view) + continue; + nouveau_reloc_emit(chan, nv50->screen->tic, + ((p * 32) + unit) * 32, NULL, + nv50_miptree(view->texture)->base.bo, 0, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | + NOUVEAU_BO_RD, 0, 0); + } + + p = PIPE_SHADER_VERTEX; + for (unit = 0; unit < nv50->sampler_view_nr[p]; unit++) { + struct pipe_sampler_view *view = nv50->sampler_views[p][unit]; + if (!view) + continue; + nouveau_reloc_emit(chan, nv50->screen->tic, + ((p * 32) + unit) * 32, NULL, + nv50_miptree(view->texture)->base.bo, 0, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | + NOUVEAU_BO_RD, 0, 0); + } +} + +struct nouveau_stateobj * nv50_tex_validate(struct nv50_context *nv50) { struct nouveau_stateobj *so; struct nouveau_grobj *tesla = nv50->screen->tesla; - unsigned p, start, push, nrlc; - - for (nrlc = 0, start = 0, push = 0, p = 0; p < PIPE_SHADER_TYPES; ++p) { - start += MAX2(nv50->miptree_nr[p], nv50->state.miptree_nr[p]); - push += MAX2(nv50->miptree_nr[p], nv50->state.miptree_nr[p]); - nrlc += nv50->miptree_nr[p]; + unsigned p, m = 0, d = 0, r = 0; + + for (p = 0; p < 3; ++p) { + unsigned nr = MAX2(nv50->sampler_view_nr[p], + nv50->state.sampler_view_nr[p]); + m += nr; + d += nr; + r += nv50->sampler_view_nr[p]; } - start = start * 2 + 4 * PIPE_SHADER_TYPES + 2; - push = push * 9 + 19 * PIPE_SHADER_TYPES + 2; - nrlc = nrlc * 2 + 2 * PIPE_SHADER_TYPES; + m = m * 2 + 3 * 4 + 1; + d = d * 9 + 3 * 19 + 1; + r = r * 2 + 3 * 2; - so = so_new(start, push, nrlc); + so = so_new(m, d, r); - if (nv50_validate_textures(nv50, so, PIPE_SHADER_VERTEX) == FALSE || - nv50_validate_textures(nv50, so, PIPE_SHADER_FRAGMENT) == FALSE) { + if (nv50_validate_textures(nv50, so, 0) == FALSE || + nv50_validate_textures(nv50, so, 2) == FALSE) { so_ref(NULL, &so); NOUVEAU_ERR("failed tex validate\n"); - return; + return NULL; } so_method(so, tesla, 0x1330, 1); /* flush TIC */ so_data (so, 0); - so_ref(so, &nv50->state.tic_upload); - so_ref(NULL, &so); + return so; } diff --git a/src/gallium/drivers/nv50/nv50_texture.h b/src/gallium/drivers/nv50/nv50_texture.h index b870302019a..3475d3e4326 100644 --- a/src/gallium/drivers/nv50/nv50_texture.h +++ b/src/gallium/drivers/nv50/nv50_texture.h @@ -7,7 +7,9 @@ */ /* Texture image control block */ +#define NV50TIC_0_0_SWIZZLE_MASK 0x3ffc0000 #define NV50TIC_0_0_MAPA_MASK 0x38000000 +#define NV50TIC_0_0_MAPA_SHIFT 27 #define NV50TIC_0_0_MAPA_ZERO 0x00000000 #define NV50TIC_0_0_MAPA_C0 0x10000000 #define NV50TIC_0_0_MAPA_C1 0x18000000 @@ -15,6 +17,7 @@ #define NV50TIC_0_0_MAPA_C3 0x28000000 #define NV50TIC_0_0_MAPA_ONE 0x38000000 #define NV50TIC_0_0_MAPB_MASK 0x07000000 +#define NV50TIC_0_0_MAPB_SHIFT 24 #define NV50TIC_0_0_MAPB_ZERO 0x00000000 #define NV50TIC_0_0_MAPB_C0 0x02000000 #define NV50TIC_0_0_MAPB_C1 0x03000000 @@ -22,6 +25,7 @@ #define NV50TIC_0_0_MAPB_C3 0x05000000 #define NV50TIC_0_0_MAPB_ONE 0x07000000 #define NV50TIC_0_0_MAPG_MASK 0x00e00000 +#define NV50TIC_0_0_MAPG_SHIFT 21 #define NV50TIC_0_0_MAPG_ZERO 0x00000000 #define NV50TIC_0_0_MAPG_C0 0x00400000 #define NV50TIC_0_0_MAPG_C1 0x00600000 @@ -29,6 +33,7 @@ #define NV50TIC_0_0_MAPG_C3 0x00a00000 #define NV50TIC_0_0_MAPG_ONE 0x00e00000 #define NV50TIC_0_0_MAPR_MASK 0x001c0000 +#define NV50TIC_0_0_MAPR_SHIFT 18 #define NV50TIC_0_0_MAPR_ZERO 0x00000000 #define NV50TIC_0_0_MAPR_C0 0x00080000 #define NV50TIC_0_0_MAPR_C1 0x000c0000 @@ -89,22 +94,39 @@ #define NV50TIC_0_1_OFFSET_LOW_MASK 0xffffffff #define NV50TIC_0_1_OFFSET_LOW_SHIFT 0 -#define NV50TIC_0_2_UNKNOWN_MASK 0xffffffff +#define NV50TIC_0_2_COLORSPACE_SRGB 0x00000400 +#define NV50TIC_0_2_TARGET_1D 0x00000000 +#define NV50TIC_0_2_TARGET_2D 0x00004000 +#define NV50TIC_0_2_TARGET_3D 0x00008000 +#define NV50TIC_0_2_TARGET_CUBE 0x0000c000 +#define NV50TIC_0_2_TARGET_1D_ARRAY 0x00010000 +#define NV50TIC_0_2_TARGET_2D_ARRAY 0x00014000 +#define NV50TIC_0_2_TARGET_BUFFER 0x00018000 +#define NV50TIC_0_2_TARGET_RECT 0x0001c000 +/* #define NV50TIC_0_0_TILE_MODE_LINEAR 0x00040000 */ +#define NV50TIC_0_2_TILE_MODE_Y_MASK 0x01c00000 +#define NV50TIC_0_2_TILE_MODE_Y_SHIFT 22 +#define NV50TIC_0_2_TILE_MODE_Z_MASK 0x0e000000 +#define NV50TIC_0_2_TILE_MODE_Z_SHIFT 25 +#define NV50TIC_0_2_NORMALIZED_COORDS 0x80000000 #define NV50TIC_0_3_UNKNOWN_MASK 0xffffffff #define NV50TIC_0_4_WIDTH_MASK 0x0000ffff #define NV50TIC_0_4_WIDTH_SHIFT 0 -#define NV50TIC_0_5_DEPTH_MASK 0xffff0000 +#define NV50TIC_0_5_LAST_LEVEL_MASK 0xf0000000 +#define NV50TIC_0_5_LAST_LEVEL_SHIFT 28 +#define NV50TIC_0_5_DEPTH_MASK 0x0fff0000 #define NV50TIC_0_5_DEPTH_SHIFT 16 #define NV50TIC_0_5_HEIGHT_MASK 0x0000ffff #define NV50TIC_0_5_HEIGHT_SHIFT 0 - #define NV50TIC_0_6_UNKNOWN_MASK 0xffffffff -#define NV50TIC_0_7_OFFSET_HIGH_MASK 0xffffffff -#define NV50TIC_0_7_OFFSET_HIGH_SHIFT 0 +#define NV50TIC_0_7_BASE_LEVEL_MASK 0x0000000f +#define NV50TIC_0_7_BASE_LEVEL_SHIFT 0 +#define NV50TIC_0_7_MAX_LEVEL_MASK 0x000000f0 +#define NV50TIC_0_7_MAX_LEVEL_SHIFT 4 /* Texture sampler control block */ #define NV50TSC_1_0_WRAPS_MASK 0x00000007 diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index 7c360e9e73a..9eb223eca65 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -121,11 +121,12 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, } static struct pipe_transfer * -nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +nv50_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, unsigned w, unsigned h) { + struct pipe_screen *pscreen = pcontext->screen; struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = nv50_miptree(pt); struct nv50_miptree_level *lvl = &mt->level[level]; @@ -186,7 +187,7 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, } static void -nv50_transfer_del(struct pipe_transfer *ptx) +nv50_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; struct nv50_miptree *mt = nv50_miptree(ptx->texture); @@ -196,7 +197,7 @@ nv50_transfer_del(struct pipe_transfer *ptx) unsigned ny = util_format_get_nblocksy(pt->format, tx->base.height); if (ptx->usage & PIPE_TRANSFER_WRITE) { - struct pipe_screen *pscreen = pt->screen; + struct pipe_screen *pscreen = pcontext->screen; nv50_transfer_rect_m2mf(pscreen, tx->bo, 0, tx->base.stride, tx->bo->tile_mode, @@ -218,7 +219,7 @@ nv50_transfer_del(struct pipe_transfer *ptx) } static void * -nv50_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv50_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; unsigned flags = 0; @@ -236,7 +237,7 @@ nv50_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } static void -nv50_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv50_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; @@ -244,12 +245,12 @@ nv50_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } void -nv50_transfer_init_screen_functions(struct pipe_screen *pscreen) +nv50_init_transfer_functions(struct nv50_context *nv50) { - pscreen->get_tex_transfer = nv50_transfer_new; - pscreen->tex_transfer_destroy = nv50_transfer_del; - pscreen->transfer_map = nv50_transfer_map; - pscreen->transfer_unmap = nv50_transfer_unmap; + nv50->pipe.get_tex_transfer = nv50_transfer_new; + nv50->pipe.tex_transfer_destroy = nv50_transfer_del; + nv50->pipe.transfer_map = nv50_transfer_map; + nv50->pipe.transfer_unmap = nv50_transfer_unmap; } void diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 1c8ee0b9adf..50472868063 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -25,53 +25,9 @@ #include "util/u_inlines.h" #include "util/u_format.h" +#include "nouveau/nouveau_util.h" #include "nv50_context.h" -static boolean -nv50_push_elements_u08(struct nv50_context *, uint8_t *, unsigned); - -static boolean -nv50_push_elements_u16(struct nv50_context *, uint16_t *, unsigned); - -static boolean -nv50_push_elements_u32(struct nv50_context *, uint32_t *, unsigned); - -static boolean -nv50_push_arrays(struct nv50_context *, unsigned, unsigned); - -#define NV50_USING_LOATHED_EDGEFLAG(ctx) ((ctx)->vertprog->cfg.edgeflag_in < 16) - -static INLINE unsigned -nv50_prim(unsigned mode) -{ - switch (mode) { - case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS; - case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES; - case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP; - case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP; - case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES; - case PIPE_PRIM_TRIANGLE_STRIP: - return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP; - case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN; - case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS; - case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP; - case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON; - case PIPE_PRIM_LINES_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY; - case PIPE_PRIM_LINE_STRIP_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY; - case PIPE_PRIM_TRIANGLES_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY; - case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY; - default: - break; - } - - NOUVEAU_ERR("invalid primitive type %d\n", mode); - return NV50TCL_VERTEX_BEGIN_POINTS; -} - static INLINE uint32_t nv50_vbo_type_to_hw(enum pipe_format format) { @@ -139,15 +95,16 @@ nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) uint32_t hw_type, hw_size; enum pipe_format pf = ve->src_format; const struct util_format_description *desc; - unsigned size; + unsigned size, nr_components; desc = util_format_description(pf); assert(desc); size = util_format_get_component_bits(pf, UTIL_FORMAT_COLORSPACE_RGB, 0); + nr_components = util_format_get_nr_components(pf); hw_type = nv50_vbo_type_to_hw(pf); - hw_size = nv50_vbo_size_to_hw(size, ve->nr_components); + hw_size = nv50_vbo_size_to_hw(size, nr_components); if (!hw_type || !hw_size) { NOUVEAU_ERR("unsupported vbo format: %s\n", util_format_name(pf)); @@ -161,250 +118,58 @@ nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) return (hw_type | hw_size); } -/* For instanced drawing from user buffers, hitting the FIFO repeatedly - * with the same vertex data is probably worse than uploading all data. - */ -static boolean -nv50_upload_vtxbuf(struct nv50_context *nv50, unsigned i) -{ - struct nv50_screen *nscreen = nv50->screen; - struct pipe_screen *pscreen = &nscreen->base.base; - struct pipe_buffer *buf = nscreen->strm_vbuf[i]; - struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; - uint8_t *src; - unsigned size = align(vb->buffer->size, 4096); - - if (buf && buf->size < size) - pipe_buffer_reference(&nscreen->strm_vbuf[i], NULL); - - if (!nscreen->strm_vbuf[i]) { - nscreen->strm_vbuf[i] = pipe_buffer_create( - pscreen, 0, PIPE_BUFFER_USAGE_VERTEX, size); - buf = nscreen->strm_vbuf[i]; - } - - src = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); - if (!src) - return FALSE; - src += vb->buffer_offset; - - size = (vb->max_index + 1) * vb->stride + 16; /* + 16 is for stride 0 */ - if (vb->buffer_offset + size > vb->buffer->size) - size = vb->buffer->size - vb->buffer_offset; - - pipe_buffer_write(pscreen, buf, vb->buffer_offset, size, src); - pipe_buffer_unmap(pscreen, vb->buffer); - - vb->buffer = buf; /* don't pipe_reference, this is a private copy */ - return TRUE; -} - -static void -nv50_upload_user_vbufs(struct nv50_context *nv50) -{ - unsigned i; - - if (nv50->vbo_fifo) - nv50->dirty |= NV50_NEW_ARRAYS; - if (!(nv50->dirty & NV50_NEW_ARRAYS)) - return; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) { - if (nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX) - continue; - nv50_upload_vtxbuf(nv50, i); - } -} - -static void -nv50_set_static_vtxattr(struct nv50_context *nv50, unsigned i, void *data) -{ - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; - float v[4]; - - util_format_read_4f(nv50->vtxelt[i].src_format, - v, 0, data, 0, 0, 0, 1, 1); - - switch (nv50->vtxelt[i].nr_components) { - case 4: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_4F_X(i), 4); - OUT_RINGf (chan, v[0]); - OUT_RINGf (chan, v[1]); - OUT_RINGf (chan, v[2]); - OUT_RINGf (chan, v[3]); - break; - case 3: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_3F_X(i), 3); - OUT_RINGf (chan, v[0]); - OUT_RINGf (chan, v[1]); - OUT_RINGf (chan, v[2]); - break; - case 2: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_2F_X(i), 2); - OUT_RINGf (chan, v[0]); - OUT_RINGf (chan, v[1]); - break; - case 1: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_1F(i), 1); - OUT_RINGf (chan, v[0]); - break; - default: - assert(0); - break; - } -} - -static unsigned -init_per_instance_arrays_immd(struct nv50_context *nv50, - unsigned startInstance, - unsigned pos[16], unsigned step[16]) -{ - struct nouveau_bo *bo; - unsigned i, b, count = 0; - - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) - continue; - ++count; - b = nv50->vtxelt[i].vertex_buffer_index; - - pos[i] = nv50->vtxelt[i].src_offset + - nv50->vtxbuf[b].buffer_offset + - startInstance * nv50->vtxbuf[b].stride; - step[i] = startInstance % nv50->vtxelt[i].instance_divisor; - - bo = nouveau_bo(nv50->vtxbuf[b].buffer); - if (!bo->map) - nouveau_bo_map(bo, NOUVEAU_BO_RD); - - nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); - } - - return count; -} - -static unsigned -init_per_instance_arrays(struct nv50_context *nv50, - unsigned startInstance, - unsigned pos[16], unsigned step[16]) -{ - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; +struct instance { struct nouveau_bo *bo; - struct nouveau_stateobj *so; - unsigned i, b, count = 0; - const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - - if (nv50->vbo_fifo) - return init_per_instance_arrays_immd(nv50, startInstance, - pos, step); - - so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); - - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) - continue; - ++count; - b = nv50->vtxelt[i].vertex_buffer_index; - - pos[i] = nv50->vtxelt[i].src_offset + - nv50->vtxbuf[b].buffer_offset + - startInstance * nv50->vtxbuf[b].stride; - - if (!startInstance) { - step[i] = 0; - continue; - } - step[i] = startInstance % nv50->vtxelt[i].instance_divisor; - - bo = nouveau_bo(nv50->vtxbuf[b].buffer); - - so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); - } - - if (count && startInstance) { - so_ref (so, &nv50->state.instbuf); /* for flush notify */ - so_emit(chan, nv50->state.instbuf); - } - so_ref (NULL, &so); - - return count; -} + unsigned delta; + unsigned stride; + unsigned step; + unsigned divisor; +}; static void -step_per_instance_arrays_immd(struct nv50_context *nv50, - unsigned pos[16], unsigned step[16]) +instance_init(struct nv50_context *nv50, struct instance *a, unsigned first) { - struct nouveau_bo *bo; - unsigned i, b; + int i; - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) - continue; - if (++step[i] != nv50->vtxelt[i].instance_divisor) - continue; - b = nv50->vtxelt[i].vertex_buffer_index; - bo = nouveau_bo(nv50->vtxbuf[b].buffer); + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; + struct pipe_vertex_buffer *vb; - step[i] = 0; - pos[i] += nv50->vtxbuf[b].stride; + a[i].divisor = ve->instance_divisor; + if (a[i].divisor) { + vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); + a[i].bo = nouveau_bo(vb->buffer); + a[i].stride = vb->stride; + a[i].step = first % a[i].divisor; + a[i].delta = vb->buffer_offset + ve->src_offset + + (first * a[i].stride); + } } } static void -step_per_instance_arrays(struct nv50_context *nv50, - unsigned pos[16], unsigned step[16]) +instance_step(struct nv50_context *nv50, struct instance *a) { + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; - struct nouveau_bo *bo; - struct nouveau_stateobj *so; - unsigned i, b; - const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - - if (nv50->vbo_fifo) { - step_per_instance_arrays_immd(nv50, pos, step); - return; - } - - so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); + int i; - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + if (!a[i].divisor) continue; - b = nv50->vtxelt[i].vertex_buffer_index; - if (++step[i] == nv50->vtxelt[i].instance_divisor) { - step[i] = 0; - pos[i] += nv50->vtxbuf[b].stride; + BEGIN_RING(chan, tesla, + NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); + OUT_RELOCh(chan, a[i].bo, a[i].delta, NOUVEAU_BO_RD | + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART); + OUT_RELOCl(chan, a[i].bo, a[i].delta, NOUVEAU_BO_RD | + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART); + if (++a[i].step == a[i].divisor) { + a[i].step = 0; + a[i].delta += a[i].stride; } - - bo = nouveau_bo(nv50->vtxbuf[b].buffer); - - so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); } - - so_ref (so, &nv50->state.instbuf); /* for flush notify */ - so_ref (NULL, &so); - - so_emit(chan, nv50->state.instbuf); -} - -static INLINE void -nv50_unmap_vbufs(struct nv50_context *nv50) -{ - unsigned i; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) - if (nouveau_bo(nv50->vtxbuf[i].buffer)->map) - nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); } void @@ -415,198 +180,207 @@ nv50_draw_arrays_instanced(struct pipe_context *pipe, struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - unsigned i, nz_divisors; - unsigned step[16], pos[16]; - - if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) - nv50_upload_user_vbufs(nv50); + struct instance a[16]; + unsigned prim = nv50_prim(mode); - nv50_state_validate(nv50); + instance_init(nv50, a, startInstance); + if (!nv50_state_validate(nv50, 10 + 16*3)) + return; - nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + if (nv50->vbo_fifo) { + nv50_push_elements_instanced(pipe, NULL, 0, mode, start, + count, startInstance, + instanceCount); + return; + } BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); OUT_RING (chan, NV50_CB_AUX | (24 << 8)); OUT_RING (chan, startInstance); + while (instanceCount--) { + if (AVAIL_RING(chan) < (7 + 16*3)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, 7 + 16*3)) { + assert(0); + return; + } + } + instance_step(nv50, a); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - if (nv50->vbo_fifo) - nv50_push_arrays(nv50, start, count); - else { + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, prim); BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); OUT_RING (chan, start); OUT_RING (chan, count); - } - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); - - for (i = 1; i < instanceCount; i++) { - if (nz_divisors) /* any non-zero array divisors ? */ - step_per_instance_arrays(nv50, pos, step); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode) | (1 << 28)); - - if (nv50->vbo_fifo) - nv50_push_arrays(nv50, start, count); - else { - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); - OUT_RING (chan, start); - OUT_RING (chan, count); - } BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); - } - nv50_unmap_vbufs(nv50); - so_ref(NULL, &nv50->state.instbuf); + prim |= (1 << 28); + } } void nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { - struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - boolean ret; - - nv50_state_validate(nv50); - - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - if (nv50->vbo_fifo) - ret = nv50_push_arrays(nv50, start, count); - else { - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); - OUT_RING (chan, start); - OUT_RING (chan, count); - ret = TRUE; - } - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); - - nv50_unmap_vbufs(nv50); - - /* XXX: not sure what to do if ret != TRUE: flush and retry? - */ - assert(ret); + nv50_draw_arrays_instanced(pipe, mode, start, count, 0, 1); } -static INLINE boolean -nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map, - unsigned start, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - - map += start; +struct inline_ctx { + struct nv50_context *nv50; + void *map; +}; - if (nv50->vbo_fifo) - return nv50_push_elements_u08(nv50, map, count); +static void +inline_elt08(void *priv, unsigned start, unsigned count) +{ + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + uint8_t *map = (uint8_t *)ctx->map + start; if (count & 1) { BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, map[0]); map++; - count--; + count &= ~1; } - while (count) { - unsigned nr = count > 2046 ? 2046 : count; - int i; - - BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); - for (i = 0; i < nr; i += 2) - OUT_RING (chan, (map[i + 1] << 16) | map[i]); + count >>= 1; + if (!count) + return; - count -= nr; - map += nr; + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, count); + while (count--) { + OUT_RING(chan, (map[1] << 16) | map[0]); + map += 2; } - return TRUE; } -static INLINE boolean -nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map, - unsigned start, unsigned count) +static void +inline_elt16(void *priv, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - - map += start; - - if (nv50->vbo_fifo) - return nv50_push_elements_u16(nv50, map, count); + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + uint16_t *map = (uint16_t *)ctx->map + start; if (count & 1) { BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, map[0]); + count &= ~1; map++; - count--; } - while (count) { - unsigned nr = count > 2046 ? 2046 : count; - int i; - - BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); - for (i = 0; i < nr; i += 2) - OUT_RING (chan, (map[i + 1] << 16) | map[i]); + count >>= 1; + if (!count) + return; - count -= nr; - map += nr; + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, count); + while (count--) { + OUT_RING(chan, (map[1] << 16) | map[0]); + map += 2; } - return TRUE; } -static INLINE boolean -nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map, - unsigned start, unsigned count) +static void +inline_elt32(void *priv, unsigned start, unsigned count) +{ + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U32, count); + OUT_RINGp (chan, (uint32_t *)ctx->map + start, count); +} + +static void +inline_edgeflag(void *priv, boolean enabled) { + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + + BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (chan, enabled ? 1 : 0); +} + +static void +nv50_draw_elements_inline(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, unsigned indexSize, + unsigned mode, unsigned start, unsigned count, + unsigned startInstance, unsigned instanceCount) +{ + struct pipe_screen *pscreen = pipe->screen; + struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; + struct instance a[16]; + struct inline_ctx ctx; + struct u_split_prim s; + boolean nzi = FALSE; + unsigned overhead; + + overhead = 16*3; /* potential instance adjustments */ + overhead += 4; /* Begin()/End() */ + overhead += 4; /* potential edgeflag disable/reenable */ + overhead += 3; /* potentially 3 VTX_ELT_U16/U32 packet headers */ + + s.priv = &ctx; + if (indexSize == 1) + s.emit = inline_elt08; + else + if (indexSize == 2) + s.emit = inline_elt16; + else + s.emit = inline_elt32; + s.edge = inline_edgeflag; + + ctx.nv50 = nv50; + ctx.map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); + assert(ctx.map); + if (!ctx.map) + return; - map += start; + instance_init(nv50, a, startInstance); + if (!nv50_state_validate(nv50, overhead + 6 + 3)) + return; - if (nv50->vbo_fifo) - return nv50_push_elements_u32(nv50, map, count); + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, startInstance); + while (instanceCount--) { + unsigned max_verts; + boolean done; + + u_split_prim_init(&s, mode, start, count); + do { + if (AVAIL_RING(chan) < (overhead + 6)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, (overhead + 6))) { + assert(0); + return; + } + } - while (count) { - unsigned nr = count > 2047 ? 2047 : count; + max_verts = AVAIL_RING(chan) - overhead; + if (max_verts > 2047) + max_verts = 2047; + if (indexSize != 4) + max_verts <<= 1; + instance_step(nv50, a); - BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U32, nr); - OUT_RINGp (chan, map, nr); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(s.mode) | (nzi ? (1<<28) : 0)); + done = u_split_prim_next(&s, max_verts); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } while (!done); - count -= nr; - map += nr; + nzi = TRUE; } - return TRUE; -} -static INLINE void -nv50_draw_elements_inline(struct nv50_context *nv50, - void *map, unsigned indexSize, - unsigned start, unsigned count) -{ - switch (indexSize) { - case 1: - nv50_draw_elements_inline_u08(nv50, map, start, count); - break; - case 2: - nv50_draw_elements_inline_u16(nv50, map, start, count); - break; - case 4: - nv50_draw_elements_inline_u32(nv50, map, start, count); - break; - } + pipe_buffer_unmap(pscreen, indexBuffer); } void @@ -617,49 +391,68 @@ nv50_draw_elements_instanced(struct pipe_context *pipe, unsigned startInstance, unsigned instanceCount) { struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; - struct pipe_screen *pscreen = pipe->screen; - void *map; - unsigned i, nz_divisors; - unsigned step[16], pos[16]; + struct instance a[16]; + unsigned prim = nv50_prim(mode); - map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); - - if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) - nv50_upload_user_vbufs(nv50); - - nv50_state_validate(nv50); + instance_init(nv50, a, startInstance); + if (!nv50_state_validate(nv50, 13 + 16*3)) + return; - nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + if (nv50->vbo_fifo) { + nv50_push_elements_instanced(pipe, indexBuffer, indexSize, + mode, start, count, startInstance, + instanceCount); + return; + } else + if (!(indexBuffer->usage & PIPE_BUFFER_USAGE_INDEX) || indexSize == 1) { + nv50_draw_elements_inline(pipe, indexBuffer, indexSize, + mode, start, count, startInstance, + instanceCount); + return; + } BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); OUT_RING (chan, NV50_CB_AUX | (24 << 8)); OUT_RING (chan, startInstance); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - nv50_draw_elements_inline(nv50, map, indexSize, start, count); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); - - for (i = 1; i < instanceCount; ++i) { - if (nz_divisors) /* any non-zero array divisors ? */ - step_per_instance_arrays(nv50, pos, step); + while (instanceCount--) { + if (AVAIL_RING(chan) < (7 + 16*3)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, 10 + 16*3)) { + assert(0); + return; + } + } + instance_step(nv50, a); BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode) | (1 << 28)); - - nv50_draw_elements_inline(nv50, map, indexSize, start, count); - + OUT_RING (chan, prim); + if (indexSize == 4) { + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32 | 0x30000, 0); + OUT_RING (chan, count); + nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), + start << 2, count << 2); + } else + if (indexSize == 2) { + unsigned vb_start = (start & ~1); + unsigned vb_end = (start + count + 1) & ~1; + unsigned dwords = (vb_end - vb_start) >> 1; + + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); + OUT_RING (chan, ((start & 1) << 31) | count); + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x30000, 0); + OUT_RING (chan, dwords); + nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), + vb_start << 1, dwords << 2); + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); + OUT_RING (chan, 0); + } BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); - } - nv50_unmap_vbufs(nv50); - so_ref(NULL, &nv50->state.instbuf); + prim |= (1 << 28); + } } void @@ -667,51 +460,8 @@ nv50_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { - struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct pipe_screen *pscreen = pipe->screen; - void *map; - - nv50_state_validate(nv50); - - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - if (!nv50->vbo_fifo && indexSize == 4) { - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32 | 0x30000, 0); - OUT_RING (chan, count); - nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), - start << 2, count << 2); - } else - if (!nv50->vbo_fifo && indexSize == 2) { - unsigned vb_start = (start & ~1); - unsigned vb_end = (start + count + 1) & ~1; - unsigned dwords = (vb_end - vb_start) >> 1; - - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); - OUT_RING (chan, ((start & 1) << 31) | count); - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x30000, 0); - OUT_RING (chan, dwords); - nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), - vb_start << 1, dwords << 2); - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); - OUT_RING (chan, 0); - } else { - map = pipe_buffer_map(pscreen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); - nv50_draw_elements_inline(nv50, map, indexSize, start, count); - nv50_unmap_vbufs(nv50); - pipe_buffer_unmap(pscreen, indexBuffer); - } - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); + nv50_draw_elements_instanced(pipe, indexBuffer, indexSize, + mode, start, count, 0, 1); } static INLINE boolean @@ -726,6 +476,7 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, struct nouveau_bo *bo = nouveau_bo(vb->buffer); float v[4]; int ret; + unsigned nr_components = util_format_get_nr_components(ve->src_format); ret = nouveau_bo_map(bo, NOUVEAU_BO_RD); if (ret) @@ -736,9 +487,10 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, 0, 0, 1, 1); so = *pso; if (!so) - *pso = so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 4, 0); + *pso = so = so_new(nv50->vtxelt->num_elements, + nv50->vtxelt->num_elements * 4, 0); - switch (ve->nr_components) { + switch (nr_components) { case 4: so_method(so, tesla, NV50TCL_VTX_ATTR_4F_X(attrib), 4); so_data (so, fui(v[0])); @@ -775,6 +527,18 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, } void +nv50_vtxelt_construct(struct nv50_vtxelt_stateobj *cso) +{ + unsigned i; + + for (i = 0; i < cso->num_elements; ++i) { + struct pipe_vertex_element *ve = &cso->pipe[i]; + + cso->hw[i] = nv50_vbo_vtxelt_to_hw(ve); + } +} + +struct nouveau_stateobj * nv50_vbo_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -783,30 +547,32 @@ nv50_vbo_validate(struct nv50_context *nv50) /* don't validate if Gallium took away our buffers */ if (nv50->vtxbuf_nr == 0) - return; + return NULL; + nv50->vbo_fifo = 0; + if (nv50->screen->force_push || + nv50->vertprog->cfg.edgeflag_in < 16) + nv50->vbo_fifo = 0xffff; - for (i = 0; i < nv50->vtxbuf_nr; ++i) + for (i = 0; i < nv50->vtxbuf_nr; i++) { if (nv50->vtxbuf[i].stride && !(nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX)) nv50->vbo_fifo = 0xffff; + } - if (NV50_USING_LOATHED_EDGEFLAG(nv50)) - nv50->vbo_fifo = 0xffff; /* vertprog can't set edgeflag */ - - n_ve = MAX2(nv50->vtxelt_nr, nv50->state.vtxelt_nr); + n_ve = MAX2(nv50->vtxelt->num_elements, nv50->state.vtxelt_nr); vtxattr = NULL; - vtxbuf = so_new(n_ve * 2, n_ve * 5, nv50->vtxelt_nr * 4); + vtxbuf = so_new(n_ve * 2, n_ve * 5, nv50->vtxelt->num_elements * 4); vtxfmt = so_new(1, n_ve, 0); so_method(vtxfmt, tesla, NV50TCL_VERTEX_ARRAY_ATTRIB(0), n_ve); - for (i = 0; i < nv50->vtxelt_nr; i++) { - struct pipe_vertex_element *ve = &nv50->vtxelt[i]; + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; struct nouveau_bo *bo = nouveau_bo(vb->buffer); - uint32_t hw = nv50_vbo_vtxelt_to_hw(ve); + uint32_t hw = nv50->vtxelt->hw[i]; if (!vb->stride && nv50_vbo_static_attrib(nv50, i, &vtxattr, ve, vb)) { @@ -821,13 +587,13 @@ nv50_vbo_validate(struct nv50_context *nv50) } if (nv50->vbo_fifo) { - so_data (vtxfmt, hw | - (ve->instance_divisor ? (1 << 4) : i)); + so_data (vtxfmt, hw | (ve->instance_divisor ? (1 << 4) : i)); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); so_data (vtxbuf, 0); continue; } + so_data(vtxfmt, hw | i); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3); @@ -855,355 +621,13 @@ nv50_vbo_validate(struct nv50_context *nv50) so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); so_data (vtxbuf, 0); } - nv50->state.vtxelt_nr = nv50->vtxelt_nr; + nv50->state.vtxelt_nr = nv50->vtxelt->num_elements; - so_ref (vtxfmt, &nv50->state.vtxfmt); so_ref (vtxbuf, &nv50->state.vtxbuf); so_ref (vtxattr, &nv50->state.vtxattr); so_ref (NULL, &vtxbuf); - so_ref (NULL, &vtxfmt); so_ref (NULL, &vtxattr); + return vtxfmt; } -typedef void (*pfn_push)(struct nouveau_channel *, void *); - -struct nv50_vbo_emitctx -{ - pfn_push push[16]; - uint8_t *map[16]; - unsigned stride[16]; - unsigned nr_ve; - unsigned vtx_dwords; - unsigned vtx_max; - - float edgeflag; - unsigned ve_edgeflag; -}; - -static INLINE void -emit_vtx_next(struct nouveau_channel *chan, struct nv50_vbo_emitctx *emit) -{ - unsigned i; - - for (i = 0; i < emit->nr_ve; ++i) { - emit->push[i](chan, emit->map[i]); - emit->map[i] += emit->stride[i]; - } -} - -static INLINE void -emit_vtx(struct nouveau_channel *chan, struct nv50_vbo_emitctx *emit, - uint32_t vi) -{ - unsigned i; - - for (i = 0; i < emit->nr_ve; ++i) - emit->push[i](chan, emit->map[i] + emit->stride[i] * vi); -} - -static INLINE boolean -nv50_map_vbufs(struct nv50_context *nv50) -{ - int i; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) { - struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; - unsigned size = vb->stride * (vb->max_index + 1) + 16; - - if (nouveau_bo(vb->buffer)->map) - continue; - - size = vb->stride * (vb->max_index + 1) + 16; - size = MIN2(size, vb->buffer->size); - if (!size) - size = vb->buffer->size; - - if (nouveau_bo_map_range(nouveau_bo(vb->buffer), - 0, size, NOUVEAU_BO_RD)) - break; - } - - if (i == nv50->vtxbuf_nr) - return TRUE; - for (; i >= 0; --i) - nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); - return FALSE; -} - -static void -emit_b32_1(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); -} - -static void -emit_b32_2(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); - OUT_RING(chan, v[1]); -} - -static void -emit_b32_3(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); - OUT_RING(chan, v[1]); - OUT_RING(chan, v[2]); -} - -static void -emit_b32_4(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); - OUT_RING(chan, v[1]); - OUT_RING(chan, v[2]); - OUT_RING(chan, v[3]); -} - -static void -emit_b16_1(struct nouveau_channel *chan, void *data) -{ - uint16_t *v = data; - - OUT_RING(chan, v[0]); -} - -static void -emit_b16_3(struct nouveau_channel *chan, void *data) -{ - uint16_t *v = data; - - OUT_RING(chan, (v[1] << 16) | v[0]); - OUT_RING(chan, v[2]); -} - -static void -emit_b08_1(struct nouveau_channel *chan, void *data) -{ - uint8_t *v = data; - - OUT_RING(chan, v[0]); -} - -static void -emit_b08_3(struct nouveau_channel *chan, void *data) -{ - uint8_t *v = data; - - OUT_RING(chan, (v[2] << 16) | (v[1] << 8) | v[0]); -} - -static boolean -emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit, - unsigned start) -{ - unsigned i; - - if (nv50_map_vbufs(nv50) == FALSE) - return FALSE; - - emit->ve_edgeflag = nv50->vertprog->cfg.edgeflag_in; - - emit->edgeflag = 0.5f; - emit->nr_ve = 0; - emit->vtx_dwords = 0; - - for (i = 0; i < nv50->vtxelt_nr; ++i) { - struct pipe_vertex_element *ve; - struct pipe_vertex_buffer *vb; - unsigned n, size; - const struct util_format_description *desc; - - ve = &nv50->vtxelt[i]; - vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - if (!(nv50->vbo_fifo & (1 << i)) || ve->instance_divisor) - continue; - n = emit->nr_ve++; - - emit->stride[n] = vb->stride; - emit->map[n] = (uint8_t *)nouveau_bo(vb->buffer)->map + - vb->buffer_offset + - (start * vb->stride + ve->src_offset); - - desc = util_format_description(ve->src_format); - assert(desc); - - size = util_format_get_component_bits( - ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0); - - assert(ve->nr_components > 0 && ve->nr_components <= 4); - - /* It shouldn't be necessary to push the implicit 1s - * for case 3 and size 8 cases 1, 2, 3. - */ - switch (size) { - default: - NOUVEAU_ERR("unsupported vtxelt size: %u\n", size); - return FALSE; - case 32: - switch (ve->nr_components) { - case 1: emit->push[n] = emit_b32_1; break; - case 2: emit->push[n] = emit_b32_2; break; - case 3: emit->push[n] = emit_b32_3; break; - case 4: emit->push[n] = emit_b32_4; break; - } - emit->vtx_dwords += ve->nr_components; - break; - case 16: - switch (ve->nr_components) { - case 1: emit->push[n] = emit_b16_1; break; - case 2: emit->push[n] = emit_b32_1; break; - case 3: emit->push[n] = emit_b16_3; break; - case 4: emit->push[n] = emit_b32_2; break; - } - emit->vtx_dwords += (ve->nr_components + 1) >> 1; - break; - case 8: - switch (ve->nr_components) { - case 1: emit->push[n] = emit_b08_1; break; - case 2: emit->push[n] = emit_b16_1; break; - case 3: emit->push[n] = emit_b08_3; break; - case 4: emit->push[n] = emit_b32_1; break; - } - emit->vtx_dwords += 1; - break; - } - } - - emit->vtx_max = 512 / emit->vtx_dwords; - if (emit->ve_edgeflag < 16) - emit->vtx_max = 1; - - return TRUE; -} - -static INLINE void -set_edgeflag(struct nouveau_channel *chan, - struct nouveau_grobj *tesla, - struct nv50_vbo_emitctx *emit, uint32_t index) -{ - unsigned i = emit->ve_edgeflag; - - if (i < 16) { - float f = *((float *)(emit->map[i] + index * emit->stride[i])); - - if (emit->edgeflag != f) { - emit->edgeflag = f; - - BEGIN_RING(chan, tesla, 0x15e4, 1); - OUT_RING (chan, f ? 1 : 0); - } - } -} - -static boolean -nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - if (emit_prepare(nv50, &emit, start) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, 0); /* nr will be 1 */ - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx_next(chan, &emit); - - count -= nr; - } - - return TRUE; -} - -static boolean -nv50_push_elements_u32(struct nv50_context *nv50, uint32_t *map, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - - if (emit_prepare(nv50, &emit, 0) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, *map); - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx(chan, &emit, *map++); - - count -= nr; - } - - return TRUE; -} - -static boolean -nv50_push_elements_u16(struct nv50_context *nv50, uint16_t *map, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - - if (emit_prepare(nv50, &emit, 0) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, *map); - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx(chan, &emit, *map++); - - count -= nr; - } - - return TRUE; -} - -static boolean -nv50_push_elements_u08(struct nv50_context *nv50, uint8_t *map, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - - if (emit_prepare(nv50, &emit, 0) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, *map); - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx(chan, &emit, *map++); - - count -= nr; - } - - return TRUE; -} diff --git a/src/gallium/drivers/nvfx/Makefile b/src/gallium/drivers/nvfx/Makefile new file mode 100644 index 00000000000..dfe97e6ed5f --- /dev/null +++ b/src/gallium/drivers/nvfx/Makefile @@ -0,0 +1,32 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nvfx + +C_SOURCES = \ + nv04_surface_2d.c \ + nvfx_context.c \ + nvfx_clear.c \ + nvfx_draw.c \ + nvfx_fragprog.c \ + nvfx_fragtex.c \ + nv30_fragtex.c \ + nv40_fragtex.c \ + nvfx_miptree.c \ + nvfx_query.c \ + nvfx_screen.c \ + nvfx_state.c \ + nvfx_state_blend.c \ + nvfx_state_emit.c \ + nvfx_state_fb.c \ + nvfx_state_rasterizer.c \ + nvfx_state_scissor.c \ + nvfx_state_stipple.c \ + nvfx_state_viewport.c \ + nvfx_state_zsa.c \ + nvfx_surface.c \ + nvfx_transfer.c \ + nvfx_vbo.c \ + nvfx_vertprog.c + +include ../../Makefile.template diff --git a/src/gallium/drivers/nouveau/nv04_surface_2d.c b/src/gallium/drivers/nvfx/nv04_surface_2d.c index b074547c4da..ed18c9f24dc 100644 --- a/src/gallium/drivers/nouveau/nv04_surface_2d.c +++ b/src/gallium/drivers/nvfx/nv04_surface_2d.c @@ -518,7 +518,6 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d ns->base.usage = PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER | PIPE_BUFFER_USAGE_GPU_READ; } - struct nv40_screen* screen = (struct nv40_screen*)pscreen; ns->base.usage = PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE; struct pipe_texture templ; @@ -544,4 +543,3 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d return temp_ns; } - diff --git a/src/gallium/drivers/nouveau/nv04_surface_2d.h b/src/gallium/drivers/nvfx/nv04_surface_2d.h index ce696a11a39..ce696a11a39 100644 --- a/src/gallium/drivers/nouveau/nv04_surface_2d.h +++ b/src/gallium/drivers/nvfx/nv04_surface_2d.h diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c index f7d98f3f208..2b56f454921 100644 --- a/src/gallium/drivers/nv30/nv30_fragtex.c +++ b/src/gallium/drivers/nvfx/nv30_fragtex.c @@ -1,7 +1,37 @@ #include "util/u_format.h" -#include "nv30_context.h" +#include "nvfx_context.h" #include "nouveau/nouveau_util.h" +#include "nvfx_tex.h" + +void +nv30_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso) +{ + if (cso->max_anisotropy >= 8) { + ps->en |= NV34TCL_TX_ENABLE_ANISO_8X; + } else + if (cso->max_anisotropy >= 4) { + ps->en |= NV34TCL_TX_ENABLE_ANISO_4X; + } else + if (cso->max_anisotropy >= 2) { + ps->en |= NV34TCL_TX_ENABLE_ANISO_2X; + } + + { + float limit; + + limit = CLAMP(cso->lod_bias, -16.0, 15.0); + ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + + limit = CLAMP(cso->max_lod, 0.0, 15.0); + ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/; + + limit = CLAMP(cso->min_lod, 0.0, 15.0); + ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/; + } +} #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \ { \ @@ -57,11 +87,11 @@ nv30_fragtex_format(uint pipe_format) } -static struct nouveau_stateobj * -nv30_fragtex_build(struct nv30_context *nv30, int unit) +struct nouveau_stateobj * +nv30_fragtex_build(struct nvfx_context *nvfx, int unit) { - struct nv30_sampler_state *ps = nv30->tex_sampler[unit]; - struct nv30_miptree *nv30mt = nv30->tex_miptree[unit]; + struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; + struct nvfx_miptree *nv30mt = nvfx->tex_miptree[unit]; struct pipe_texture *pt = &nv30mt->base; struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer); struct nv30_texture_format *tf; @@ -101,7 +131,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) txs = tf->swizzle; so = so_new(1, 8, 2); - so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_OFFSET(unit), 8); so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR, NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); @@ -115,47 +145,3 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) return so; } - -static boolean -nv30_fragtex_validate(struct nv30_context *nv30) -{ - struct nv30_fragment_program *fp = nv30->fragprog; - struct nv30_state *state = &nv30->state; - struct nouveau_stateobj *so; - unsigned samplers, unit; - - samplers = state->fp_samplers & ~fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = so_new(1, 1, 0); - so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1); - so_data (so, 0); - so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]); - so_ref(NULL, &so); - state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit)); - } - - samplers = nv30->dirty_samplers & fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = nv30_fragtex_build(nv30, unit); - so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]); - so_ref(NULL, &so); - state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit)); - } - - nv30->state.fp_samplers = fp->samplers; - return FALSE; -} - -struct nv30_state_entry nv30_state_fragtex = { - .validate = nv30_fragtex_validate, - .dirty = { - .pipe = NV30_NEW_SAMPLER | NV30_NEW_FRAGPROG, - .hw = 0 - } -}; diff --git a/src/gallium/drivers/nvfx/nv30_vertprog.h b/src/gallium/drivers/nvfx/nv30_vertprog.h new file mode 100644 index 00000000000..ec0444c07f8 --- /dev/null +++ b/src/gallium/drivers/nvfx/nv30_vertprog.h @@ -0,0 +1,169 @@ +#ifndef __NV30_SHADER_H__ +#define __NV30_SHADER_H__ + +/* Vertex programs instruction set + * + * 128bit opcodes, split into 4 32-bit ones for ease of use. + * + * Non-native instructions + * ABS - MOV + NV40_VP_INST0_DEST_ABS + * POW - EX2 + MUL + LG2 + * SUB - ADD, second source negated + * SWZ - MOV + * XPD - + * + * Register access + * - Only one INPUT can be accessed per-instruction (move extras into TEMPs) + * - Only one CONST can be accessed per-instruction (move extras into TEMPs) + * + * Relative Addressing + * According to the value returned for + * MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB + * + * there are only two address registers available. The destination in the + * ARL instruction is set to TEMP <n> (The temp isn't actually written). + * + * When using vanilla ARB_v_p, the proprietary driver will squish both the + * available ADDRESS regs into the first hardware reg in the X and Y + * components. + * + * To use an address reg as an index into consts, the CONST_SRC is set to + * (const_base + offset) and INDEX_CONST is set. + * + * To access the second address reg use ADDR_REG_SELECT_1. A particular + * component of the address regs is selected with ADDR_SWZ. + * + * Only one address register can be accessed per instruction. + * + * Conditional execution (see NV_vertex_program{2,3} for details) Conditional + * execution of an instruction is enabled by setting COND_TEST_ENABLE, and + * selecting the condition which will allow the test to pass with + * COND_{FL,LT,...}. It is possible to swizzle the values in the condition + * register, which allows for testing against an individual component. + * + * Branching: + * + * The BRA/CAL instructions seem to follow a slightly different opcode + * layout. The destination instruction ID (IADDR) overlaps a source field. + * Instruction ID's seem to be numbered based on the UPLOAD_FROM_ID FIFO + * command, and is incremented automatically on each UPLOAD_INST FIFO + * command. + * + * Conditional branching is achieved by using the condition tests described + * above. There doesn't appear to be dedicated looping instructions, but + * this can be done using a temp reg + conditional branching. + * + * Subroutines may be uploaded before the main program itself, but the first + * executed instruction is determined by the PROGRAM_START_ID FIFO command. + * + */ + +/* DWORD 0 */ + +#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24) +#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */ +#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */ +#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */ +#define NV30_VP_INST_VEC_RESULT (1 << 20) +#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16 +#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16) +#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15) +#define NV30_VP_INST_VEC_DEST_TEMP_MASK (0xF << 16) +#define NV30_VP_INST_COND_TEST_ENABLE (1<<14) +#define NV30_VP_INST_COND_SHIFT 11 +#define NV30_VP_INST_COND_MASK (0x07 << 11) +#define NV30_VP_INST_COND_SWZ_X_SHIFT 9 +#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9) +#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7 +#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7) +#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5 +#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5) +#define NV30_VP_INST_COND_SWZ_W_SHIFT 3 +#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3) +#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3 +#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3) +#define NV30_VP_INST_ADDR_SWZ_SHIFT 1 +#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1) +#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0 +#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0) + +/* DWORD 1 */ +#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28 +#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28) +#define NV30_VP_INST_VEC_OPCODE_SHIFT 23 +#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23) +#define NV30_VP_INST_CONST_SRC_SHIFT 14 +#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14) +#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/ +#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/ +#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/ +#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/ + +/* Please note: the IADDR fields overlap other fields because they are used + * only for branch instructions. See Branching: label above + * + * DWORD 2 + */ +#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/ +#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /* NV30_VP_SRC0_LOW_MASK << 26 */ +#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/ +#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/ +#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/ +#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /* NV30_VP_SRC2_HIGH_MASK >> 4*/ +#define NV30_VP_INST_IADDR_SHIFT 2 +#define NV30_VP_INST_IADDR_MASK (0xF << 28) /* NV30_VP_SRC2_LOW_MASK << 28 */ + +/* DWORD 3 */ +#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/ +#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/ +#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24 +#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24) +#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20 +#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20) +#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16 +#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16) +#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/ +#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/ +#define NV30_VP_INST_DEST_SHIFT 2 +#define NV30_VP_INST_DEST_MASK (0x0F << 2) +# define NV30_VP_INST_DEST_POS 0 +# define NV30_VP_INST_DEST_BFC0 1 +# define NV30_VP_INST_DEST_BFC1 2 +# define NV30_VP_INST_DEST_COL0 3 +# define NV30_VP_INST_DEST_COL1 4 +# define NV30_VP_INST_DEST_FOGC 5 +# define NV30_VP_INST_DEST_PSZ 6 +# define NV30_VP_INST_DEST_TC(n) (8+n) + +/* Useful to split the source selection regs into their pieces */ +#define NV30_VP_SRC0_HIGH_SHIFT 6 +#define NV30_VP_SRC0_HIGH_MASK 0x00007FC0 +#define NV30_VP_SRC0_LOW_MASK 0x0000003F +#define NV30_VP_SRC2_HIGH_SHIFT 4 +#define NV30_VP_SRC2_HIGH_MASK 0x00007FF0 +#define NV30_VP_SRC2_LOW_MASK 0x0000000F + + +/* Source-register definition - matches NV20 exactly */ +#define NV30_VP_SRC_NEGATE (1<<14) +#define NV30_VP_SRC_SWZ_X_SHIFT 12 +#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12) +#define NV30_VP_SRC_SWZ_Y_SHIFT 10 +#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10) +#define NV30_VP_SRC_SWZ_Z_SHIFT 8 +#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8) +#define NV30_VP_SRC_SWZ_W_SHIFT 6 +#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6) +#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6 +#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6) +#define NV30_VP_SRC_TEMP_SRC_SHIFT 2 +#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0) +#define NV30_VP_SRC_REG_TYPE_SHIFT 0 +#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0) +#define NV30_VP_SRC_REG_TYPE_TEMP 1 +#define NV30_VP_SRC_REG_TYPE_INPUT 2 +#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */ + +#include "nvfx_shader.h" + +#endif diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c index b60118922a2..5889b5e40d5 100644 --- a/src/gallium/drivers/nv40/nv40_fragtex.c +++ b/src/gallium/drivers/nvfx/nv40_fragtex.c @@ -1,18 +1,63 @@ #include "util/u_format.h" +#include "nvfx_context.h" +#include "nvfx_tex.h" -#include "nv40_context.h" +void +nv40_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso) +{ + if (cso->max_anisotropy >= 2) { + /* no idea, binary driver sets it, works without it.. meh.. */ + ps->wrap |= (1 << 5); + + if (cso->max_anisotropy >= 16) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X; + } else + if (cso->max_anisotropy >= 12) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X; + } else + if (cso->max_anisotropy >= 10) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X; + } else + if (cso->max_anisotropy >= 8) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X; + } else + if (cso->max_anisotropy >= 6) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X; + } else + if (cso->max_anisotropy >= 4) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X; + } else { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X; + } + } + + { + float limit; + + limit = CLAMP(cso->lod_bias, -16.0, 15.0); + ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + + limit = CLAMP(cso->max_lod, 0.0, 15.0); + ps->en |= (int)(limit * 256.0) << 7; + + limit = CLAMP(cso->min_lod, 0.0, 15.0); + ps->en |= (int)(limit * 256.0) << 19; + } +} #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw) \ { \ TRUE, \ PIPE_FORMAT_##m, \ NV40TCL_TEX_FORMAT_FORMAT_##tf, \ - (NV40TCL_TEX_SWIZZLE_S0_X_##ts0x | NV40TCL_TEX_SWIZZLE_S0_Y_##ts0y | \ - NV40TCL_TEX_SWIZZLE_S0_Z_##ts0z | NV40TCL_TEX_SWIZZLE_S0_W_##ts0w | \ - NV40TCL_TEX_SWIZZLE_S1_X_##ts1x | NV40TCL_TEX_SWIZZLE_S1_Y_##ts1y | \ - NV40TCL_TEX_SWIZZLE_S1_Z_##ts1z | NV40TCL_TEX_SWIZZLE_S1_W_##ts1w), \ - ((NV40TCL_TEX_FILTER_SIGNED_RED*sx) | (NV40TCL_TEX_FILTER_SIGNED_GREEN*sy) | \ - (NV40TCL_TEX_FILTER_SIGNED_BLUE*sz) | (NV40TCL_TEX_FILTER_SIGNED_ALPHA*sw)) \ + (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \ + NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \ + NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \ + NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w), \ + ((NV34TCL_TX_FILTER_SIGNED_RED*sx) | (NV34TCL_TX_FILTER_SIGNED_GREEN*sy) | \ + (NV34TCL_TX_FILTER_SIGNED_BLUE*sz) | (NV34TCL_TX_FILTER_SIGNED_ALPHA*sw)) \ } struct nv40_texture_format { @@ -60,11 +105,11 @@ nv40_fragtex_format(uint pipe_format) } -static struct nouveau_stateobj * -nv40_fragtex_build(struct nv40_context *nv40, int unit) +struct nouveau_stateobj * +nv40_fragtex_build(struct nvfx_context *nvfx, int unit) { - struct nv40_sampler_state *ps = nv40->tex_sampler[unit]; - struct nv40_miptree *nv40mt = nv40->tex_miptree[unit]; + struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; + struct nvfx_miptree *nv40mt = nvfx->tex_miptree[unit]; struct nouveau_bo *bo = nouveau_bo(nv40mt->buffer); struct pipe_texture *pt = &nv40mt->base; struct nv40_texture_format *tf; @@ -81,20 +126,20 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT); if (1) /* XXX */ - txf |= NV40TCL_TEX_FORMAT_NO_BORDER; + txf |= NV34TCL_TX_FORMAT_NO_BORDER; switch (pt->target) { case PIPE_TEXTURE_CUBE: - txf |= NV40TCL_TEX_FORMAT_CUBIC; + txf |= NV34TCL_TX_FORMAT_CUBIC; /* fall-through */ case PIPE_TEXTURE_2D: - txf |= NV40TCL_TEX_FORMAT_DIMS_2D; + txf |= NV34TCL_TX_FORMAT_DIMS_2D; break; case PIPE_TEXTURE_3D: - txf |= NV40TCL_TEX_FORMAT_DIMS_3D; + txf |= NV34TCL_TX_FORMAT_DIMS_3D; break; case PIPE_TEXTURE_1D: - txf |= NV40TCL_TEX_FORMAT_DIMS_1D; + txf |= NV34TCL_TX_FORMAT_DIMS_1D; break; default: NOUVEAU_ERR("Unknown target %d\n", pt->target); @@ -111,63 +156,19 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) txs = tf->swizzle; so = so_new(2, 9, 2); - so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_OFFSET(unit), 8); so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR, - NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1); + NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); so_data (so, ps->wrap); so_data (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en); so_data (so, txs); so_data (so, ps->filt | tf->sign | 0x2000 /*voodoo*/); - so_data (so, (pt->width0 << NV40TCL_TEX_SIZE0_W_SHIFT) | + so_data (so, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pt->height0); so_data (so, ps->bcol); - so_method(so, nv40->screen->curie, NV40TCL_TEX_SIZE1(unit), 1); + so_method(so, nvfx->screen->eng3d, NV40TCL_TEX_SIZE1(unit), 1); so_data (so, (pt->depth0 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp); return so; } - -static boolean -nv40_fragtex_validate(struct nv40_context *nv40) -{ - struct nv40_fragment_program *fp = nv40->fragprog; - struct nv40_state *state = &nv40->state; - struct nouveau_stateobj *so; - unsigned samplers, unit; - - samplers = state->fp_samplers & ~fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = so_new(1, 1, 0); - so_method(so, nv40->screen->curie, NV40TCL_TEX_ENABLE(unit), 1); - so_data (so, 0); - so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]); - state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit)); - } - - samplers = nv40->dirty_samplers & fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = nv40_fragtex_build(nv40, unit); - so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]); - so_ref(NULL, &so); - state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit)); - } - - nv40->state.fp_samplers = fp->samplers; - return FALSE; -} - -struct nv40_state_entry nv40_state_fragtex = { - .validate = nv40_fragtex_validate, - .dirty = { - .pipe = NV40_NEW_SAMPLER | NV40_NEW_FRAGPROG, - .hw = 0 - } -}; - diff --git a/src/gallium/drivers/nvfx/nv40_vertprog.h b/src/gallium/drivers/nvfx/nv40_vertprog.h new file mode 100644 index 00000000000..7337293babc --- /dev/null +++ b/src/gallium/drivers/nvfx/nv40_vertprog.h @@ -0,0 +1,177 @@ +#ifndef __NV40_SHADER_H__ +#define __NV40_SHADER_H__ + +/* Vertex programs instruction set + * + * The NV40 instruction set is very similar to NV30. Most fields are in + * a slightly different position in the instruction however. + * + * Merged instructions + * In some cases it is possible to put two instructions into one opcode + * slot. The rules for when this is OK is not entirely clear to me yet. + * + * There are separate writemasks and dest temp register fields for each + * grouping of instructions. There is however only one field with the + * ID of a result register. Writing to temp/result regs is selected by + * setting VEC_RESULT/SCA_RESULT. + * + * Temporary registers + * The source/dest temp register fields have been extended by 1 bit, to + * give a total of 32 temporary registers. + * + * Relative Addressing + * NV40 can use an address register to index into vertex attribute regs. + * This is done by putting the offset value into INPUT_SRC and setting + * the INDEX_INPUT flag. + * + * Conditional execution (see NV_vertex_program{2,3} for details) + * There is a second condition code register on NV40, it's use is enabled + * by setting the COND_REG_SELECT_1 flag. + * + * Texture lookup + * TODO + */ + +/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */ +#define NV40_VP_INST_VEC_RESULT (1 << 30) +/* uncertain.. */ +#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29) +/* use address reg as index into attribs */ +#define NV40_VP_INST_INDEX_INPUT (1 << 27) +#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25) +#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24) +#define NV40_VP_INST_SRC2_ABS (1 << 23) +#define NV40_VP_INST_SRC1_ABS (1 << 22) +#define NV40_VP_INST_SRC0_ABS (1 << 21) +#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15 +#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15) +#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13) +#define NV40_VP_INST_COND_SHIFT 10 +#define NV40_VP_INST_COND_MASK (0x7 << 10) +#define NV40_VP_INST_COND_SWZ_X_SHIFT 8 +#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8) +#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6 +#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6) +#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4 +#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4) +#define NV40_VP_INST_COND_SWZ_W_SHIFT 2 +#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2) +#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2 +#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2) +#define NV40_VP_INST_ADDR_SWZ_SHIFT 0 +#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0) +#define NV40_VP_INST0_KNOWN ( \ + NV40_VP_INST_INDEX_INPUT | \ + NV40_VP_INST_COND_REG_SELECT_1 | \ + NV40_VP_INST_ADDR_REG_SELECT_1 | \ + NV40_VP_INST_SRC2_ABS | \ + NV40_VP_INST_SRC1_ABS | \ + NV40_VP_INST_SRC0_ABS | \ + NV40_VP_INST_VEC_DEST_TEMP_MASK | \ + NV40_VP_INST_COND_TEST_ENABLE | \ + NV40_VP_INST_COND_MASK | \ + NV40_VP_INST_COND_SWZ_ALL_MASK | \ + NV40_VP_INST_ADDR_SWZ_MASK) + +/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */ +#define NV40_VP_INST_VEC_OPCODE_SHIFT 22 +#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22) +#define NV40_VP_INST_SCA_OPCODE_SHIFT 27 +#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27) +#define NV40_VP_INST_CONST_SRC_SHIFT 12 +#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12) +#define NV40_VP_INST_INPUT_SRC_SHIFT 8 +#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8) +#define NV40_VP_INST_SRC0H_SHIFT 0 +#define NV40_VP_INST_SRC0H_MASK (0xFF << 0) +#define NV40_VP_INST1_KNOWN ( \ + NV40_VP_INST_VEC_OPCODE_MASK | \ + NV40_VP_INST_SCA_OPCODE_MASK | \ + NV40_VP_INST_CONST_SRC_MASK | \ + NV40_VP_INST_INPUT_SRC_MASK | \ + NV40_VP_INST_SRC0H_MASK \ + ) + +/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */ +#define NV40_VP_INST_SRC0L_SHIFT 23 +#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23) +#define NV40_VP_INST_SRC1_SHIFT 6 +#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6) +#define NV40_VP_INST_SRC2H_SHIFT 0 +#define NV40_VP_INST_SRC2H_MASK (0x3F << 0) +#define NV40_VP_INST_IADDRH_SHIFT 0 +#define NV40_VP_INST_IADDRH_MASK (0x1F << 0) + +/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */ +#define NV40_VP_INST_IADDRL_SHIFT 29 +#define NV40_VP_INST_IADDRL_MASK (7 << 29) +#define NV40_VP_INST_SRC2L_SHIFT 21 +#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21) +#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17 +#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17) +# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20) +# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19) +# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18) +# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17) +#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13 +#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13) +# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16) +# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15) +# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14) +# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13) +#define NV40_VP_INST_SCA_RESULT (1 << 12) +#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7 +#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7) +#define NV40_VP_INST_DEST_SHIFT 2 +#define NV40_VP_INST_DEST_MASK (31 << 2) +# define NV40_VP_INST_DEST_POS 0 +# define NV40_VP_INST_DEST_COL0 1 +# define NV40_VP_INST_DEST_COL1 2 +# define NV40_VP_INST_DEST_BFC0 3 +# define NV40_VP_INST_DEST_BFC1 4 +# define NV40_VP_INST_DEST_FOGC 5 +# define NV40_VP_INST_DEST_PSZ 6 +# define NV40_VP_INST_DEST_TC0 7 +# define NV40_VP_INST_DEST_TC(n) (7+n) +# define NV40_VP_INST_DEST_TEMP 0x1F +#define NV40_VP_INST_INDEX_CONST (1 << 1) +#define NV40_VP_INST3_KNOWN ( \ + NV40_VP_INST_SRC2L_MASK |\ + NV40_VP_INST_SCA_WRITEMASK_MASK |\ + NV40_VP_INST_VEC_WRITEMASK_MASK |\ + NV40_VP_INST_SCA_DEST_TEMP_MASK |\ + NV40_VP_INST_DEST_MASK |\ + NV40_VP_INST_INDEX_CONST) + +/* Useful to split the source selection regs into their pieces */ +#define NV40_VP_SRC0_HIGH_SHIFT 9 +#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00 +#define NV40_VP_SRC0_LOW_MASK 0x000001FF +#define NV40_VP_SRC2_HIGH_SHIFT 11 +#define NV40_VP_SRC2_HIGH_MASK 0x0001F800 +#define NV40_VP_SRC2_LOW_MASK 0x000007FF + +/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */ +#define NV40_VP_SRC_NEGATE (1 << 16) +#define NV40_VP_SRC_SWZ_X_SHIFT 14 +#define NV40_VP_SRC_SWZ_X_MASK (3 << 14) +#define NV40_VP_SRC_SWZ_Y_SHIFT 12 +#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12) +#define NV40_VP_SRC_SWZ_Z_SHIFT 10 +#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10) +#define NV40_VP_SRC_SWZ_W_SHIFT 8 +#define NV40_VP_SRC_SWZ_W_MASK (3 << 8) +#define NV40_VP_SRC_SWZ_ALL_SHIFT 8 +#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8) +#define NV40_VP_SRC_TEMP_SRC_SHIFT 2 +#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2) +#define NV40_VP_SRC_REG_TYPE_SHIFT 0 +#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0) +# define NV40_VP_SRC_REG_TYPE_UNK0 0 +# define NV40_VP_SRC_REG_TYPE_TEMP 1 +# define NV40_VP_SRC_REG_TYPE_INPUT 2 +# define NV40_VP_SRC_REG_TYPE_CONST 3 + +#include "nvfx_shader.h" + +#endif diff --git a/src/gallium/drivers/nv40/nv40_clear.c b/src/gallium/drivers/nvfx/nvfx_clear.c index ddf13addf3b..2be70fcee40 100644 --- a/src/gallium/drivers/nv40/nv40_clear.c +++ b/src/gallium/drivers/nvfx/nvfx_clear.c @@ -3,12 +3,12 @@ #include "pipe/p_state.h" #include "util/u_clear.h" -#include "nv40_context.h" +#include "nvfx_context.h" void -nv40_clear(struct pipe_context *pipe, unsigned buffers, +nvfx_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil) { - util_clear(pipe, &nv40_context(pipe)->framebuffer, buffers, rgba, depth, + util_clear(pipe, &nvfx_context(pipe)->framebuffer, buffers, rgba, depth, stencil); } diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c new file mode 100644 index 00000000000..fc3cbdb558f --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_context.c @@ -0,0 +1,90 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" + +#include "nvfx_context.h" +#include "nvfx_screen.h" + +static void +nvfx_flush(struct pipe_context *pipe, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + if (flags & PIPE_FLUSH_TEXTURE_CACHE) { + BEGIN_RING(chan, eng3d, 0x1fd8, 1); + OUT_RING (chan, 2); + BEGIN_RING(chan, eng3d, 0x1fd8, 1); + OUT_RING (chan, 1); + } + + FIRE_RING(chan); + if (fence) + *fence = NULL; +} + +static void +nvfx_destroy(struct pipe_context *pipe) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned i; + + for (i = 0; i < NVFX_STATE_MAX; i++) { + if (nvfx->state.hw[i]) + so_ref(NULL, &nvfx->state.hw[i]); + } + + if (nvfx->draw) + draw_destroy(nvfx->draw); + FREE(nvfx); +} + +struct pipe_context * +nvfx_create(struct pipe_screen *pscreen, void *priv) +{ + struct nvfx_screen *screen = nvfx_screen(pscreen); + struct pipe_winsys *ws = pscreen->winsys; + struct nvfx_context *nvfx; + struct nouveau_winsys *nvws = screen->nvws; + + nvfx = CALLOC(1, sizeof(struct nvfx_context)); + if (!nvfx) + return NULL; + nvfx->screen = screen; + + nvfx->nvws = nvws; + + nvfx->pipe.winsys = ws; + nvfx->pipe.screen = pscreen; + nvfx->pipe.priv = priv; + nvfx->pipe.destroy = nvfx_destroy; + nvfx->pipe.draw_arrays = nvfx_draw_arrays; + nvfx->pipe.draw_elements = nvfx_draw_elements; + nvfx->pipe.clear = nvfx_clear; + nvfx->pipe.flush = nvfx_flush; + + nvfx->pipe.is_texture_referenced = nouveau_is_texture_referenced; + nvfx->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; + + screen->base.channel->user_private = nvfx; + screen->base.channel->flush_notify = nvfx_state_flush_notify; + + nvfx->is_nv4x = screen->is_nv4x; + + nvfx_init_query_functions(nvfx); + nvfx_init_surface_functions(nvfx); + nvfx_init_state_functions(nvfx); + nvfx_init_transfer_functions(nvfx); + + /* Create, configure, and install fallback swtnl path */ + nvfx->draw = draw_create(); + draw_wide_point_threshold(nvfx->draw, 9999999.0); + draw_wide_line_threshold(nvfx->draw, 9999999.0); + draw_enable_line_stipple(nvfx->draw, FALSE); + draw_enable_point_sprites(nvfx->draw, FALSE); + draw_set_rasterize_stage(nvfx->draw, nvfx_draw_render_stage(nvfx)); + + return &nvfx->pipe; +} diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h new file mode 100644 index 00000000000..001b19eedf0 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -0,0 +1,265 @@ +#ifndef __NVFX_CONTEXT_H__ +#define __NVFX_CONTEXT_H__ + +#include <stdio.h> + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_compiler.h" + +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_inlines.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" +#include "nouveau/nouveau_context.h" +#include "nouveau/nouveau_stateobj.h" + +#include "nvfx_state.h" + +#define NOUVEAU_ERR(fmt, args...) \ + fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ + fprintf(stderr, "nouveau: "fmt, ##args); + +enum nvfx_state_index { + NVFX_STATE_FB = 0, + NVFX_STATE_VIEWPORT = 1, + NVFX_STATE_BLEND = 2, + NVFX_STATE_RAST = 3, + NVFX_STATE_ZSA = 4, + NVFX_STATE_BCOL = 5, + NVFX_STATE_CLIP = 6, + NVFX_STATE_SCISSOR = 7, + NVFX_STATE_STIPPLE = 8, + NVFX_STATE_FRAGPROG = 9, + NVFX_STATE_VERTPROG = 10, + NVFX_STATE_FRAGTEX0 = 11, + NVFX_STATE_FRAGTEX1 = 12, + NVFX_STATE_FRAGTEX2 = 13, + NVFX_STATE_FRAGTEX3 = 14, + NVFX_STATE_FRAGTEX4 = 15, + NVFX_STATE_FRAGTEX5 = 16, + NVFX_STATE_FRAGTEX6 = 17, + NVFX_STATE_FRAGTEX7 = 18, + NVFX_STATE_FRAGTEX8 = 19, + NVFX_STATE_FRAGTEX9 = 20, + NVFX_STATE_FRAGTEX10 = 21, + NVFX_STATE_FRAGTEX11 = 22, + NVFX_STATE_FRAGTEX12 = 23, + NVFX_STATE_FRAGTEX13 = 24, + NVFX_STATE_FRAGTEX14 = 25, + NVFX_STATE_FRAGTEX15 = 26, + NVFX_STATE_VERTTEX0 = 27, + NVFX_STATE_VERTTEX1 = 28, + NVFX_STATE_VERTTEX2 = 29, + NVFX_STATE_VERTTEX3 = 30, + NVFX_STATE_VTXBUF = 31, + NVFX_STATE_VTXFMT = 32, + NVFX_STATE_VTXATTR = 33, + NVFX_STATE_SR = 34, + NVFX_STATE_MAX = 35 +}; + +#include "nvfx_screen.h" + +#define NVFX_NEW_BLEND (1 << 0) +#define NVFX_NEW_RAST (1 << 1) +#define NVFX_NEW_ZSA (1 << 2) +#define NVFX_NEW_SAMPLER (1 << 3) +#define NVFX_NEW_FB (1 << 4) +#define NVFX_NEW_STIPPLE (1 << 5) +#define NVFX_NEW_SCISSOR (1 << 6) +#define NVFX_NEW_VIEWPORT (1 << 7) +#define NVFX_NEW_BCOL (1 << 8) +#define NVFX_NEW_VERTPROG (1 << 9) +#define NVFX_NEW_FRAGPROG (1 << 10) +#define NVFX_NEW_ARRAYS (1 << 11) +#define NVFX_NEW_UCP (1 << 12) +#define NVFX_NEW_SR (1 << 13) + +struct nvfx_rasterizer_state { + struct pipe_rasterizer_state pipe; + struct nouveau_stateobj *so; +}; + +struct nvfx_zsa_state { + struct pipe_depth_stencil_alpha_state pipe; + struct nouveau_stateobj *so; +}; + +struct nvfx_blend_state { + struct pipe_blend_state pipe; + struct nouveau_stateobj *so; +}; + + +struct nvfx_state { + unsigned scissor_enabled; + unsigned stipple_enabled; + unsigned fp_samplers; + + uint64_t dirty; + struct nouveau_stateobj *hw[NVFX_STATE_MAX]; +}; + +struct nvfx_vtxelt_state { + struct pipe_vertex_element pipe[16]; + unsigned num_elements; +}; + +struct nvfx_context { + struct pipe_context pipe; + + struct nouveau_winsys *nvws; + struct nvfx_screen *screen; + + unsigned is_nv4x; /* either 0 or ~0 */ + + struct draw_context *draw; + + /* HW state derived from pipe states */ + struct nvfx_state state; + struct { + struct nvfx_vertex_program *vertprog; + + unsigned nr_attribs; + unsigned hw[PIPE_MAX_SHADER_INPUTS]; + unsigned draw[PIPE_MAX_SHADER_INPUTS]; + unsigned emit[PIPE_MAX_SHADER_INPUTS]; + } swtnl; + + enum { + HW, SWTNL, SWRAST + } render_mode; + unsigned fallback_swtnl; + unsigned fallback_swrast; + + /* Context state */ + unsigned dirty, draw_dirty; + struct pipe_scissor_state scissor; + unsigned stipple[32]; + struct pipe_clip_state clip; + struct nvfx_vertex_program *vertprog; + struct nvfx_fragment_program *fragprog; + struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; + unsigned constbuf_nr[PIPE_SHADER_TYPES]; + struct nvfx_rasterizer_state *rasterizer; + struct nvfx_zsa_state *zsa; + struct nvfx_blend_state *blend; + struct pipe_blend_color blend_colour; + struct pipe_stencil_ref stencil_ref; + struct pipe_viewport_state viewport; + struct pipe_framebuffer_state framebuffer; + struct pipe_buffer *idxbuf; + unsigned idxbuf_format; + struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; + struct nvfx_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers; + unsigned nr_textures; + unsigned dirty_samplers; + struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; + unsigned vtxbuf_nr; + struct nvfx_vtxelt_state *vtxelt; +}; + +static INLINE struct nvfx_context * +nvfx_context(struct pipe_context *pipe) +{ + return (struct nvfx_context *)pipe; +} + +struct nvfx_state_entry { + boolean (*validate)(struct nvfx_context *nvfx); + struct { + unsigned pipe; + unsigned hw; + } dirty; +}; + +extern struct nvfx_state_entry nvfx_state_blend; +extern struct nvfx_state_entry nvfx_state_blend_colour; +extern struct nvfx_state_entry nvfx_state_fragprog; +extern struct nvfx_state_entry nvfx_state_fragtex; +extern struct nvfx_state_entry nvfx_state_framebuffer; +extern struct nvfx_state_entry nvfx_state_rasterizer; +extern struct nvfx_state_entry nvfx_state_scissor; +extern struct nvfx_state_entry nvfx_state_sr; +extern struct nvfx_state_entry nvfx_state_stipple; +extern struct nvfx_state_entry nvfx_state_vbo; +extern struct nvfx_state_entry nvfx_state_vertprog; +extern struct nvfx_state_entry nvfx_state_viewport; +extern struct nvfx_state_entry nvfx_state_vtxfmt; +extern struct nvfx_state_entry nvfx_state_zsa; + +extern void nvfx_init_query_functions(struct nvfx_context *nvfx); +extern void nvfx_init_surface_functions(struct nvfx_context *nvfx); + +/* nvfx_context.c */ +struct pipe_context * +nvfx_create(struct pipe_screen *pscreen, void *priv); + +/* nvfx_clear.c */ +extern void nvfx_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); + +/* nvfx_draw.c */ +extern struct draw_stage *nvfx_draw_render_stage(struct nvfx_context *nvfx); +extern void nvfx_draw_elements_swtnl(struct pipe_context *pipe, + struct pipe_buffer *idxbuf, + unsigned ib_size, unsigned mode, + unsigned start, unsigned count); + +/* nvfx_fragprog.c */ +extern void nvfx_fragprog_destroy(struct nvfx_context *, + struct nvfx_fragment_program *); + +/* nv30_fragtex.c */ +extern void +nv30_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso); +extern void nv30_fragtex_bind(struct nvfx_context *); +extern struct nouveau_stateobj * +nv30_fragtex_build(struct nvfx_context *nvfx, int unit); + +/* nv40_fragtex.c */ +extern void +nv40_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso); +extern void nv40_fragtex_bind(struct nvfx_context *); +extern struct nouveau_stateobj * +nv40_fragtex_build(struct nvfx_context *nvfx, int unit); + +/* nvfx_state.c */ +extern void nvfx_init_state_functions(struct nvfx_context *nvfx); + +/* nvfx_state_emit.c */ +extern void nvfx_state_flush_notify(struct nouveau_channel *chan); +extern boolean nvfx_state_validate(struct nvfx_context *nvfx); +extern boolean nvfx_state_validate_swtnl(struct nvfx_context *nvfx); +extern void nvfx_state_emit(struct nvfx_context *nvfx); + +/* nvfx_transfer.c */ +extern void nvfx_init_transfer_functions(struct nvfx_context *nvfx); + +/* nvfx_vbo.c */ +extern void nvfx_draw_arrays(struct pipe_context *, unsigned mode, + unsigned start, unsigned count); +extern void nvfx_draw_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, + unsigned count); + +/* nvfx_vertprog.c */ +extern void nvfx_vertprog_destroy(struct nvfx_context *, + struct nvfx_vertex_program *); + +#endif diff --git a/src/gallium/drivers/nvfx/nvfx_draw.c b/src/gallium/drivers/nvfx/nvfx_draw.c new file mode 100644 index 00000000000..5379b29efd1 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_draw.c @@ -0,0 +1,350 @@ +#include "pipe/p_shader_tokens.h" +#include "util/u_inlines.h" +#include "tgsi/tgsi_ureg.h" + +#include "util/u_pack_color.h" + +#include "draw/draw_context.h" +#include "draw/draw_vertex.h" +#include "draw/draw_pipe.h" + +#include "nvfx_context.h" +#include "nv30_vertprog.h" +#include "nv40_vertprog.h" + +/* Simple, but crappy, swtnl path, hopefully we wont need to hit this very + * often at all. Uses "quadro style" vertex submission + a fixed vertex + * layout to avoid the need to generate a vertex program or vtxfmt. + */ + +struct nvfx_render_stage { + struct draw_stage stage; + struct nvfx_context *nvfx; + unsigned prim; +}; + +static INLINE struct nvfx_render_stage * +nvfx_render_stage(struct draw_stage *stage) +{ + return (struct nvfx_render_stage *)stage; +} + +static INLINE void +nvfx_render_vertex(struct nvfx_context *nvfx, const struct vertex_header *v) +{ + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned i; + + for (i = 0; i < nvfx->swtnl.nr_attribs; i++) { + unsigned idx = nvfx->swtnl.draw[i]; + unsigned hw = nvfx->swtnl.hw[i]; + + switch (nvfx->swtnl.emit[i]) { + case EMIT_OMIT: + break; + case EMIT_1F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_1F(hw), 1); + OUT_RING (chan, fui(v->data[idx][0])); + break; + case EMIT_2F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_2F_X(hw), 2); + OUT_RING (chan, fui(v->data[idx][0])); + OUT_RING (chan, fui(v->data[idx][1])); + break; + case EMIT_3F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_3F_X(hw), 3); + OUT_RING (chan, fui(v->data[idx][0])); + OUT_RING (chan, fui(v->data[idx][1])); + OUT_RING (chan, fui(v->data[idx][2])); + break; + case EMIT_4F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4F_X(hw), 4); + OUT_RING (chan, fui(v->data[idx][0])); + OUT_RING (chan, fui(v->data[idx][1])); + OUT_RING (chan, fui(v->data[idx][2])); + OUT_RING (chan, fui(v->data[idx][3])); + break; + case 0xff: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4F_X(hw), 4); + OUT_RING (chan, fui(v->data[idx][0] / v->data[idx][3])); + OUT_RING (chan, fui(v->data[idx][1] / v->data[idx][3])); + OUT_RING (chan, fui(v->data[idx][2] / v->data[idx][3])); + OUT_RING (chan, fui(1.0f / v->data[idx][3])); + break; + case EMIT_4UB: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4UB(hw), 1); + OUT_RING (chan, pack_ub4(float_to_ubyte(v->data[idx][0]), + float_to_ubyte(v->data[idx][1]), + float_to_ubyte(v->data[idx][2]), + float_to_ubyte(v->data[idx][3]))); + break; + default: + assert(0); + break; + } + } +} + +static INLINE void +nvfx_render_prim(struct draw_stage *stage, struct prim_header *prim, + unsigned mode, unsigned count) +{ + struct nvfx_render_stage *rs = nvfx_render_stage(stage); + struct nvfx_context *nvfx = rs->nvfx; + + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned i; + + /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */ + if (AVAIL_RING(chan) < ((count * 20) + 6)) { + if (rs->prim != NV34TCL_VERTEX_BEGIN_END_STOP) { + NOUVEAU_ERR("AIII, missed flush\n"); + assert(0); + } + FIRE_RING(chan); + nvfx_state_emit(nvfx); + } + + /* Switch primitive modes if necessary */ + if (rs->prim != mode) { + if (rs->prim != NV34TCL_VERTEX_BEGIN_END_STOP) { + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, NV34TCL_VERTEX_BEGIN_END_STOP); + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, mode); + rs->prim = mode; + } + + /* Emit vertex data */ + for (i = 0; i < count; i++) + nvfx_render_vertex(nvfx, prim->v[i]); + + /* If it's likely we'll need to empty the push buffer soon, finish + * off the primitive now. + */ + if (AVAIL_RING(chan) < ((count * 20) + 6)) { + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, NV34TCL_VERTEX_BEGIN_END_STOP); + rs->prim = NV34TCL_VERTEX_BEGIN_END_STOP; + } +} + +static void +nvfx_render_point(struct draw_stage *draw, struct prim_header *prim) +{ + nvfx_render_prim(draw, prim, NV34TCL_VERTEX_BEGIN_END_POINTS, 1); +} + +static void +nvfx_render_line(struct draw_stage *draw, struct prim_header *prim) +{ + nvfx_render_prim(draw, prim, NV34TCL_VERTEX_BEGIN_END_LINES, 2); +} + +static void +nvfx_render_tri(struct draw_stage *draw, struct prim_header *prim) +{ + nvfx_render_prim(draw, prim, NV34TCL_VERTEX_BEGIN_END_TRIANGLES, 3); +} + +static void +nvfx_render_flush(struct draw_stage *draw, unsigned flags) +{ + struct nvfx_render_stage *rs = nvfx_render_stage(draw); + struct nvfx_context *nvfx = rs->nvfx; + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + if (rs->prim != NV34TCL_VERTEX_BEGIN_END_STOP) { + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, NV34TCL_VERTEX_BEGIN_END_STOP); + rs->prim = NV34TCL_VERTEX_BEGIN_END_STOP; + } +} + +static void +nvfx_render_reset_stipple_counter(struct draw_stage *draw) +{ +} + +static void +nvfx_render_destroy(struct draw_stage *draw) +{ + FREE(draw); +} + +static struct nvfx_vertex_program * +nvfx_create_drawvp(struct nvfx_context *nvfx) +{ + struct ureg_program *ureg; + uint i; + + ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + if (ureg == NULL) + return NULL; + + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0), ureg_DECL_vs_input(ureg, 0)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0), ureg_DECL_vs_input(ureg, 3)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1), ureg_DECL_vs_input(ureg, 4)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_BCOLOR, 0), ureg_DECL_vs_input(ureg, 3)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_BCOLOR, 1), ureg_DECL_vs_input(ureg, 4)); + ureg_MOV(ureg, + ureg_writemask(ureg_DECL_output(ureg, TGSI_SEMANTIC_FOG, 1), TGSI_WRITEMASK_X), + ureg_DECL_vs_input(ureg, 5)); + for (i = 0; i < 8; ++i) + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, i), ureg_DECL_vs_input(ureg, 8 + i)); + + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, &nvfx->pipe ); +} + +struct draw_stage * +nvfx_draw_render_stage(struct nvfx_context *nvfx) +{ + struct nvfx_render_stage *render = CALLOC_STRUCT(nvfx_render_stage); + + if (!nvfx->swtnl.vertprog) + nvfx->swtnl.vertprog = nvfx_create_drawvp(nvfx); + + render->nvfx = nvfx; + render->stage.draw = nvfx->draw; + render->stage.point = nvfx_render_point; + render->stage.line = nvfx_render_line; + render->stage.tri = nvfx_render_tri; + render->stage.flush = nvfx_render_flush; + render->stage.reset_stipple_counter = nvfx_render_reset_stipple_counter; + render->stage.destroy = nvfx_render_destroy; + + return &render->stage; +} + +void +nvfx_draw_elements_swtnl(struct pipe_context *pipe, + struct pipe_buffer *idxbuf, unsigned idxbuf_size, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct pipe_screen *pscreen = pipe->screen; + unsigned i; + void *map; + + if (!nvfx_state_validate_swtnl(nvfx)) + return; + nvfx->state.dirty &= ~(1ULL << NVFX_STATE_VTXBUF); + nvfx_state_emit(nvfx); + + for (i = 0; i < nvfx->vtxbuf_nr; i++) { + map = pipe_buffer_map(pscreen, nvfx->vtxbuf[i].buffer, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_vertex_buffer(nvfx->draw, i, map); + } + + if (idxbuf) { + map = pipe_buffer_map(pscreen, idxbuf, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_element_buffer(nvfx->draw, idxbuf_size, map); + } else { + draw_set_mapped_element_buffer(nvfx->draw, 0, NULL); + } + + if (nvfx->constbuf[PIPE_SHADER_VERTEX]) { + const unsigned nr = nvfx->constbuf_nr[PIPE_SHADER_VERTEX]; + + map = pipe_buffer_map(pscreen, + nvfx->constbuf[PIPE_SHADER_VERTEX], + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_constant_buffer(nvfx->draw, PIPE_SHADER_VERTEX, 0, + map, nr); + } + + draw_arrays(nvfx->draw, mode, start, count); + + for (i = 0; i < nvfx->vtxbuf_nr; i++) + pipe_buffer_unmap(pscreen, nvfx->vtxbuf[i].buffer); + + if (idxbuf) + pipe_buffer_unmap(pscreen, idxbuf); + + if (nvfx->constbuf[PIPE_SHADER_VERTEX]) + pipe_buffer_unmap(pscreen, nvfx->constbuf[PIPE_SHADER_VERTEX]); + + draw_flush(nvfx->draw); + pipe->flush(pipe, 0, NULL); +} + +static INLINE void +emit_attrib(struct nvfx_context *nvfx, unsigned hw, unsigned emit, + unsigned semantic, unsigned index) +{ + unsigned draw_out = draw_find_shader_output(nvfx->draw, semantic, index); + unsigned a = nvfx->swtnl.nr_attribs++; + + nvfx->swtnl.hw[a] = hw; + nvfx->swtnl.emit[a] = emit; + nvfx->swtnl.draw[a] = draw_out; +} + +static boolean +nvfx_state_vtxfmt_validate(struct nvfx_context *nvfx) +{ + struct nvfx_fragment_program *fp = nvfx->fragprog; + unsigned colour = 0, texcoords = 0, fog = 0, i; + + /* Determine needed fragprog inputs */ + for (i = 0; i < fp->info.num_inputs; i++) { + switch (fp->info.input_semantic_name[i]) { + case TGSI_SEMANTIC_POSITION: + break; + case TGSI_SEMANTIC_COLOR: + colour |= (1 << fp->info.input_semantic_index[i]); + break; + case TGSI_SEMANTIC_GENERIC: + texcoords |= (1 << fp->info.input_semantic_index[i]); + break; + case TGSI_SEMANTIC_FOG: + fog = 1; + break; + default: + assert(0); + } + } + + nvfx->swtnl.nr_attribs = 0; + + /* Map draw vtxprog output to hw attribute IDs */ + for (i = 0; i < 2; i++) { + if (!(colour & (1 << i))) + continue; + emit_attrib(nvfx, 3 + i, EMIT_4F, TGSI_SEMANTIC_COLOR, i); + } + + for (i = 0; i < 8; i++) { + if (!(texcoords & (1 << i))) + continue; + emit_attrib(nvfx, 8 + i, EMIT_4F, TGSI_SEMANTIC_GENERIC, i); + } + + if (fog) { + emit_attrib(nvfx, 5, EMIT_1F, TGSI_SEMANTIC_FOG, 0); + } + + emit_attrib(nvfx, 0, 0xff, TGSI_SEMANTIC_POSITION, 0); + + return FALSE; +} + +struct nvfx_state_entry nvfx_state_vtxfmt = { + .validate = nvfx_state_vtxfmt_validate, + .dirty = { + .pipe = NVFX_NEW_ARRAYS | NVFX_NEW_FRAGPROG, + .hw = 0 + } +}; diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nvfx/nvfx_fragprog.c index dc24f9b08a5..76351430f44 100644 --- a/src/gallium/drivers/nv40/nv40_fragprog.c +++ b/src/gallium/drivers/nvfx/nvfx_fragprog.c @@ -7,37 +7,20 @@ #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" -#include "nv40_context.h" - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 1 -#define MASK_Y 2 -#define MASK_Z 4 -#define MASK_W 8 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE NV40_FP_OP_DST_SCALE_1X -#define DEF_CTEST NV40_FP_OP_COND_TR -#include "nv40_shader.h" - -#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv40_sr_neg((s)) -#define abs(s) nv40_sr_abs((s)) -#define scale(s,v) nv40_sr_scale((s), NV40_FP_OP_DST_SCALE_##v) +#include "nvfx_context.h" +#include "nvfx_shader.h" #define MAX_CONSTS 128 #define MAX_IMM 32 -struct nv40_fpc { - struct nv40_fragment_program *fp; +struct nvfx_fpc { + struct nvfx_fragment_program *fp; uint attrib_map[PIPE_MAX_SHADER_INPUTS]; unsigned r_temps; unsigned r_temps_discard; - struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; - struct nv40_sreg *r_temp; + struct nvfx_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; + struct nvfx_sreg *r_temp; int num_regs; @@ -50,35 +33,35 @@ struct nv40_fpc { } consts[MAX_CONSTS]; int nr_consts; - struct nv40_sreg imm[MAX_IMM]; + struct nvfx_sreg imm[MAX_IMM]; unsigned nr_imm; }; -static INLINE struct nv40_sreg -temp(struct nv40_fpc *fpc) +static INLINE struct nvfx_sreg +temp(struct nvfx_fpc *fpc) { int idx = ffs(~fpc->r_temps) - 1; if (idx < 0) { NOUVEAU_ERR("out of temps!!\n"); assert(0); - return nv40_sr(NV40SR_TEMP, 0); + return nvfx_sr(NVFXSR_TEMP, 0); } fpc->r_temps |= (1 << idx); fpc->r_temps_discard |= (1 << idx); - return nv40_sr(NV40SR_TEMP, idx); + return nvfx_sr(NVFXSR_TEMP, idx); } static INLINE void -release_temps(struct nv40_fpc *fpc) +release_temps(struct nvfx_fpc *fpc) { fpc->r_temps &= ~fpc->r_temps_discard; fpc->r_temps_discard = 0; } -static INLINE struct nv40_sreg -constant(struct nv40_fpc *fpc, int pipe, float vals[4]) +static INLINE struct nvfx_sreg +constant(struct nvfx_fpc *fpc, int pipe, float vals[4]) { int idx; @@ -89,45 +72,45 @@ constant(struct nv40_fpc *fpc, int pipe, float vals[4]) fpc->consts[idx].pipe = pipe; if (pipe == -1) memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float)); - return nv40_sr(NV40SR_CONST, idx); + return nvfx_sr(NVFXSR_CONST, idx); } #define arith(cc,s,o,d,m,s0,s1,s2) \ - nv40_fp_arith((cc), (s), NV40_FP_OP_OPCODE_##o, \ + nvfx_fp_arith((cc), (s), NVFX_FP_OP_OPCODE_##o, \ (d), (m), (s0), (s1), (s2)) #define tex(cc,s,o,u,d,m,s0,s1,s2) \ - nv40_fp_tex((cc), (s), NV40_FP_OP_OPCODE_##o, (u), \ + nvfx_fp_tex((cc), (s), NVFX_FP_OP_OPCODE_##o, (u), \ (d), (m), (s0), none, none) static void -grow_insns(struct nv40_fpc *fpc, int size) +grow_insns(struct nvfx_fpc *fpc, int size) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; fp->insn_len += size; fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len); } static void -emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src) +emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_sreg src) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; uint32_t *hw = &fp->insn[fpc->inst_offset]; uint32_t sr = 0; switch (src.type) { - case NV40SR_INPUT: - sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT); - hw[0] |= (src.index << NV40_FP_OP_INPUT_SRC_SHIFT); + case NVFXSR_INPUT: + sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT); + hw[0] |= (src.index << NVFX_FP_OP_INPUT_SRC_SHIFT); break; - case NV40SR_OUTPUT: - sr |= NV40_FP_REG_SRC_HALF; + case NVFXSR_OUTPUT: + sr |= NVFX_FP_REG_SRC_HALF; /* fall-through */ - case NV40SR_TEMP: - sr |= (NV40_FP_REG_TYPE_TEMP << NV40_FP_REG_TYPE_SHIFT); - sr |= (src.index << NV40_FP_REG_SRC_SHIFT); + case NVFXSR_TEMP: + sr |= (NVFX_FP_REG_TYPE_TEMP << NVFX_FP_REG_TYPE_SHIFT); + sr |= (src.index << NVFX_FP_REG_SRC_SHIFT); break; - case NV40SR_CONST: + case NVFXSR_CONST: if (!fpc->have_const) { grow_insns(fpc, 4); fpc->have_const = 1; @@ -135,7 +118,7 @@ emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src) hw = &fp->insn[fpc->inst_offset]; if (fpc->consts[src.index].pipe >= 0) { - struct nv40_fragment_program_data *fpd; + struct nvfx_fragment_program_data *fpd; fp->consts = realloc(fp->consts, ++fp->nr_consts * sizeof(*fpd)); @@ -149,63 +132,63 @@ emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src) sizeof(uint32_t) * 4); } - sr |= (NV40_FP_REG_TYPE_CONST << NV40_FP_REG_TYPE_SHIFT); + sr |= (NVFX_FP_REG_TYPE_CONST << NVFX_FP_REG_TYPE_SHIFT); break; - case NV40SR_NONE: - sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT); + case NVFXSR_NONE: + sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT); break; default: assert(0); } if (src.negate) - sr |= NV40_FP_REG_NEGATE; + sr |= NVFX_FP_REG_NEGATE; if (src.abs) hw[1] |= (1 << (29 + pos)); - sr |= ((src.swz[0] << NV40_FP_REG_SWZ_X_SHIFT) | - (src.swz[1] << NV40_FP_REG_SWZ_Y_SHIFT) | - (src.swz[2] << NV40_FP_REG_SWZ_Z_SHIFT) | - (src.swz[3] << NV40_FP_REG_SWZ_W_SHIFT)); + sr |= ((src.swz[0] << NVFX_FP_REG_SWZ_X_SHIFT) | + (src.swz[1] << NVFX_FP_REG_SWZ_Y_SHIFT) | + (src.swz[2] << NVFX_FP_REG_SWZ_Z_SHIFT) | + (src.swz[3] << NVFX_FP_REG_SWZ_W_SHIFT)); hw[pos + 1] |= sr; } static void -emit_dst(struct nv40_fpc *fpc, struct nv40_sreg dst) +emit_dst(struct nvfx_fpc *fpc, struct nvfx_sreg dst) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; uint32_t *hw = &fp->insn[fpc->inst_offset]; switch (dst.type) { - case NV40SR_TEMP: + case NVFXSR_TEMP: if (fpc->num_regs < (dst.index + 1)) fpc->num_regs = dst.index + 1; break; - case NV40SR_OUTPUT: + case NVFXSR_OUTPUT: if (dst.index == 1) { fp->fp_control |= 0xe; } else { - hw[0] |= NV40_FP_OP_OUT_REG_HALF; + hw[0] |= NVFX_FP_OP_OUT_REG_HALF; } break; - case NV40SR_NONE: + case NVFXSR_NONE: hw[0] |= (1 << 30); break; default: assert(0); } - hw[0] |= (dst.index << NV40_FP_OP_OUT_REG_SHIFT); + hw[0] |= (dst.index << NVFX_FP_OP_OUT_REG_SHIFT); } static void -nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op, - struct nv40_sreg dst, int mask, - struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2) +nvfx_fp_arith(struct nvfx_fpc *fpc, int sat, int op, + struct nvfx_sreg dst, int mask, + struct nvfx_sreg s0, struct nvfx_sreg s1, struct nvfx_sreg s2) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; uint32_t *hw; fpc->inst_offset = fp->insn_len; @@ -214,22 +197,22 @@ nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op, hw = &fp->insn[fpc->inst_offset]; memset(hw, 0, sizeof(uint32_t) * 4); - if (op == NV40_FP_OP_OPCODE_KIL) - fp->fp_control |= NV40TCL_FP_CONTROL_KIL; - hw[0] |= (op << NV40_FP_OP_OPCODE_SHIFT); - hw[0] |= (mask << NV40_FP_OP_OUTMASK_SHIFT); - hw[2] |= (dst.dst_scale << NV40_FP_OP_DST_SCALE_SHIFT); + if (op == NVFX_FP_OP_OPCODE_KIL) + fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL; + hw[0] |= (op << NVFX_FP_OP_OPCODE_SHIFT); + hw[0] |= (mask << NVFX_FP_OP_OUTMASK_SHIFT); + hw[2] |= (dst.dst_scale << NVFX_FP_OP_DST_SCALE_SHIFT); if (sat) - hw[0] |= NV40_FP_OP_OUT_SAT; + hw[0] |= NVFX_FP_OP_OUT_SAT; if (dst.cc_update) - hw[0] |= NV40_FP_OP_COND_WRITE_ENABLE; - hw[1] |= (dst.cc_test << NV40_FP_OP_COND_SHIFT); - hw[1] |= ((dst.cc_swz[0] << NV40_FP_OP_COND_SWZ_X_SHIFT) | - (dst.cc_swz[1] << NV40_FP_OP_COND_SWZ_Y_SHIFT) | - (dst.cc_swz[2] << NV40_FP_OP_COND_SWZ_Z_SHIFT) | - (dst.cc_swz[3] << NV40_FP_OP_COND_SWZ_W_SHIFT)); + hw[0] |= NVFX_FP_OP_COND_WRITE_ENABLE; + hw[1] |= (dst.cc_test << NVFX_FP_OP_COND_SHIFT); + hw[1] |= ((dst.cc_swz[0] << NVFX_FP_OP_COND_SWZ_X_SHIFT) | + (dst.cc_swz[1] << NVFX_FP_OP_COND_SWZ_Y_SHIFT) | + (dst.cc_swz[2] << NVFX_FP_OP_COND_SWZ_Z_SHIFT) | + (dst.cc_swz[3] << NVFX_FP_OP_COND_SWZ_W_SHIFT)); emit_dst(fpc, dst); emit_src(fpc, 0, s0); @@ -238,26 +221,26 @@ nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op, } static void -nv40_fp_tex(struct nv40_fpc *fpc, int sat, int op, int unit, - struct nv40_sreg dst, int mask, - struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2) +nvfx_fp_tex(struct nvfx_fpc *fpc, int sat, int op, int unit, + struct nvfx_sreg dst, int mask, + struct nvfx_sreg s0, struct nvfx_sreg s1, struct nvfx_sreg s2) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; - nv40_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); + nvfx_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); - fp->insn[fpc->inst_offset] |= (unit << NV40_FP_OP_TEX_UNIT_SHIFT); + fp->insn[fpc->inst_offset] |= (unit << NVFX_FP_OP_TEX_UNIT_SHIFT); fp->samplers |= (1 << unit); } -static INLINE struct nv40_sreg -tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc) +static INLINE struct nvfx_sreg +tgsi_src(struct nvfx_fpc *fpc, const struct tgsi_full_src_register *fsrc) { - struct nv40_sreg src; + struct nvfx_sreg src; switch (fsrc->Register.File) { case TGSI_FILE_INPUT: - src = nv40_sr(NV40SR_INPUT, + src = nvfx_sr(NVFXSR_INPUT, fpc->attrib_map[fsrc->Register.Index]); break; case TGSI_FILE_CONSTANT: @@ -288,18 +271,18 @@ tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc) return src; } -static INLINE struct nv40_sreg -tgsi_dst(struct nv40_fpc *fpc, const struct tgsi_full_dst_register *fdst) { +static INLINE struct nvfx_sreg +tgsi_dst(struct nvfx_fpc *fpc, const struct tgsi_full_dst_register *fdst) { switch (fdst->Register.File) { case TGSI_FILE_OUTPUT: return fpc->r_result[fdst->Register.Index]; case TGSI_FILE_TEMPORARY: return fpc->r_temp[fdst->Register.Index]; case TGSI_FILE_NULL: - return nv40_sr(NV40SR_NONE, 0); + return nvfx_sr(NVFXSR_NONE, 0); default: NOUVEAU_ERR("bad dst file %d\n", fdst->Register.File); - return nv40_sr(NV40SR_NONE, 0); + return nvfx_sr(NVFXSR_NONE, 0); } } @@ -308,52 +291,19 @@ tgsi_mask(uint tgsi) { int mask = 0; - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; + if (tgsi & TGSI_WRITEMASK_X) mask |= NVFX_FP_MASK_X; + if (tgsi & TGSI_WRITEMASK_Y) mask |= NVFX_FP_MASK_Y; + if (tgsi & TGSI_WRITEMASK_Z) mask |= NVFX_FP_MASK_Z; + if (tgsi & TGSI_WRITEMASK_W) mask |= NVFX_FP_MASK_W; return mask; } static boolean -src_native_swz(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc, - struct nv40_sreg *src) -{ - const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - struct nv40_sreg tgsi = tgsi_src(fpc, fsrc); - uint mask = 0; - uint c; - - for (c = 0; c < 4; c++) { - switch (tgsi_util_get_full_src_register_swizzle(fsrc, c)) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - mask |= (1 << c); - break; - default: - assert(0); - } - } - - if (mask == MASK_ALL) - return TRUE; - - *src = temp(fpc); - - if (mask) - arith(fpc, 0, MOV, *src, mask, tgsi, none, none); - - return FALSE; -} - -static boolean -nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, +nvfx_fragprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_fpc *fpc, const struct tgsi_full_instruction *finst) { - const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - struct nv40_sreg src[3], dst, tmp; + const struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0); + struct nvfx_sreg src[3], dst, tmp; int mask, sat, unit; int ai = -1, ci = -1, ii = -1; int i; @@ -377,23 +327,12 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, switch (fsrc->Register.File) { case TGSI_FILE_INPUT: - case TGSI_FILE_CONSTANT: - case TGSI_FILE_TEMPORARY: - if (!src_native_swz(fpc, fsrc, &src[i])) - continue; - break; - default: - break; - } - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: if (ai == -1 || ai == fsrc->Register.Index) { ai = fsrc->Register.Index; src[i] = tgsi_src(fpc, fsrc); } else { src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, + arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none); } break; @@ -404,7 +343,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, src[i] = tgsi_src(fpc, fsrc); } else { src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, + arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none); } break; @@ -415,7 +354,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, src[i] = tgsi_src(fpc, fsrc); } else { src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, + arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none); } break; @@ -445,25 +384,25 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, arith(fpc, sat, ADD, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_CMP: - tmp = nv40_sr(NV40SR_NONE, 0); + tmp = nvfx_sr(NVFXSR_NONE, 0); tmp.cc_update = 1; arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none); - dst.cc_test = NV40_VP_INST_COND_GE; + dst.cc_test = NVFX_COND_GE; arith(fpc, sat, MOV, dst, mask, src[2], none, none); - dst.cc_test = NV40_VP_INST_COND_LT; + dst.cc_test = NVFX_COND_LT; arith(fpc, sat, MOV, dst, mask, src[1], none, none); break; case TGSI_OPCODE_COS: arith(fpc, sat, COS, dst, mask, src[0], none, none); break; case TGSI_OPCODE_DDX: - if (mask & (MASK_Z | MASK_W)) { + if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) { tmp = temp(fpc); - arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, + arith(fpc, sat, DDX, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none); - arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W, + arith(fpc, 0, MOV, tmp, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none); - arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, src[0], + arith(fpc, sat, DDX, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none); arith(fpc, 0, MOV, dst, mask, tmp, none, none); } else { @@ -471,13 +410,13 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, } break; case TGSI_OPCODE_DDY: - if (mask & (MASK_Z | MASK_W)) { + if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) { tmp = temp(fpc); - arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, + arith(fpc, sat, DDY, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none); - arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W, + arith(fpc, 0, MOV, tmp, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none); - arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, src[0], + arith(fpc, sat, DDY, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none); arith(fpc, 0, MOV, dst, mask, tmp, none, none); } else { @@ -492,7 +431,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, break; case TGSI_OPCODE_DPH: tmp = temp(fpc); - arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none); + arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_X, src[0], src[1], none); arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X), swz(src[1], W, W, W, W), none); break; @@ -512,10 +451,10 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, arith(fpc, 0, KIL, none, 0, none, none, none); break; case TGSI_OPCODE_KIL: - dst = nv40_sr(NV40SR_NONE, 0); + dst = nvfx_sr(NVFXSR_NONE, 0); dst.cc_update = 1; - arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none); - dst.cc_update = 0; dst.cc_test = NV40_FP_OP_COND_LT; + arith(fpc, 0, MOV, dst, NVFX_FP_MASK_ALL, src[0], none, none); + dst.cc_update = 0; dst.cc_test = NVFX_COND_LT; arith(fpc, 0, KIL, dst, 0, none, none, none); break; case TGSI_OPCODE_LG2: @@ -523,9 +462,13 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, break; // case TGSI_OPCODE_LIT: case TGSI_OPCODE_LRP: - tmp = temp(fpc); - arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]); - arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp); + if(!nvfx->is_nv4x) + arith(fpc, sat, LRP_NV30, dst, mask, src[0], src[1], src[2]); + else { + tmp = temp(fpc); + arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]); + arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp); + } break; case TGSI_OPCODE_MAD: arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]); @@ -543,13 +486,17 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, arith(fpc, sat, MUL, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_POW: - tmp = temp(fpc); - arith(fpc, 0, LG2, tmp, MASK_X, - swz(src[0], X, X, X, X), none, none); - arith(fpc, 0, MUL, tmp, MASK_X, swz(tmp, X, X, X, X), - swz(src[1], X, X, X, X), none); - arith(fpc, sat, EX2, dst, mask, - swz(tmp, X, X, X, X), none, none); + if(!nvfx->is_nv4x) + arith(fpc, sat, POW_NV30, dst, mask, src[0], src[1], none); + else { + tmp = temp(fpc); + arith(fpc, 0, LG2, tmp, NVFX_FP_MASK_X, + swz(src[0], X, X, X, X), none, none); + arith(fpc, 0, MUL, tmp, NVFX_FP_MASK_X, swz(tmp, X, X, X, X), + swz(src[1], X, X, X, X), none); + arith(fpc, sat, EX2, dst, mask, + swz(tmp, X, X, X, X), none, none); + } break; case TGSI_OPCODE_RCP: arith(fpc, sat, RCP, dst, mask, src[0], none, none); @@ -558,42 +505,50 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, assert(0); break; case TGSI_OPCODE_RFL: - tmp = temp(fpc); - arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[0], none); - arith(fpc, 0, DP3, tmp, MASK_Y, src[0], src[1], none); - arith(fpc, 0, DIV, scale(tmp, 2X), MASK_Z, - swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none); - arith(fpc, sat, MAD, dst, mask, - swz(tmp, Z, Z, Z, Z), src[0], neg(src[1])); + if(!nvfx->is_nv4x) + arith(fpc, 0, RFL_NV30, dst, mask, src[0], src[1], none); + else { + tmp = temp(fpc); + arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_X, src[0], src[0], none); + arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_Y, src[0], src[1], none); + arith(fpc, 0, DIV, scale(tmp, 2X), NVFX_FP_MASK_Z, + swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none); + arith(fpc, sat, MAD, dst, mask, + swz(tmp, Z, Z, Z, Z), src[0], neg(src[1])); + } break; case TGSI_OPCODE_RSQ: - tmp = temp(fpc); - arith(fpc, 0, LG2, scale(tmp, INV_2X), MASK_X, - abs(swz(src[0], X, X, X, X)), none, none); - arith(fpc, sat, EX2, dst, mask, - neg(swz(tmp, X, X, X, X)), none, none); + if(!nvfx->is_nv4x) + arith(fpc, sat, RSQ_NV30, dst, mask, abs(swz(src[0], X, X, X, X)), none, none); + else { + tmp = temp(fpc); + arith(fpc, 0, LG2, scale(tmp, INV_2X), NVFX_FP_MASK_X, + abs(swz(src[0], X, X, X, X)), none, none); + arith(fpc, sat, EX2, dst, mask, + neg(swz(tmp, X, X, X, X)), none, none); + } break; case TGSI_OPCODE_SCS: /* avoid overwriting the source */ - if(src[0].swz[SWZ_X] != SWZ_X) + if(src[0].swz[NVFX_SWZ_X] != NVFX_SWZ_X) { - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, + if (mask & NVFX_FP_MASK_X) { + arith(fpc, sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none); } - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, + if (mask & NVFX_FP_MASK_Y) { + arith(fpc, sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none); } } else { - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, + if (mask & NVFX_FP_MASK_Y) { + arith(fpc, sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none); } - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, + if (mask & NVFX_FP_MASK_X) { + arith(fpc, sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none); } } @@ -641,7 +596,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, tmp = temp(fpc); arith(fpc, 0, MUL, tmp, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(fpc, sat, MAD, dst, (mask & ~MASK_W), + arith(fpc, sat, MAD, dst, (mask & ~NVFX_FP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)); break; @@ -655,32 +610,32 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, } static boolean -nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc, +nvfx_fragprog_parse_decl_attrib(struct nvfx_context* nvfx, struct nvfx_fpc *fpc, const struct tgsi_full_declaration *fdec) { int hw; switch (fdec->Semantic.Name) { case TGSI_SEMANTIC_POSITION: - hw = NV40_FP_OP_INPUT_SRC_POSITION; + hw = NVFX_FP_OP_INPUT_SRC_POSITION; break; case TGSI_SEMANTIC_COLOR: if (fdec->Semantic.Index == 0) { - hw = NV40_FP_OP_INPUT_SRC_COL0; + hw = NVFX_FP_OP_INPUT_SRC_COL0; } else if (fdec->Semantic.Index == 1) { - hw = NV40_FP_OP_INPUT_SRC_COL1; + hw = NVFX_FP_OP_INPUT_SRC_COL1; } else { NOUVEAU_ERR("bad colour semantic index\n"); return FALSE; } break; case TGSI_SEMANTIC_FOG: - hw = NV40_FP_OP_INPUT_SRC_FOGC; + hw = NVFX_FP_OP_INPUT_SRC_FOGC; break; case TGSI_SEMANTIC_GENERIC: if (fdec->Semantic.Index <= 7) { - hw = NV40_FP_OP_INPUT_SRC_TC(fdec->Semantic. + hw = NVFX_FP_OP_INPUT_SRC_TC(fdec->Semantic. Index); } else { NOUVEAU_ERR("bad generic semantic index\n"); @@ -697,7 +652,7 @@ nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc, } static boolean -nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc, +nvfx_fragprog_parse_decl_output(struct nvfx_context* nvfx, struct nvfx_fpc *fpc, const struct tgsi_full_declaration *fdec) { unsigned idx = fdec->Range.First; @@ -708,12 +663,14 @@ nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc, hw = 1; break; case TGSI_SEMANTIC_COLOR: + hw = ~0; switch (fdec->Semantic.Index) { case 0: hw = 0; break; case 1: hw = 2; break; case 2: hw = 3; break; case 3: hw = 4; break; - default: + } + if(hw > ((nvfx->is_nv4x) ? 4 : 2)) { NOUVEAU_ERR("bad rcol index\n"); return FALSE; } @@ -723,13 +680,13 @@ nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc, return FALSE; } - fpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw); + fpc->r_result[idx] = nvfx_sr(NVFXSR_OUTPUT, hw); fpc->r_temps |= (1 << hw); return TRUE; } static boolean -nv40_fragprog_prepare(struct nv40_fpc *fpc) +nvfx_fragprog_prepare(struct nvfx_context* nvfx, struct nvfx_fpc *fpc) { struct tgsi_parse_context p; int high_temp = -1, i; @@ -746,11 +703,11 @@ nv40_fragprog_prepare(struct nv40_fpc *fpc) fdec = &p.FullToken.FullDeclaration; switch (fdec->Declaration.File) { case TGSI_FILE_INPUT: - if (!nv40_fragprog_parse_decl_attrib(fpc, fdec)) + if (!nvfx_fragprog_parse_decl_attrib(nvfx, fpc, fdec)) goto out_err; break; case TGSI_FILE_OUTPUT: - if (!nv40_fragprog_parse_decl_output(fpc, fdec)) + if (!nvfx_fragprog_parse_decl_output(nvfx, fpc, fdec)) goto out_err; break; case TGSI_FILE_TEMPORARY: @@ -787,7 +744,7 @@ nv40_fragprog_prepare(struct nv40_fpc *fpc) tgsi_parse_free(&p); if (++high_temp) { - fpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg)); + fpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_sreg)); for (i = 0; i < high_temp; i++) fpc->r_temp[i] = temp(fpc); fpc->r_temps_discard = 0; @@ -803,19 +760,19 @@ out_err: } static void -nv40_fragprog_translate(struct nv40_context *nv40, - struct nv40_fragment_program *fp) +nvfx_fragprog_translate(struct nvfx_context *nvfx, + struct nvfx_fragment_program *fp) { struct tgsi_parse_context parse; - struct nv40_fpc *fpc = NULL; + struct nvfx_fpc *fpc = NULL; - fpc = CALLOC(1, sizeof(struct nv40_fpc)); + fpc = CALLOC(1, sizeof(struct nvfx_fpc)); if (!fpc) return; fpc->fp = fp; fpc->num_regs = 2; - if (!nv40_fragprog_prepare(fpc)) { + if (!nvfx_fragprog_prepare(nvfx, fpc)) { FREE(fpc); return; } @@ -831,7 +788,7 @@ nv40_fragprog_translate(struct nv40_context *nv40, const struct tgsi_full_instruction *finst; finst = &parse.FullToken.FullInstruction; - if (!nv40_fragprog_parse_instruction(fpc, finst)) + if (!nvfx_fragprog_parse_instruction(nvfx, fpc, finst)) goto out_err; } break; @@ -840,7 +797,10 @@ nv40_fragprog_translate(struct nv40_context *nv40, } } - fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT; + if(!nvfx->is_nv4x) + fp->fp_control |= (fpc->num_regs-1)/2; + else + fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT; /* Terminate final instruction */ fp->insn[fpc->inst_offset] |= 0x00000001; @@ -862,10 +822,10 @@ out_err: } static void -nv40_fragprog_upload(struct nv40_context *nv40, - struct nv40_fragment_program *fp) +nvfx_fragprog_upload(struct nvfx_context *nvfx, + struct nvfx_fragment_program *fp) { - struct pipe_screen *pscreen = nv40->pipe.screen; + struct pipe_screen *pscreen = nvfx->pipe.screen; const uint32_t le = 1; uint32_t *map; int i; @@ -896,12 +856,12 @@ nv40_fragprog_upload(struct nv40_context *nv40, } static boolean -nv40_fragprog_validate(struct nv40_context *nv40) +nvfx_fragprog_validate(struct nvfx_context *nvfx) { - struct nv40_fragment_program *fp = nv40->fragprog; + struct nvfx_fragment_program *fp = nvfx->fragprog; struct pipe_buffer *constbuf = - nv40->constbuf[PIPE_SHADER_FRAGMENT]; - struct pipe_screen *pscreen = nv40->pipe.screen; + nvfx->constbuf[PIPE_SHADER_FRAGMENT]; + struct pipe_screen *pscreen = nvfx->pipe.screen; struct nouveau_stateobj *so; boolean new_consts = FALSE; int i; @@ -909,24 +869,31 @@ nv40_fragprog_validate(struct nv40_context *nv40) if (fp->translated) goto update_constants; - nv40->fallback_swrast &= ~NV40_NEW_FRAGPROG; - nv40_fragprog_translate(nv40, fp); + nvfx->fallback_swrast &= ~NVFX_NEW_FRAGPROG; + nvfx_fragprog_translate(nvfx, fp); if (!fp->translated) { - nv40->fallback_swrast |= NV40_NEW_FRAGPROG; + nvfx->fallback_swrast |= NVFX_NEW_FRAGPROG; return FALSE; } fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4); - nv40_fragprog_upload(nv40, fp); + nvfx_fragprog_upload(nvfx, fp); - so = so_new(2, 2, 1); - so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1); + so = so_new(4, 4, 1); + so_method(so, nvfx->screen->eng3d, NV34TCL_FP_ACTIVE_PROGRAM, 1); so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | - NOUVEAU_BO_OR, NV40TCL_FP_ADDRESS_DMA0, - NV40TCL_FP_ADDRESS_DMA1); - so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1); + NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0, + NV34TCL_FP_ACTIVE_PROGRAM_DMA1); + so_method(so, nvfx->screen->eng3d, NV34TCL_FP_CONTROL, 1); so_data (so, fp->fp_control); + if(!nvfx->is_nv4x) { + so_method(so, nvfx->screen->eng3d, NV34TCL_FP_REG_CONTROL, 1); + so_data (so, (1<<16)|0x4); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_UNITS_ENABLE, 1); + so_data (so, fp->samplers); + } + so_ref(so, &fp->so); so_ref(NULL, &so); @@ -937,7 +904,7 @@ update_constants: map = pipe_buffer_map(pscreen, constbuf, PIPE_BUFFER_USAGE_CPU_READ); for (i = 0; i < fp->nr_consts; i++) { - struct nv40_fragment_program_data *fpd = &fp->consts[i]; + struct nvfx_fragment_program_data *fpd = &fp->consts[i]; uint32_t *p = &fp->insn[fpd->offset]; uint32_t *cb = (uint32_t *)&map[fpd->index * 4]; @@ -949,11 +916,11 @@ update_constants: pipe_buffer_unmap(pscreen, constbuf); if (new_consts) - nv40_fragprog_upload(nv40, fp); + nvfx_fragprog_upload(nvfx, fp); } - if (new_consts || fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) { - so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]); + if (new_consts || fp->so != nvfx->state.hw[NVFX_STATE_FRAGPROG]) { + so_ref(fp->so, &nvfx->state.hw[NVFX_STATE_FRAGPROG]); return TRUE; } @@ -961,8 +928,8 @@ update_constants: } void -nv40_fragprog_destroy(struct nv40_context *nv40, - struct nv40_fragment_program *fp) +nvfx_fragprog_destroy(struct nvfx_context *nvfx, + struct nvfx_fragment_program *fp) { if (fp->buffer) pipe_buffer_reference(&fp->buffer, NULL); @@ -974,11 +941,10 @@ nv40_fragprog_destroy(struct nv40_context *nv40, FREE(fp->insn); } -struct nv40_state_entry nv40_state_fragprog = { - .validate = nv40_fragprog_validate, +struct nvfx_state_entry nvfx_state_fragprog = { + .validate = nvfx_fragprog_validate, .dirty = { - .pipe = NV40_NEW_FRAGPROG, - .hw = NV40_STATE_FRAGPROG + .pipe = NVFX_NEW_FRAGPROG, + .hw = NVFX_STATE_FRAGPROG } }; - diff --git a/src/gallium/drivers/nvfx/nvfx_fragtex.c b/src/gallium/drivers/nvfx/nvfx_fragtex.c new file mode 100644 index 00000000000..84e4eb10042 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_fragtex.c @@ -0,0 +1,49 @@ +#include "nvfx_context.h" + +static boolean +nvfx_fragtex_validate(struct nvfx_context *nvfx) +{ + struct nvfx_fragment_program *fp = nvfx->fragprog; + struct nvfx_state *state = &nvfx->state; + struct nouveau_stateobj *so; + unsigned samplers, unit; + + samplers = state->fp_samplers & ~fp->samplers; + while (samplers) { + unit = ffs(samplers) - 1; + samplers &= ~(1 << unit); + + so = so_new(1, 1, 0); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_ENABLE(unit), 1); + so_data (so, 0); + so_ref(so, &nvfx->state.hw[NVFX_STATE_FRAGTEX0 + unit]); + so_ref(NULL, &so); + state->dirty |= (1ULL << (NVFX_STATE_FRAGTEX0 + unit)); + } + + samplers = nvfx->dirty_samplers & fp->samplers; + while (samplers) { + unit = ffs(samplers) - 1; + samplers &= ~(1 << unit); + + if(!nvfx->is_nv4x) + so = nv30_fragtex_build(nvfx, unit); + else + so = nv40_fragtex_build(nvfx, unit); + + so_ref(so, &nvfx->state.hw[NVFX_STATE_FRAGTEX0 + unit]); + so_ref(NULL, &so); + state->dirty |= (1ULL << (NVFX_STATE_FRAGTEX0 + unit)); + } + + nvfx->state.fp_samplers = fp->samplers; + return FALSE; +} + +struct nvfx_state_entry nvfx_state_fragtex = { + .validate = nvfx_fragtex_validate, + .dirty = { + .pipe = NVFX_NEW_SAMPLER | NVFX_NEW_FRAGPROG, + .hw = 0 + } +}; diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c index 85d7e1f1972..0f5ed61aab7 100644 --- a/src/gallium/drivers/nv40/nv40_miptree.c +++ b/src/gallium/drivers/nvfx/nvfx_miptree.c @@ -4,13 +4,13 @@ #include "util/u_format.h" #include "util/u_math.h" -#include "nv40_context.h" -#include "../nouveau/nv04_surface_2d.h" +#include "nvfx_context.h" +#include "nv04_surface_2d.h" static void -nv40_miptree_layout(struct nv40_miptree *mt) +nvfx_miptree_layout(struct nvfx_miptree *mt) { struct pipe_texture *pt = &mt->base; uint width = pt->width0; @@ -20,7 +20,7 @@ nv40_miptree_layout(struct nv40_miptree *mt) PIPE_TEXTURE_USAGE_DEPTH_STENCIL | PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); + PIPE_TEXTURE_USAGE_SCANOUT); if (pt->target == PIPE_TEXTURE_CUBE) { nr_faces = 6; @@ -62,13 +62,13 @@ nv40_miptree_layout(struct nv40_miptree *mt) } static struct pipe_texture * -nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) { - struct nv40_miptree *mt; + struct nvfx_miptree *mt; unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | NOUVEAU_BUFFER_USAGE_TEXTURE; - mt = MALLOC(sizeof(struct nv40_miptree)); + mt = MALLOC(sizeof(struct nvfx_miptree)); if (!mt) return NULL; mt->base = *pt; @@ -80,7 +80,7 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) pt->height0 & (pt->height0 - 1)) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else - if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | + if (pt->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; @@ -89,6 +89,18 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else { switch (pt->format) { + case PIPE_FORMAT_B5G6R5_UNORM: + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + /* TODO: we can actually swizzle these formats on nv40, we + are just preserving the pre-unification behavior. + The whole 2D code is going to be rewritten anyway. */ + if(nvfx_screen(pscreen)->is_nv4x) { + mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + break; + } /* TODO: Figure out which formats can be swizzled */ case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: @@ -112,7 +124,7 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) if (pt->tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET && util_format_get_stride(pt->format, pt->width0) < 64) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - nv40_miptree_layout(mt); + nvfx_miptree_layout(mt); mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage, mt->total_size); if (!mt->buffer) { @@ -124,17 +136,17 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) } static struct pipe_texture * -nv40_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, +nvfx_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, const unsigned *stride, struct pipe_buffer *pb) { - struct nv40_miptree *mt; + struct nvfx_miptree *mt; /* Only supports 2D, non-mipmapped textures for the moment */ if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || pt->depth0 != 1) return NULL; - mt = CALLOC_STRUCT(nv40_miptree); + mt = CALLOC_STRUCT(nvfx_miptree); if (!mt) return NULL; @@ -153,9 +165,9 @@ nv40_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, } static void -nv40_miptree_destroy(struct pipe_texture *pt) +nvfx_miptree_destroy(struct pipe_texture *pt) { - struct nv40_miptree *mt = (struct nv40_miptree *)pt; + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; int l; pipe_buffer_reference(&mt->buffer, NULL); @@ -168,11 +180,11 @@ nv40_miptree_destroy(struct pipe_texture *pt) } static struct pipe_surface * -nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { - struct nv40_miptree *mt = (struct nv40_miptree *)pt; + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; struct nv04_surface *ns; ns = CALLOC_STRUCT(nv04_surface); @@ -202,21 +214,21 @@ nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, * Note that ns->pitch is always a multiple of 64 for linear surfaces and swizzled surfaces are POT, so * ns->pitch & 63 is equivalent to (ns->pitch < 64 && swizzled)*/ if((ns->pitch & 63) && (ns->base.usage & (PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER)) == PIPE_BUFFER_USAGE_GPU_WRITE) - return &nv04_surface_wrap_for_render(pscreen, ((struct nv40_screen*)pscreen)->eng2d, ns)->base; + return &nv04_surface_wrap_for_render(pscreen, ((struct nvfx_screen*)pscreen)->eng2d, ns)->base; return &ns->base; } static void -nv40_miptree_surface_del(struct pipe_surface *ps) +nvfx_miptree_surface_del(struct pipe_surface *ps) { struct nv04_surface* ns = (struct nv04_surface*)ps; if(ns->backing) { - struct nv40_screen* screen = (struct nv40_screen*)ps->texture->screen; + struct nvfx_screen* screen = (struct nvfx_screen*)ps->texture->screen; if(ns->backing->base.usage & PIPE_BUFFER_USAGE_GPU_WRITE) screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height); - nv40_miptree_surface_del(&ns->backing->base); + nvfx_miptree_surface_del(&ns->backing->base); } pipe_texture_reference(&ps->texture, NULL); @@ -224,12 +236,12 @@ nv40_miptree_surface_del(struct pipe_surface *ps) } void -nv40_screen_init_miptree_functions(struct pipe_screen *pscreen) +nvfx_screen_init_miptree_functions(struct pipe_screen *pscreen) { - pscreen->texture_create = nv40_miptree_create; - pscreen->texture_blanket = nv40_miptree_blanket; - pscreen->texture_destroy = nv40_miptree_destroy; - pscreen->get_tex_surface = nv40_miptree_surface_new; - pscreen->tex_surface_destroy = nv40_miptree_surface_del; -} + pscreen->texture_create = nvfx_miptree_create; + pscreen->texture_destroy = nvfx_miptree_destroy; + pscreen->get_tex_surface = nvfx_miptree_surface_new; + pscreen->tex_surface_destroy = nvfx_miptree_surface_del; + nouveau_screen(pscreen)->texture_blanket = nvfx_miptree_blanket; +} diff --git a/src/gallium/drivers/nvfx/nvfx_query.c b/src/gallium/drivers/nvfx/nvfx_query.c new file mode 100644 index 00000000000..acbaf75a236 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_query.c @@ -0,0 +1,127 @@ +#include "pipe/p_context.h" + +#include "nvfx_context.h" + +struct nvfx_query { + struct nouveau_resource *object; + unsigned type; + boolean ready; + uint64_t result; +}; + +static INLINE struct nvfx_query * +nvfx_query(struct pipe_query *pipe) +{ + return (struct nvfx_query *)pipe; +} + +static struct pipe_query * +nvfx_query_create(struct pipe_context *pipe, unsigned query_type) +{ + struct nvfx_query *q; + + q = CALLOC(1, sizeof(struct nvfx_query)); + q->type = query_type; + + return (struct pipe_query *)q; +} + +static void +nvfx_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) +{ + struct nvfx_query *q = nvfx_query(pq); + + if (q->object) + nouveau_resource_free(&q->object); + FREE(q); +} + +static void +nvfx_query_begin(struct pipe_context *pipe, struct pipe_query *pq) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_query *q = nvfx_query(pq); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); + + /* Happens when end_query() is called, then another begin_query() + * without querying the result in-between. For now we'll wait for + * the existing query to notify completion, but it could be better. + */ + if (q->object) { + uint64_t tmp; + pipe->get_query_result(pipe, pq, 1, &tmp); + } + + if (nouveau_resource_alloc(nvfx->screen->query_heap, 1, NULL, &q->object)) + assert(0); + nouveau_notifier_reset(nvfx->screen->query, q->object->start); + + BEGIN_RING(chan, eng3d, NV34TCL_QUERY_RESET, 1); + OUT_RING (chan, 1); + BEGIN_RING(chan, eng3d, NV34TCL_QUERY_UNK17CC, 1); + OUT_RING (chan, 1); + + q->ready = FALSE; +} + +static void +nvfx_query_end(struct pipe_context *pipe, struct pipe_query *pq) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + struct nvfx_query *q = nvfx_query(pq); + + BEGIN_RING(chan, eng3d, NV34TCL_QUERY_GET, 1); + OUT_RING (chan, (0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) | + ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT)); + FIRE_RING(chan); +} + +static boolean +nvfx_query_result(struct pipe_context *pipe, struct pipe_query *pq, + boolean wait, uint64_t *result) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_query *q = nvfx_query(pq); + + assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); + + if (!q->ready) { + unsigned status; + + status = nouveau_notifier_status(nvfx->screen->query, + q->object->start); + if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { + if (wait == FALSE) + return FALSE; + + nouveau_notifier_wait_status(nvfx->screen->query, + q->object->start, + NV_NOTIFY_STATE_STATUS_COMPLETED, 0); + } + + q->result = nouveau_notifier_return_val(nvfx->screen->query, + q->object->start); + q->ready = TRUE; + nouveau_resource_free(&q->object); + } + + *result = q->result; + return TRUE; +} + +void +nvfx_init_query_functions(struct nvfx_context *nvfx) +{ + nvfx->pipe.create_query = nvfx_query_create; + nvfx->pipe.destroy_query = nvfx_query_destroy; + nvfx->pipe.begin_query = nvfx_query_begin; + nvfx->pipe.end_query = nvfx_query_end; + nvfx->pipe.get_query_result = nvfx_query_result; +} diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index 85433d20953..8138715cc7d 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -3,18 +3,18 @@ #include "nouveau/nouveau_screen.h" -#include "nv30_context.h" -#include "nv30_screen.h" +#include "nvfx_context.h" +#include "nvfx_screen.h" #define NV30TCL_CHIPSET_3X_MASK 0x00000003 #define NV34TCL_CHIPSET_3X_MASK 0x00000010 #define NV35TCL_CHIPSET_3X_MASK 0x000001e0 /* FIXME: It seems I should not include directly ../../winsys/drm/nouveau/drm/nouveau_drm_api.h - * to get the pointer to the context front buffer, so I copied nouveau_winsys here. - * nv30_screen_surface_format_supported() can then use it to enforce creating fbo - * with same number of bits everywhere. - */ +* to get the pointer to the context front buffer, so I copied nouveau_winsys here. +* nv30_screen_surface_format_supported() can then use it to enforce creating fbo +* with same number of bits everywhere. +*/ struct nouveau_winsys { struct pipe_winsys base; @@ -22,15 +22,21 @@ struct nouveau_winsys { struct pipe_surface *front; }; +#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf +#define NV4X_GRCLASS4497_CHIPSETS 0x00005450 +#define NV6X_GRCLASS4497_CHIPSETS 0x00000088 static int -nv30_screen_get_param(struct pipe_screen *pscreen, int param) +nvfx_screen_get_param(struct pipe_screen *pscreen, int param) { + struct nvfx_screen *screen = nvfx_screen(pscreen); + switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 8; + /* TODO: check this */ + return screen->is_nv4x ? 16 : 8; case PIPE_CAP_NPOT_TEXTURES: - return 0; + return !!screen->is_nv4x; case PIPE_CAP_TWO_SIDED_STENCIL: return 1; case PIPE_CAP_GLSL: @@ -40,7 +46,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_POINT_SPRITE: return 1; case PIPE_CAP_MAX_RENDER_TARGETS: - return 2; + return screen->is_nv4x ? 4 : 2; case PIPE_CAP_OCCLUSION_QUERY: return 1; case PIPE_CAP_TEXTURE_SHADOW_MAP: @@ -52,21 +58,26 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 13; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: - return 0; + return !!screen->is_nv4x; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: return 1; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; + return 0; /* We have 4 on nv40 - but unsupported currently */ case PIPE_CAP_TGSI_CONT_SUPPORTED: return 0; case PIPE_CAP_BLEND_EQUATION_SEPARATE: - return 0; + return !!screen->is_nv4x; case NOUVEAU_CAP_HW_VTXBUF: + /* TODO: this is almost surely wrong */ + return !!screen->is_nv4x; case NOUVEAU_CAP_HW_IDXBUF: - return 1; + /* TODO: this is also almost surely wrong */ + return screen->is_nv4x && screen->eng3d->grclass == NV40TCL; case PIPE_CAP_MAX_COMBINED_SAMPLERS: return 16; case PIPE_CAP_INDEP_BLEND_ENABLE: + /* TODO: on nv40 we have separate color masks */ + /* TODO: nv40 mrt blending is probably broken */ return 0; case PIPE_CAP_INDEP_BLEND_FUNC: return 0; @@ -83,8 +94,10 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) } static float -nv30_screen_get_paramf(struct pipe_screen *pscreen, int param) +nvfx_screen_get_paramf(struct pipe_screen *pscreen, int param) { + struct nvfx_screen *screen = nvfx_screen(pscreen); + switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: case PIPE_CAP_MAX_LINE_WIDTH_AA: @@ -93,9 +106,9 @@ nv30_screen_get_paramf(struct pipe_screen *pscreen, int param) case PIPE_CAP_MAX_POINT_WIDTH_AA: return 64.0; case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 8.0; + return screen->is_nv4x ? 16.0 : 8.0; case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: - return 4.0; + return screen->is_nv4x ? 16.0 : 4.0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0.0; @@ -103,11 +116,12 @@ nv30_screen_get_paramf(struct pipe_screen *pscreen, int param) } static boolean -nv30_screen_surface_format_supported(struct pipe_screen *pscreen, +nvfx_screen_surface_format_supported(struct pipe_screen *pscreen, enum pipe_format format, enum pipe_texture_target target, unsigned tex_usage, unsigned geom_flags) { + struct nvfx_screen *screen = nvfx_screen(pscreen); struct pipe_surface *front = ((struct nouveau_winsys *) pscreen->winsys)->front; if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { @@ -125,9 +139,9 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_X8Z24_UNORM: return TRUE; case PIPE_FORMAT_Z16_UNORM: - if (front) { + /* TODO: this nv30 limitation probably does not exist */ + if (!screen->is_nv4x && front) return (front->format == PIPE_FORMAT_B5G6R5_UNORM); - } return TRUE; default: break; @@ -144,7 +158,14 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_L8A8_UNORM: case PIPE_FORMAT_Z16_UNORM: case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: return TRUE; + /* TODO: does nv30 support this? */ + case PIPE_FORMAT_R16_SNORM: + return !!screen->is_nv4x; default: break; } @@ -154,20 +175,20 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen, } static struct pipe_buffer * -nv30_surface_buffer(struct pipe_surface *surf) +nvfx_surface_buffer(struct pipe_surface *surf) { - struct nv30_miptree *mt = (struct nv30_miptree *)surf->texture; + struct nvfx_miptree *mt = (struct nvfx_miptree *)surf->texture; return mt->buffer; } static void -nv30_screen_destroy(struct pipe_screen *pscreen) +nvfx_screen_destroy(struct pipe_screen *pscreen) { - struct nv30_screen *screen = nv30_screen(pscreen); + struct nvfx_screen *screen = nvfx_screen(pscreen); unsigned i; - for (i = 0; i < NV30_STATE_MAX; i++) { + for (i = 0; i < NVFX_STATE_MAX; i++) { if (screen->state[i]) so_ref(NULL, &screen->state[i]); } @@ -177,7 +198,7 @@ nv30_screen_destroy(struct pipe_screen *pscreen) nouveau_resource_destroy(&screen->query_heap); nouveau_notifier_free(&screen->query); nouveau_notifier_free(&screen->sync); - nouveau_grobj_free(&screen->rankine); + nouveau_grobj_free(&screen->eng3d); nv04_surface_2d_takedown(&screen->eng2d); nouveau_screen_fini(&screen->base); @@ -185,60 +206,155 @@ nv30_screen_destroy(struct pipe_screen *pscreen) FREE(pscreen); } +static void nv30_screen_init(struct nvfx_screen *screen, struct nouveau_stateobj* so) +{ + int i; + + /* TODO: perhaps we should do some of this on nv40 too? */ + for (i=1; i<8; i++) { + so_method(so, screen->eng3d, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1); + so_data (so, 0); + so_method(so, screen->eng3d, NV34TCL_VIEWPORT_CLIP_VERT(i), 1); + so_data (so, 0); + } + + so_method(so, screen->eng3d, 0x220, 1); + so_data (so, 1); + + so_method(so, screen->eng3d, 0x03b0, 1); + so_data (so, 0x00100000); + so_method(so, screen->eng3d, 0x1454, 1); + so_data (so, 0); + so_method(so, screen->eng3d, 0x1d80, 1); + so_data (so, 3); + so_method(so, screen->eng3d, 0x1450, 1); + so_data (so, 0x00030004); + + /* NEW */ + so_method(so, screen->eng3d, 0x1e98, 1); + so_data (so, 0); + so_method(so, screen->eng3d, 0x17e0, 3); + so_data (so, fui(0.0)); + so_data (so, fui(0.0)); + so_data (so, fui(1.0)); + so_method(so, screen->eng3d, 0x1f80, 16); + for (i=0; i<16; i++) { + so_data (so, (i==8) ? 0x0000ffff : 0); + } + + so_method(so, screen->eng3d, 0x120, 3); + so_data (so, 0); + so_data (so, 1); + so_data (so, 2); + + so_method(so, screen->eng3d, 0x1d88, 1); + so_data (so, 0x00001200); + + so_method(so, screen->eng3d, NV34TCL_RC_ENABLE, 1); + so_data (so, 0); + + so_method(so, screen->eng3d, NV34TCL_DEPTH_RANGE_NEAR, 2); + so_data (so, fui(0.0)); + so_data (so, fui(1.0)); + + so_method(so, screen->eng3d, NV34TCL_MULTISAMPLE_CONTROL, 1); + so_data (so, 0xffff0000); + + /* enables use of vp rather than fixed-function somehow */ + so_method(so, screen->eng3d, 0x1e94, 1); + so_data (so, 0x13); +} + +static void nv40_screen_init(struct nvfx_screen *screen, struct nouveau_stateobj* so) +{ + so_method(so, screen->eng3d, NV40TCL_DMA_COLOR2, 2); + so_data (so, screen->base.channel->vram->handle); + so_data (so, screen->base.channel->vram->handle); + + so_method(so, screen->eng3d, 0x1ea4, 3); + so_data (so, 0x00000010); + so_data (so, 0x01000100); + so_data (so, 0xff800006); + + /* vtxprog output routing */ + so_method(so, screen->eng3d, 0x1fc4, 1); + so_data (so, 0x06144321); + so_method(so, screen->eng3d, 0x1fc8, 2); + so_data (so, 0xedcba987); + so_data (so, 0x00000021); + so_method(so, screen->eng3d, 0x1fd0, 1); + so_data (so, 0x00171615); + so_method(so, screen->eng3d, 0x1fd4, 1); + so_data (so, 0x001b1a19); + + so_method(so, screen->eng3d, 0x1ef8, 1); + so_data (so, 0x0020ffff); + so_method(so, screen->eng3d, 0x1d64, 1); + so_data (so, 0x00d30000); + so_method(so, screen->eng3d, 0x1e94, 1); + so_data (so, 0x00000001); +} + struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) +nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { - struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen); + struct nvfx_screen *screen = CALLOC_STRUCT(nvfx_screen); struct nouveau_channel *chan; struct pipe_screen *pscreen; struct nouveau_stateobj *so; - unsigned rankine_class = 0; - int ret, i; + unsigned eng3d_class = 0; + int ret; if (!screen) return NULL; + pscreen = &screen->base.base; ret = nouveau_screen_init(&screen->base, dev); if (ret) { - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } chan = screen->base.channel; pscreen->winsys = ws; - pscreen->destroy = nv30_screen_destroy; - pscreen->get_param = nv30_screen_get_param; - pscreen->get_paramf = nv30_screen_get_paramf; - pscreen->is_format_supported = nv30_screen_surface_format_supported; - pscreen->context_create = nv30_create; - - nv30_screen_init_miptree_functions(pscreen); - nv30_screen_init_transfer_functions(pscreen); + pscreen->destroy = nvfx_screen_destroy; + pscreen->get_param = nvfx_screen_get_param; + pscreen->get_paramf = nvfx_screen_get_paramf; + pscreen->is_format_supported = nvfx_screen_surface_format_supported; + pscreen->context_create = nvfx_create; - /* 3D object */ switch (dev->chipset & 0xf0) { case 0x30: if (NV30TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) - rankine_class = 0x0397; - else - if (NV34TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) - rankine_class = 0x0697; - else - if (NV35TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) - rankine_class = 0x0497; + eng3d_class = 0x0397; + else if (NV34TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) + eng3d_class = 0x0697; + else if (NV35TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) + eng3d_class = 0x0497; break; - default: + case 0x40: + if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f))) + eng3d_class = NV40TCL; + else if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) + eng3d_class = NV44TCL; + screen->is_nv4x = ~0; + break; + case 0x60: + if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) + eng3d_class = NV44TCL; + screen->is_nv4x = ~0; break; } - if (!rankine_class) { - NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", dev->chipset); + if (!eng3d_class) { + NOUVEAU_ERR("Unknown nv3x/nv4x chipset: nv%02x\n", dev->chipset); return NULL; } - ret = nouveau_grobj_alloc(chan, 0xbeef3097, rankine_class, - &screen->rankine); + nvfx_screen_init_miptree_functions(pscreen); + + ret = nouveau_grobj_alloc(chan, 0xbeef3097, eng3d_class, &screen->eng3d); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return FALSE; @@ -246,13 +362,13 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) /* 2D engine setup */ screen->eng2d = nv04_surface_2d_init(&screen->base); - screen->eng2d->buf = nv30_surface_buffer; + screen->eng2d->buf = nvfx_surface_buffer; /* Notifier for sync purposes */ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } @@ -260,99 +376,54 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query); if (ret) { NOUVEAU_ERR("Error initialising query objects: %d\n", ret); - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } ret = nouveau_resource_init(&screen->query_heap, 0, 32); if (ret) { NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } /* Vtxprog resources */ - if (nouveau_resource_init(&screen->vp_exec_heap, 0, 256) || + if (nouveau_resource_init(&screen->vp_exec_heap, 0, screen->is_nv4x ? 512 : 256) || nouveau_resource_init(&screen->vp_data_heap, 0, 256)) { - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } - /* Static rankine initialisation */ - so = so_new(36, 60, 0); - so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1); + /* Static eng3d initialisation */ + /* make the so big and don't worry about exact values + since we it will be thrown away immediately after use */ + so = so_new(256, 256, 0); + so_method(so, screen->eng3d, NV34TCL_DMA_NOTIFY, 1); so_data (so, screen->sync->handle); - so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2); + so_method(so, screen->eng3d, NV34TCL_DMA_TEXTURE0, 2); so_data (so, chan->vram->handle); so_data (so, chan->gart->handle); - so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1); + so_method(so, screen->eng3d, NV34TCL_DMA_COLOR1, 1); so_data (so, chan->vram->handle); - so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2); + so_method(so, screen->eng3d, NV34TCL_DMA_COLOR0, 2); so_data (so, chan->vram->handle); so_data (so, chan->vram->handle); - so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2); + so_method(so, screen->eng3d, NV34TCL_DMA_VTXBUF0, 2); so_data (so, chan->vram->handle); so_data (so, chan->gart->handle); -/* so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2); - so_data (so, 0); - so_data (so, screen->query->handle);*/ - so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1); - so_data (so, chan->vram->handle); - so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1); - so_data (so, chan->vram->handle); - - for (i=1; i<8; i++) { - so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1); - so_data (so, 0); - so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1); - so_data (so, 0); - } - - so_method(so, screen->rankine, 0x220, 1); - so_data (so, 1); - - so_method(so, screen->rankine, 0x03b0, 1); - so_data (so, 0x00100000); - so_method(so, screen->rankine, 0x1454, 1); - so_data (so, 0); - so_method(so, screen->rankine, 0x1d80, 1); - so_data (so, 3); - so_method(so, screen->rankine, 0x1450, 1); - so_data (so, 0x00030004); - /* NEW */ - so_method(so, screen->rankine, 0x1e98, 1); - so_data (so, 0); - so_method(so, screen->rankine, 0x17e0, 3); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(1.0)); - so_method(so, screen->rankine, 0x1f80, 16); - for (i=0; i<16; i++) { - so_data (so, (i==8) ? 0x0000ffff : 0); - } - - so_method(so, screen->rankine, 0x120, 3); + so_method(so, screen->eng3d, NV34TCL_DMA_FENCE, 2); so_data (so, 0); - so_data (so, 1); - so_data (so, 2); + so_data (so, screen->query->handle); - so_method(so, screen->rankine, 0x1d88, 1); - so_data (so, 0x00001200); - - so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1); - so_data (so, 0); - - so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2); - so_data (so, fui(0.0)); - so_data (so, fui(1.0)); - - so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1); - so_data (so, 0xffff0000); + so_method(so, screen->eng3d, NV34TCL_DMA_IN_MEMORY7, 2); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); - /* enables use of vp rather than fixed-function somehow */ - so_method(so, screen->rankine, 0x1e94, 1); - so_data (so, 0x13); + if(!screen->is_nv4x) + nv30_screen_init(screen, so); + else + nv40_screen_init(screen, so); so_emit(chan, so); so_ref(NULL, &so); diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nvfx/nvfx_screen.h index 9437aa050d4..c0b4b9899dd 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nvfx/nvfx_screen.h @@ -1,19 +1,21 @@ -#ifndef __NV40_SCREEN_H__ -#define __NV40_SCREEN_H__ +#ifndef __NVFX_SCREEN_H__ +#define __NVFX_SCREEN_H__ #include "nouveau/nouveau_screen.h" -#include "nouveau/nv04_surface_2d.h" +#include "nv04_surface_2d.h" -struct nv40_screen { +struct nvfx_screen { struct nouveau_screen base; struct nouveau_winsys *nvws; - struct nv40_context *cur_ctx; + struct nvfx_context *cur_ctx; + + unsigned is_nv4x; /* either 0 or ~0 */ /* HW graphics objects */ struct nv04_surface_2d *eng2d; - struct nouveau_grobj *curie; + struct nouveau_grobj *eng3d; struct nouveau_notifier *sync; /* Query object resources */ @@ -25,16 +27,13 @@ struct nv40_screen { struct nouveau_resource *vp_data_heap; /* Current 3D state of channel */ - struct nouveau_stateobj *state[NV40_STATE_MAX]; + struct nouveau_stateobj *state[NVFX_STATE_MAX]; }; -static INLINE struct nv40_screen * -nv40_screen(struct pipe_screen *screen) +static INLINE struct nvfx_screen * +nvfx_screen(struct pipe_screen *screen) { - return (struct nv40_screen *)screen; + return (struct nvfx_screen *)screen; } -void -nv40_screen_init_transfer_functions(struct pipe_screen *pscreen); - #endif diff --git a/src/gallium/drivers/nvfx/nvfx_shader.h b/src/gallium/drivers/nvfx/nvfx_shader.h new file mode 100644 index 00000000000..0b2f044f7fe --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_shader.h @@ -0,0 +1,429 @@ +#ifndef __NVFX_SHADER_H__ +#define __NVFX_SHADER_H__ + +/* this will resolve to either the NV30 or the NV40 version + * depending on the current hardware */ +/* unusual, but very fast and compact method */ +#define NVFX_VP(c) ((NV30_VP_##c) + (nvfx->is_nv4x & ((NV40_VP_##c) - (NV30_VP_##c)))) + +#define NVFX_VP_INST_SLOT_VEC 0 +#define NVFX_VP_INST_SLOT_SCA 1 + +#define NVFX_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */ +#define NVFX_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */ +#define NVFX_VP_INST_IN_NORMAL 2 +#define NVFX_VP_INST_IN_COL0 3 /* Should probably confirm them all though */ +#define NVFX_VP_INST_IN_COL1 4 +#define NVFX_VP_INST_IN_FOGC 5 +#define NVFX_VP_INST_IN_TC0 8 +#define NVFX_VP_INST_IN_TC(n) (8+n) + +#define NVFX_VP_INST_SCA_OP_NOP 0x00 +#define NVFX_VP_INST_SCA_OP_MOV 0x01 +#define NVFX_VP_INST_SCA_OP_RCP 0x02 +#define NVFX_VP_INST_SCA_OP_RCC 0x03 +#define NVFX_VP_INST_SCA_OP_RSQ 0x04 +#define NVFX_VP_INST_SCA_OP_EXP 0x05 +#define NVFX_VP_INST_SCA_OP_LOG 0x06 +#define NVFX_VP_INST_SCA_OP_LIT 0x07 +#define NVFX_VP_INST_SCA_OP_BRA 0x09 +#define NVFX_VP_INST_SCA_OP_CAL 0x0B +#define NVFX_VP_INST_SCA_OP_RET 0x0C +#define NVFX_VP_INST_SCA_OP_LG2 0x0D +#define NVFX_VP_INST_SCA_OP_EX2 0x0E +#define NVFX_VP_INST_SCA_OP_SIN 0x0F +#define NVFX_VP_INST_SCA_OP_COS 0x10 + +#define NV40_VP_INST_SCA_OP_PUSHA 0x13 +#define NV40_VP_INST_SCA_OP_POPA 0x14 + +#define NVFX_VP_INST_VEC_OP_NOP 0x00 +#define NVFX_VP_INST_VEC_OP_MOV 0x01 +#define NVFX_VP_INST_VEC_OP_MUL 0x02 +#define NVFX_VP_INST_VEC_OP_ADD 0x03 +#define NVFX_VP_INST_VEC_OP_MAD 0x04 +#define NVFX_VP_INST_VEC_OP_DP3 0x05 +#define NVFX_VP_INST_VEC_OP_DPH 0x06 +#define NVFX_VP_INST_VEC_OP_DP4 0x07 +#define NVFX_VP_INST_VEC_OP_DST 0x08 +#define NVFX_VP_INST_VEC_OP_MIN 0x09 +#define NVFX_VP_INST_VEC_OP_MAX 0x0A +#define NVFX_VP_INST_VEC_OP_SLT 0x0B +#define NVFX_VP_INST_VEC_OP_SGE 0x0C +#define NVFX_VP_INST_VEC_OP_ARL 0x0D +#define NVFX_VP_INST_VEC_OP_FRC 0x0E +#define NVFX_VP_INST_VEC_OP_FLR 0x0F +#define NVFX_VP_INST_VEC_OP_SEQ 0x10 +#define NVFX_VP_INST_VEC_OP_SFL 0x11 +#define NVFX_VP_INST_VEC_OP_SGT 0x12 +#define NVFX_VP_INST_VEC_OP_SLE 0x13 +#define NVFX_VP_INST_VEC_OP_SNE 0x14 +#define NVFX_VP_INST_VEC_OP_STR 0x15 +#define NVFX_VP_INST_VEC_OP_SSG 0x16 +#define NVFX_VP_INST_VEC_OP_ARR 0x17 +#define NVFX_VP_INST_VEC_OP_ARA 0x18 + +#define NV40_VP_INST_VEC_OP_TXL 0x19 + +/* DWORD 3 */ +#define NVFX_VP_INST_LAST (1 << 0) + +/* + * Each fragment program opcode appears to be comprised of 4 32-bit values. + * + * 0 - Opcode, output reg/mask, ATTRIB source + * 1 - Source 0 + * 2 - Source 1 + * 3 - Source 2 + * + * There appears to be no special difference between result regs and temp regs. + * result.color == R0.xyzw + * result.depth == R1.z + * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0 + * otherwise it is set to 1. + * + * Constants are inserted directly after the instruction that uses them. + * + * It appears that it's not possible to use two input registers in one + * instruction as the input sourcing is done in the instruction dword + * and not the source selection dwords. As such instructions such as: + * + * ADD result.color, fragment.color, fragment.texcoord[0]; + * + * must be split into two MOV's and then an ADD (nvidia does this) but + * I'm not sure why it's not just one MOV and then source the second input + * in the ADD instruction.. + * + * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary + * negation requires multiplication with a const. + * + * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE + * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO + * is implemented simply by not writing to the relevant components of the destination. + * + * Conditional execution + * TODO + * + * Non-native instructions: + * LIT + * LRP - MAD+MAD + * SUB - ADD, negate second source + * RSQ - LG2 + EX2 + * POW - LG2 + MUL + EX2 + * SCS - COS + SIN + * XPD + * + * NV40 Looping + * Loops appear to be fairly expensive on NV40 at least, the proprietary + * driver goes to a lot of effort to avoid using the native looping + * instructions. If the total number of *executed* instructions between + * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop. + * The maximum loop count is 255. + * + */ + +//== Opcode / Destination selection == +#define NVFX_FP_OP_PROGRAM_END (1 << 0) +#define NVFX_FP_OP_OUT_REG_SHIFT 1 +#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */ +#define NV40_FP_OP_OUT_REG_MASK (63 << 1) +/* Needs to be set when writing outputs to get expected result.. */ +#define NVFX_FP_OP_OUT_REG_HALF (1 << 7) +#define NVFX_FP_OP_COND_WRITE_ENABLE (1 << 8) +#define NVFX_FP_OP_OUTMASK_SHIFT 9 +#define NVFX_FP_OP_OUTMASK_MASK (0xF << 9) +# define NVFX_FP_OP_OUT_X (1<<9) +# define NVFX_FP_OP_OUT_Y (1<<10) +# define NVFX_FP_OP_OUT_Z (1<<11) +# define NVFX_FP_OP_OUT_W (1<<12) +/* Uncertain about these, especially the input_src values.. it's possible that + * they can be dynamically changed. + */ +#define NVFX_FP_OP_INPUT_SRC_SHIFT 13 +#define NVFX_FP_OP_INPUT_SRC_MASK (15 << 13) +# define NVFX_FP_OP_INPUT_SRC_POSITION 0x0 +# define NVFX_FP_OP_INPUT_SRC_COL0 0x1 +# define NVFX_FP_OP_INPUT_SRC_COL1 0x2 +# define NVFX_FP_OP_INPUT_SRC_FOGC 0x3 +# define NVFX_FP_OP_INPUT_SRC_TC0 0x4 +# define NVFX_FP_OP_INPUT_SRC_TC(n) (0x4 + n) +# define NV40_FP_OP_INPUT_SRC_FACING 0xE +#define NVFX_FP_OP_TEX_UNIT_SHIFT 17 +#define NVFX_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */ +#define NVFX_FP_OP_PRECISION_SHIFT 22 +#define NVFX_FP_OP_PRECISION_MASK (3 << 22) +# define NVFX_FP_PRECISION_FP32 0 +# define NVFX_FP_PRECISION_FP16 1 +# define NVFX_FP_PRECISION_FX12 2 +#define NVFX_FP_OP_OPCODE_SHIFT 24 +#define NVFX_FP_OP_OPCODE_MASK (0x3F << 24) +/* NV30/NV40 fragment program opcodes */ +#define NVFX_FP_OP_OPCODE_NOP 0x00 +#define NVFX_FP_OP_OPCODE_MOV 0x01 +#define NVFX_FP_OP_OPCODE_MUL 0x02 +#define NVFX_FP_OP_OPCODE_ADD 0x03 +#define NVFX_FP_OP_OPCODE_MAD 0x04 +#define NVFX_FP_OP_OPCODE_DP3 0x05 +#define NVFX_FP_OP_OPCODE_DP4 0x06 +#define NVFX_FP_OP_OPCODE_DST 0x07 +#define NVFX_FP_OP_OPCODE_MIN 0x08 +#define NVFX_FP_OP_OPCODE_MAX 0x09 +#define NVFX_FP_OP_OPCODE_SLT 0x0A +#define NVFX_FP_OP_OPCODE_SGE 0x0B +#define NVFX_FP_OP_OPCODE_SLE 0x0C +#define NVFX_FP_OP_OPCODE_SGT 0x0D +#define NVFX_FP_OP_OPCODE_SNE 0x0E +#define NVFX_FP_OP_OPCODE_SEQ 0x0F +#define NVFX_FP_OP_OPCODE_FRC 0x10 +#define NVFX_FP_OP_OPCODE_FLR 0x11 +#define NVFX_FP_OP_OPCODE_KIL 0x12 +#define NVFX_FP_OP_OPCODE_PK4B 0x13 +#define NVFX_FP_OP_OPCODE_UP4B 0x14 +#define NVFX_FP_OP_OPCODE_DDX 0x15 /* can only write XY */ +#define NVFX_FP_OP_OPCODE_DDY 0x16 /* can only write XY */ +#define NVFX_FP_OP_OPCODE_TEX 0x17 +#define NVFX_FP_OP_OPCODE_TXP 0x18 +#define NVFX_FP_OP_OPCODE_TXD 0x19 +#define NVFX_FP_OP_OPCODE_RCP 0x1A +#define NVFX_FP_OP_OPCODE_EX2 0x1C +#define NVFX_FP_OP_OPCODE_LG2 0x1D +#define NVFX_FP_OP_OPCODE_STR 0x20 +#define NVFX_FP_OP_OPCODE_SFL 0x21 +#define NVFX_FP_OP_OPCODE_COS 0x22 +#define NVFX_FP_OP_OPCODE_SIN 0x23 +#define NVFX_FP_OP_OPCODE_PK2H 0x24 +#define NVFX_FP_OP_OPCODE_UP2H 0x25 +#define NVFX_FP_OP_OPCODE_PK4UB 0x27 +#define NVFX_FP_OP_OPCODE_UP4UB 0x28 +#define NVFX_FP_OP_OPCODE_PK2US 0x29 +#define NVFX_FP_OP_OPCODE_UP2US 0x2A +#define NVFX_FP_OP_OPCODE_DP2A 0x2E +#define NVFX_FP_OP_OPCODE_TXB 0x31 +#define NVFX_FP_OP_OPCODE_DIV 0x3A + +/* NV30 only fragment program opcodes */ +#define NVFX_FP_OP_OPCODE_RSQ_NV30 0x1B +#define NVFX_FP_OP_OPCODE_LIT_NV30 0x1E +#define NVFX_FP_OP_OPCODE_LRP_NV30 0x1F +#define NVFX_FP_OP_OPCODE_POW_NV30 0x26 +#define NVFX_FP_OP_OPCODE_RFL_NV30 0x36 + +/* NV40 only fragment program opcodes */ +#define NVFX_FP_OP_OPCODE_TXL_NV40 0x31 +/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/ +#define NV40_FP_OP_BRA_OPCODE_BRK 0x0 +#define NV40_FP_OP_BRA_OPCODE_CAL 0x1 +#define NV40_FP_OP_BRA_OPCODE_IF 0x2 +#define NV40_FP_OP_BRA_OPCODE_LOOP 0x3 +#define NV40_FP_OP_BRA_OPCODE_REP 0x4 +#define NV40_FP_OP_BRA_OPCODE_RET 0x5 + +#define NVFX_FP_OP_OUT_SAT (1 << 31) + +/* high order bits of SRC0 */ +#define NVFX_FP_OP_OUT_ABS (1 << 29) +#define NVFX_FP_OP_COND_SWZ_W_SHIFT 27 +#define NVFX_FP_OP_COND_SWZ_W_MASK (3 << 27) +#define NVFX_FP_OP_COND_SWZ_Z_SHIFT 25 +#define NVFX_FP_OP_COND_SWZ_Z_MASK (3 << 25) +#define NVFX_FP_OP_COND_SWZ_Y_SHIFT 23 +#define NVFX_FP_OP_COND_SWZ_Y_MASK (3 << 23) +#define NVFX_FP_OP_COND_SWZ_X_SHIFT 21 +#define NVFX_FP_OP_COND_SWZ_X_MASK (3 << 21) +#define NVFX_FP_OP_COND_SWZ_ALL_SHIFT 21 +#define NVFX_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) +#define NVFX_FP_OP_COND_SHIFT 18 +#define NVFX_FP_OP_COND_MASK (0x07 << 18) +# define NVFX_FP_OP_COND_FL 0 +# define NVFX_FP_OP_COND_LT 1 +# define NVFX_FP_OP_COND_EQ 2 +# define NVFX_FP_OP_COND_LE 3 +# define NVFX_FP_OP_COND_GT 4 +# define NVFX_FP_OP_COND_NE 5 +# define NVFX_FP_OP_COND_GE 6 +# define NVFX_FP_OP_COND_TR 7 + +/* high order bits of SRC1 */ +#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31) +#define NVFX_FP_OP_DST_SCALE_SHIFT 28 +#define NVFX_FP_OP_DST_SCALE_MASK (3 << 28) +#define NVFX_FP_OP_DST_SCALE_1X 0 +#define NVFX_FP_OP_DST_SCALE_2X 1 +#define NVFX_FP_OP_DST_SCALE_4X 2 +#define NVFX_FP_OP_DST_SCALE_8X 3 +#define NVFX_FP_OP_DST_SCALE_INV_2X 5 +#define NVFX_FP_OP_DST_SCALE_INV_4X 6 +#define NVFX_FP_OP_DST_SCALE_INV_8X 7 + +/* SRC1 LOOP */ +#define NV40_FP_OP_LOOP_INCR_SHIFT 19 +#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19) +#define NV40_FP_OP_LOOP_INDEX_SHIFT 10 +#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10) +#define NV40_FP_OP_LOOP_COUNT_SHIFT 2 +#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2) + +/* SRC1 IF */ +#define NV40_FP_OP_ELSE_ID_SHIFT 2 +#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2) + +/* SRC1 CAL */ +#define NV40_FP_OP_IADDR_SHIFT 2 +#define NV40_FP_OP_IADDR_MASK (0xFF << 2) + +/* SRC1 REP + * I have no idea why there are 3 count values here.. but they + * have always been filled with the same value in my tests so + * far.. + */ +#define NV40_FP_OP_REP_COUNT1_SHIFT 2 +#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2) +#define NV40_FP_OP_REP_COUNT2_SHIFT 10 +#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10) +#define NV40_FP_OP_REP_COUNT3_SHIFT 19 +#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19) + +/* SRC2 REP/IF */ +#define NV40_FP_OP_END_ID_SHIFT 2 +#define NV40_FP_OP_END_ID_MASK (0xFF << 2) + +/* high order bits of SRC2 */ +#define NVFX_FP_OP_INDEX_INPUT (1 << 30) +#define NV40_FP_OP_ADDR_INDEX_SHIFT 19 +#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19) + +//== Register selection == +#define NVFX_FP_REG_TYPE_SHIFT 0 +#define NVFX_FP_REG_TYPE_MASK (3 << 0) +# define NVFX_FP_REG_TYPE_TEMP 0 +# define NVFX_FP_REG_TYPE_INPUT 1 +# define NVFX_FP_REG_TYPE_CONST 2 +#define NVFX_FP_REG_SRC_SHIFT 2 +#define NV30_FP_REG_SRC_MASK (31 << 2) +#define NV40_FP_REG_SRC_MASK (63 << 2) +#define NVFX_FP_REG_SRC_HALF (1 << 8) +#define NVFX_FP_REG_SWZ_ALL_SHIFT 9 +#define NVFX_FP_REG_SWZ_ALL_MASK (255 << 9) +#define NVFX_FP_REG_SWZ_X_SHIFT 9 +#define NVFX_FP_REG_SWZ_X_MASK (3 << 9) +#define NVFX_FP_REG_SWZ_Y_SHIFT 11 +#define NVFX_FP_REG_SWZ_Y_MASK (3 << 11) +#define NVFX_FP_REG_SWZ_Z_SHIFT 13 +#define NVFX_FP_REG_SWZ_Z_MASK (3 << 13) +#define NVFX_FP_REG_SWZ_W_SHIFT 15 +#define NVFX_FP_REG_SWZ_W_MASK (3 << 15) +# define NVFX_FP_SWIZZLE_X 0 +# define NVFX_FP_SWIZZLE_Y 1 +# define NVFX_FP_SWIZZLE_Z 2 +# define NVFX_FP_SWIZZLE_W 3 +#define NVFX_FP_REG_NEGATE (1 << 17) + +#define NVFXSR_NONE 0 +#define NVFXSR_OUTPUT 1 +#define NVFXSR_INPUT 2 +#define NVFXSR_TEMP 3 +#define NVFXSR_CONST 4 + +#define NVFX_COND_FL 0 +#define NVFX_COND_LT 1 +#define NVFX_COND_EQ 2 +#define NVFX_COND_LE 3 +#define NVFX_COND_GT 4 +#define NVFX_COND_NE 5 +#define NVFX_COND_GE 6 +#define NVFX_COND_TR 7 + +/* Yes, this are ordered differently... */ + +#define NVFX_VP_MASK_X 8 +#define NVFX_VP_MASK_Y 4 +#define NVFX_VP_MASK_Z 2 +#define NVFX_VP_MASK_W 1 +#define NVFX_VP_MASK_ALL 0xf + +#define NVFX_FP_MASK_X 1 +#define NVFX_FP_MASK_Y 2 +#define NVFX_FP_MASK_Z 4 +#define NVFX_FP_MASK_W 8 +#define NVFX_FP_MASK_ALL 0xf + +#define NVFX_SWZ_X 0 +#define NVFX_SWZ_Y 1 +#define NVFX_SWZ_Z 2 +#define NVFX_SWZ_W 3 + +#define swz(s,x,y,z,w) nvfx_sr_swz((s), NVFX_SWZ_##x, NVFX_SWZ_##y, NVFX_SWZ_##z, NVFX_SWZ_##w) +#define neg(s) nvfx_sr_neg((s)) +#define abs(s) nvfx_sr_abs((s)) +#define scale(s,v) nvfx_sr_scale((s), NVFX_FP_OP_DST_SCALE_##v) + +struct nvfx_sreg { + int type; + int index; + + int dst_scale; + + int negate; + int abs; + int swz[4]; + + int cc_update; + int cc_update_reg; + int cc_test; + int cc_test_reg; + int cc_swz[4]; +}; + +static INLINE struct nvfx_sreg +nvfx_sr(int type, int index) +{ + struct nvfx_sreg temp = { + .type = type, + .index = index, + .dst_scale = 0, + .abs = 0, + .negate = 0, + .swz = { 0, 1, 2, 3 }, + .cc_update = 0, + .cc_update_reg = 0, + .cc_test = NVFX_COND_TR, + .cc_test_reg = 0, + .cc_swz = { 0, 1, 2, 3 }, + }; + return temp; +} + +static INLINE struct nvfx_sreg +nvfx_sr_swz(struct nvfx_sreg src, int x, int y, int z, int w) +{ + struct nvfx_sreg dst = src; + + dst.swz[NVFX_SWZ_X] = src.swz[x]; + dst.swz[NVFX_SWZ_Y] = src.swz[y]; + dst.swz[NVFX_SWZ_Z] = src.swz[z]; + dst.swz[NVFX_SWZ_W] = src.swz[w]; + return dst; +} + +static INLINE struct nvfx_sreg +nvfx_sr_neg(struct nvfx_sreg src) +{ + src.negate = !src.negate; + return src; +} + +static INLINE struct nvfx_sreg +nvfx_sr_abs(struct nvfx_sreg src) +{ + src.abs = 1; + return src; +} + +static INLINE struct nvfx_sreg +nvfx_sr_scale(struct nvfx_sreg src, int scale) +{ + src.dst_scale = scale; + return src; +} + +#endif diff --git a/src/gallium/drivers/nvfx/nvfx_state.c b/src/gallium/drivers/nvfx/nvfx_state.c new file mode 100644 index 00000000000..ecaa0dcb16a --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state.c @@ -0,0 +1,650 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "draw/draw_context.h" + +#include "tgsi/tgsi_parse.h" + +#include "nvfx_context.h" +#include "nvfx_state.h" +#include "nvfx_tex.h" + +static void * +nvfx_blend_state_create(struct pipe_context *pipe, + const struct pipe_blend_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct nvfx_blend_state *bso = CALLOC(1, sizeof(*bso)); + struct nouveau_stateobj *so = so_new(5, 8, 0); + + if (cso->rt[0].blend_enable) { + so_method(so, eng3d, NV34TCL_BLEND_FUNC_ENABLE, 3); + so_data (so, 1); + so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | + nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | + nvgl_blend_func(cso->rt[0].rgb_dst_factor)); + if(nvfx->screen->base.device->chipset < 0x40) { + so_method(so, eng3d, NV34TCL_BLEND_EQUATION, 1); + so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); + } else { + so_method(so, eng3d, NV40TCL_BLEND_EQUATION, 1); + so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 | + nvgl_blend_eqn(cso->rt[0].rgb_func)); + } + } else { + so_method(so, eng3d, NV34TCL_BLEND_FUNC_ENABLE, 1); + so_data (so, 0); + } + + so_method(so, eng3d, NV34TCL_COLOR_MASK, 1); + so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); + + /* TODO: add NV40 MRT color mask */ + + if (cso->logicop_enable) { + so_method(so, eng3d, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2); + so_data (so, 1); + so_data (so, nvgl_logicop_func(cso->logicop_func)); + } else { + so_method(so, eng3d, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1); + so_data (so, 0); + } + + so_method(so, eng3d, NV34TCL_DITHER_ENABLE, 1); + so_data (so, cso->dither ? 1 : 0); + + so_ref(so, &bso->so); + so_ref(NULL, &so); + bso->pipe = *cso; + return (void *)bso; +} + +static void +nvfx_blend_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->blend = hwcso; + nvfx->dirty |= NVFX_NEW_BLEND; +} + +static void +nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_blend_state *bso = hwcso; + + so_ref(NULL, &bso->so); + FREE(bso); +} + +static void * +nvfx_sampler_state_create(struct pipe_context *pipe, + const struct pipe_sampler_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_sampler_state *ps; + + ps = MALLOC(sizeof(struct nvfx_sampler_state)); + + /* on nv30, we use this as an internal flag */ + ps->fmt = cso->normalized_coords ? 0 : NV40TCL_TEX_FORMAT_RECT; + ps->en = 0; + ps->filt = nvfx_tex_filter(cso); + ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) | + (nvfx_tex_wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) | + (nvfx_tex_wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT) | + nvfx_tex_wrap_compare_mode(cso); + ps->bcol = nvfx_tex_border_color(cso->border_color); + + if(nvfx->is_nv4x) + nv40_sampler_state_init(pipe, ps, cso); + else + nv30_sampler_state_init(pipe, ps, cso); + + return (void *)ps; +} + +static void +nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + nvfx->tex_sampler[unit] = sampler[unit]; + nvfx->dirty_samplers |= (1 << unit); + } + + for (unit = nr; unit < nvfx->nr_samplers; unit++) { + nvfx->tex_sampler[unit] = NULL; + nvfx->dirty_samplers |= (1 << unit); + } + + nvfx->nr_samplers = nr; + nvfx->dirty |= NVFX_NEW_SAMPLER; +} + +static void +nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void +nvfx_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], + views[unit]); + nvfx->dirty_samplers |= (1 << unit); + } + + for (unit = nr; unit < nvfx->nr_textures; unit++) { + pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], + NULL); + nvfx->dirty_samplers |= (1 << unit); + } + + nvfx->nr_textures = nr; + nvfx->dirty |= NVFX_NEW_SAMPLER; +} + + +static struct pipe_sampler_view * +nvfx_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +nvfx_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + +static void * +nvfx_rasterizer_state_create(struct pipe_context *pipe, + const struct pipe_rasterizer_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); + struct nouveau_stateobj *so = so_new(9, 19, 0); + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + + /*XXX: ignored: + * light_twoside + * point_smooth -nohw + * multisample + */ + + so_method(so, eng3d, NV34TCL_SHADE_MODEL, 1); + so_data (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT : + NV34TCL_SHADE_MODEL_SMOOTH); + + so_method(so, eng3d, NV34TCL_LINE_WIDTH, 2); + so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff); + so_data (so, cso->line_smooth ? 1 : 0); + so_method(so, eng3d, NV34TCL_LINE_STIPPLE_ENABLE, 2); + so_data (so, cso->line_stipple_enable ? 1 : 0); + so_data (so, (cso->line_stipple_pattern << 16) | + cso->line_stipple_factor); + + so_method(so, eng3d, NV34TCL_POINT_SIZE, 1); + so_data (so, fui(cso->point_size)); + + so_method(so, eng3d, NV34TCL_POLYGON_MODE_FRONT, 6); + if (cso->front_winding == PIPE_WINDING_CCW) { + so_data(so, nvgl_polygon_mode(cso->fill_ccw)); + so_data(so, nvgl_polygon_mode(cso->fill_cw)); + switch (cso->cull_mode) { + case PIPE_WINDING_CCW: + so_data(so, NV34TCL_CULL_FACE_FRONT); + break; + case PIPE_WINDING_CW: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + case PIPE_WINDING_BOTH: + so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); + break; + default: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + } + so_data(so, NV34TCL_FRONT_FACE_CCW); + } else { + so_data(so, nvgl_polygon_mode(cso->fill_cw)); + so_data(so, nvgl_polygon_mode(cso->fill_ccw)); + switch (cso->cull_mode) { + case PIPE_WINDING_CCW: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + case PIPE_WINDING_CW: + so_data(so, NV34TCL_CULL_FACE_FRONT); + break; + case PIPE_WINDING_BOTH: + so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); + break; + default: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + } + so_data(so, NV34TCL_FRONT_FACE_CW); + } + so_data(so, cso->poly_smooth ? 1 : 0); + so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); + + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); + so_data (so, cso->poly_stipple_enable ? 1 : 0); + + so_method(so, eng3d, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3); + if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || + (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) + so_data(so, 1); + else + so_data(so, 0); + if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || + (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) + so_data(so, 1); + else + so_data(so, 0); + if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || + (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) + so_data(so, 1); + else + so_data(so, 0); + if (cso->offset_cw || cso->offset_ccw) { + so_method(so, eng3d, NV34TCL_POLYGON_OFFSET_FACTOR, 2); + so_data (so, fui(cso->offset_scale)); + so_data (so, fui(cso->offset_units * 2)); + } + + so_method(so, eng3d, NV34TCL_POINT_SPRITE, 1); + if (cso->point_quad_rasterization) { + unsigned psctl = (1 << 0), i; + + for (i = 0; i < 8; i++) { + if ((cso->sprite_coord_enable >> i) & 1) + psctl |= (1 << (8 + i)); + } + + so_data(so, psctl); + } else { + so_data(so, 0); + } + + so_ref(so, &rsso->so); + so_ref(NULL, &so); + rsso->pipe = *cso; + return (void *)rsso; +} + +static void +nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->rasterizer = hwcso; + nvfx->dirty |= NVFX_NEW_RAST; + nvfx->draw_dirty |= NVFX_NEW_RAST; +} + +static void +nvfx_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_rasterizer_state *rsso = hwcso; + + so_ref(NULL, &rsso->so); + FREE(rsso); +} + +static void * +nvfx_depth_stencil_alpha_state_create(struct pipe_context *pipe, + const struct pipe_depth_stencil_alpha_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); + struct nouveau_stateobj *so = so_new(6, 20, 0); + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + + so_method(so, eng3d, NV34TCL_DEPTH_FUNC, 3); + so_data (so, nvgl_comparison_op(cso->depth.func)); + so_data (so, cso->depth.writemask ? 1 : 0); + so_data (so, cso->depth.enabled ? 1 : 0); + + so_method(so, eng3d, NV34TCL_ALPHA_FUNC_ENABLE, 3); + so_data (so, cso->alpha.enabled ? 1 : 0); + so_data (so, nvgl_comparison_op(cso->alpha.func)); + so_data (so, float_to_ubyte(cso->alpha.ref_value)); + + if (cso->stencil[0].enabled) { + so_method(so, eng3d, NV34TCL_STENCIL_FRONT_ENABLE, 3); + so_data (so, cso->stencil[0].enabled ? 1 : 0); + so_data (so, cso->stencil[0].writemask); + so_data (so, nvgl_comparison_op(cso->stencil[0].func)); + so_method(so, eng3d, NV34TCL_STENCIL_FRONT_FUNC_MASK, 4); + so_data (so, cso->stencil[0].valuemask); + so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); + } else { + so_method(so, eng3d, NV34TCL_STENCIL_FRONT_ENABLE, 1); + so_data (so, 0); + } + + if (cso->stencil[1].enabled) { + so_method(so, eng3d, NV34TCL_STENCIL_BACK_ENABLE, 3); + so_data (so, cso->stencil[1].enabled ? 1 : 0); + so_data (so, cso->stencil[1].writemask); + so_data (so, nvgl_comparison_op(cso->stencil[1].func)); + so_method(so, eng3d, NV34TCL_STENCIL_BACK_FUNC_MASK, 4); + so_data (so, cso->stencil[1].valuemask); + so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); + } else { + so_method(so, eng3d, NV34TCL_STENCIL_BACK_ENABLE, 1); + so_data (so, 0); + } + + so_ref(so, &zsaso->so); + so_ref(NULL, &so); + zsaso->pipe = *cso; + return (void *)zsaso; +} + +static void +nvfx_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->zsa = hwcso; + nvfx->dirty |= NVFX_NEW_ZSA; +} + +static void +nvfx_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_zsa_state *zsaso = hwcso; + + so_ref(NULL, &zsaso->so); + FREE(zsaso); +} + +static void * +nvfx_vp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_vertex_program *vp; + + vp = CALLOC(1, sizeof(struct nvfx_vertex_program)); + vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + vp->draw = draw_create_vertex_shader(nvfx->draw, &vp->pipe); + + return (void *)vp; +} + +static void +nvfx_vp_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->vertprog = hwcso; + nvfx->dirty |= NVFX_NEW_VERTPROG; + nvfx->draw_dirty |= NVFX_NEW_VERTPROG; +} + +static void +nvfx_vp_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_vertex_program *vp = hwcso; + + draw_delete_vertex_shader(nvfx->draw, vp->draw); + nvfx_vertprog_destroy(nvfx, vp); + FREE((void*)vp->pipe.tokens); + FREE(vp); +} + +static void * +nvfx_fp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + struct nvfx_fragment_program *fp; + + fp = CALLOC(1, sizeof(struct nvfx_fragment_program)); + fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + + tgsi_scan_shader(fp->pipe.tokens, &fp->info); + + return (void *)fp; +} + +static void +nvfx_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->fragprog = hwcso; + nvfx->dirty |= NVFX_NEW_FRAGPROG; +} + +static void +nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_fragment_program *fp = hwcso; + + nvfx_fragprog_destroy(nvfx, fp); + FREE((void*)fp->pipe.tokens); + FREE(fp); +} + +static void +nvfx_set_blend_color(struct pipe_context *pipe, + const struct pipe_blend_color *bcol) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->blend_colour = *bcol; + nvfx->dirty |= NVFX_NEW_BCOL; +} + +static void +nvfx_set_stencil_ref(struct pipe_context *pipe, + const struct pipe_stencil_ref *sr) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->stencil_ref = *sr; + nvfx->dirty |= NVFX_NEW_SR; +} + +static void +nvfx_set_clip_state(struct pipe_context *pipe, + const struct pipe_clip_state *clip) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->clip = *clip; + nvfx->dirty |= NVFX_NEW_UCP; + nvfx->draw_dirty |= NVFX_NEW_UCP; +} + +static void +nvfx_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, + struct pipe_buffer *buf ) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->constbuf[shader] = buf; + nvfx->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); + + if (shader == PIPE_SHADER_VERTEX) { + nvfx->dirty |= NVFX_NEW_VERTPROG; + } else + if (shader == PIPE_SHADER_FRAGMENT) { + nvfx->dirty |= NVFX_NEW_FRAGPROG; + } +} + +static void +nvfx_set_framebuffer_state(struct pipe_context *pipe, + const struct pipe_framebuffer_state *fb) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->framebuffer = *fb; + nvfx->dirty |= NVFX_NEW_FB; +} + +static void +nvfx_set_polygon_stipple(struct pipe_context *pipe, + const struct pipe_poly_stipple *stipple) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + memcpy(nvfx->stipple, stipple->stipple, 4 * 32); + nvfx->dirty |= NVFX_NEW_STIPPLE; +} + +static void +nvfx_set_scissor_state(struct pipe_context *pipe, + const struct pipe_scissor_state *s) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->scissor = *s; + nvfx->dirty |= NVFX_NEW_SCISSOR; +} + +static void +nvfx_set_viewport_state(struct pipe_context *pipe, + const struct pipe_viewport_state *vpt) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->viewport = *vpt; + nvfx->dirty |= NVFX_NEW_VIEWPORT; + nvfx->draw_dirty |= NVFX_NEW_VIEWPORT; +} + +static void +nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count, + const struct pipe_vertex_buffer *vb) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + memcpy(nvfx->vtxbuf, vb, sizeof(*vb) * count); + nvfx->vtxbuf_nr = count; + + nvfx->dirty |= NVFX_NEW_ARRAYS; + nvfx->draw_dirty |= NVFX_NEW_ARRAYS; +} + +static void * +nvfx_vtxelts_state_create(struct pipe_context *pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct nvfx_vtxelt_state *cso = CALLOC_STRUCT(nvfx_vtxelt_state); + + assert(num_elements < 16); /* not doing fallbacks yet */ + cso->num_elements = num_elements; + memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); + +/* nvfx_vtxelt_construct(cso);*/ + + return (void *)cso; +} + +static void +nvfx_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void +nvfx_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->vtxelt = hwcso; + nvfx->dirty |= NVFX_NEW_ARRAYS; + /*nvfx->draw_dirty |= NVFX_NEW_ARRAYS;*/ +} + +void +nvfx_init_state_functions(struct nvfx_context *nvfx) +{ + nvfx->pipe.create_blend_state = nvfx_blend_state_create; + nvfx->pipe.bind_blend_state = nvfx_blend_state_bind; + nvfx->pipe.delete_blend_state = nvfx_blend_state_delete; + + nvfx->pipe.create_sampler_state = nvfx_sampler_state_create; + nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind; + nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete; + nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views; + nvfx->pipe.create_sampler_view = nvfx_create_sampler_view; + nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy; + + nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create; + nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind; + nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete; + + nvfx->pipe.create_depth_stencil_alpha_state = + nvfx_depth_stencil_alpha_state_create; + nvfx->pipe.bind_depth_stencil_alpha_state = + nvfx_depth_stencil_alpha_state_bind; + nvfx->pipe.delete_depth_stencil_alpha_state = + nvfx_depth_stencil_alpha_state_delete; + + nvfx->pipe.create_vs_state = nvfx_vp_state_create; + nvfx->pipe.bind_vs_state = nvfx_vp_state_bind; + nvfx->pipe.delete_vs_state = nvfx_vp_state_delete; + + nvfx->pipe.create_fs_state = nvfx_fp_state_create; + nvfx->pipe.bind_fs_state = nvfx_fp_state_bind; + nvfx->pipe.delete_fs_state = nvfx_fp_state_delete; + + nvfx->pipe.set_blend_color = nvfx_set_blend_color; + nvfx->pipe.set_stencil_ref = nvfx_set_stencil_ref; + nvfx->pipe.set_clip_state = nvfx_set_clip_state; + nvfx->pipe.set_constant_buffer = nvfx_set_constant_buffer; + nvfx->pipe.set_framebuffer_state = nvfx_set_framebuffer_state; + nvfx->pipe.set_polygon_stipple = nvfx_set_polygon_stipple; + nvfx->pipe.set_scissor_state = nvfx_set_scissor_state; + nvfx->pipe.set_viewport_state = nvfx_set_viewport_state; + + nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create; + nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete; + nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind; + + nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers; +} diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nvfx/nvfx_state.h index 192074e7471..e585246879b 100644 --- a/src/gallium/drivers/nv40/nv40_state.h +++ b/src/gallium/drivers/nvfx/nvfx_state.h @@ -1,29 +1,21 @@ -#ifndef __NV40_STATE_H__ -#define __NV40_STATE_H__ +#ifndef __NVFX_STATE_H__ +#define __NVFX_STATE_H__ #include "pipe/p_state.h" #include "tgsi/tgsi_scan.h" -struct nv40_sampler_state { - uint32_t fmt; - uint32_t wrap; - uint32_t en; - uint32_t filt; - uint32_t bcol; -}; - -struct nv40_vertex_program_exec { +struct nvfx_vertex_program_exec { uint32_t data[4]; boolean has_branch_offset; int const_index; }; -struct nv40_vertex_program_data { +struct nvfx_vertex_program_data { int index; /* immediates == -1 */ float value[4]; }; -struct nv40_vertex_program { +struct nvfx_vertex_program { struct pipe_shader_state pipe; struct draw_vertex_shader *draw; @@ -32,9 +24,9 @@ struct nv40_vertex_program { struct pipe_clip_state ucp; - struct nv40_vertex_program_exec *insns; + struct nvfx_vertex_program_exec *insns; unsigned nr_insns; - struct nv40_vertex_program_data *consts; + struct nvfx_vertex_program_data *consts; unsigned nr_consts; struct nouveau_resource *exec; @@ -49,12 +41,12 @@ struct nv40_vertex_program { struct nouveau_stateobj *so; }; -struct nv40_fragment_program_data { +struct nvfx_fragment_program_data { unsigned offset; unsigned index; }; -struct nv40_fragment_program { +struct nvfx_fragment_program { struct pipe_shader_state pipe; struct tgsi_shader_info info; @@ -64,7 +56,7 @@ struct nv40_fragment_program { uint32_t *insn; int insn_len; - struct nv40_fragment_program_data *consts; + struct nvfx_fragment_program_data *consts; unsigned nr_consts; struct pipe_buffer *buffer; @@ -73,7 +65,9 @@ struct nv40_fragment_program { struct nouveau_stateobj *so; }; -struct nv40_miptree { +#define NVFX_MAX_TEXTURE_LEVELS 16 + +struct nvfx_miptree { struct pipe_texture base; struct nouveau_bo *bo; @@ -83,7 +77,7 @@ struct nv40_miptree { struct { uint pitch; uint *image_offset; - } level[PIPE_MAX_TEXTURE_LEVELS]; + } level[NVFX_MAX_TEXTURE_LEVELS]; }; #endif diff --git a/src/gallium/drivers/nvfx/nvfx_state_blend.c b/src/gallium/drivers/nvfx/nvfx_state_blend.c new file mode 100644 index 00000000000..03b6ef8117d --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_blend.c @@ -0,0 +1,41 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_blend_validate(struct nvfx_context *nvfx) +{ + so_ref(nvfx->blend->so, &nvfx->state.hw[NVFX_STATE_BLEND]); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_blend = { + .validate = nvfx_state_blend_validate, + .dirty = { + .pipe = NVFX_NEW_BLEND, + .hw = NVFX_STATE_BLEND + } +}; + +static boolean +nvfx_state_blend_colour_validate(struct nvfx_context *nvfx) +{ + struct nouveau_stateobj *so = so_new(1, 1, 0); + struct pipe_blend_color *bcol = &nvfx->blend_colour; + + so_method(so, nvfx->screen->eng3d, NV34TCL_BLEND_COLOR, 1); + so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | + (float_to_ubyte(bcol->color[0]) << 16) | + (float_to_ubyte(bcol->color[1]) << 8) | + (float_to_ubyte(bcol->color[2]) << 0))); + + so_ref(so, &nvfx->state.hw[NVFX_STATE_BCOL]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_blend_colour = { + .validate = nvfx_state_blend_colour_validate, + .dirty = { + .pipe = NVFX_NEW_BCOL, + .hw = NVFX_STATE_BCOL + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c new file mode 100644 index 00000000000..72537388ea4 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c @@ -0,0 +1,179 @@ +#include "nvfx_context.h" +#include "nvfx_state.h" +#include "draw/draw_context.h" + +#define RENDER_STATES(name, vbo) \ +static struct nvfx_state_entry *name##render_states[] = { \ + &nvfx_state_framebuffer, \ + &nvfx_state_rasterizer, \ + &nvfx_state_scissor, \ + &nvfx_state_stipple, \ + &nvfx_state_fragprog, \ + &nvfx_state_fragtex, \ + &nvfx_state_vertprog, \ + &nvfx_state_blend, \ + &nvfx_state_blend_colour, \ + &nvfx_state_zsa, \ + &nvfx_state_sr, \ + &nvfx_state_viewport, \ + &nvfx_state_##vbo, \ + NULL \ +} + +RENDER_STATES(, vbo); +RENDER_STATES(swtnl_, vtxfmt); + +static void +nvfx_state_do_validate(struct nvfx_context *nvfx, + struct nvfx_state_entry **states) +{ + while (*states) { + struct nvfx_state_entry *e = *states; + + if (nvfx->dirty & e->dirty.pipe) { + if (e->validate(nvfx)) + nvfx->state.dirty |= (1ULL << e->dirty.hw); + } + + states++; + } + nvfx->dirty = 0; +} + +void +nvfx_state_emit(struct nvfx_context *nvfx) +{ + struct nvfx_state *state = &nvfx->state; + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned i; + uint64_t states; + + /* XXX: race conditions + */ + if (nvfx != screen->cur_ctx) { + for (i = 0; i < NVFX_STATE_MAX; i++) { + if (state->hw[i] && screen->state[i] != state->hw[i]) + state->dirty |= (1ULL << i); + } + + screen->cur_ctx = nvfx; + } + + for (i = 0, states = state->dirty; states; i++) { + if (!(states & (1ULL << i))) + continue; + so_ref (state->hw[i], &nvfx->screen->state[i]); + if (state->hw[i]) + so_emit(chan, nvfx->screen->state[i]); + states &= ~(1ULL << i); + } + + /* TODO: could nv30 need this or something similar too? */ + if(nvfx->is_nv4x) { + if (state->dirty & ((1ULL << NVFX_STATE_FRAGPROG) | + (1ULL << NVFX_STATE_FRAGTEX0))) { + BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1); + OUT_RING (chan, 2); + BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1); + OUT_RING (chan, 1); + } + } + state->dirty = 0; +} + +void +nvfx_state_flush_notify(struct nouveau_channel *chan) +{ + struct nvfx_context *nvfx = chan->user_private; + struct nvfx_state *state = &nvfx->state; + unsigned i, samplers; + + so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FB]); + for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { + if (!(samplers & (1 << i))) + continue; + so_emit_reloc_markers(chan, + state->hw[NVFX_STATE_FRAGTEX0+i]); + samplers &= ~(1ULL << i); + } + so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FRAGPROG]); + if (state->hw[NVFX_STATE_VTXBUF] && nvfx->render_mode == HW) + so_emit_reloc_markers(chan, state->hw[NVFX_STATE_VTXBUF]); +} + +boolean +nvfx_state_validate(struct nvfx_context *nvfx) +{ + boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE; + + if (nvfx->render_mode != HW) { + /* Don't even bother trying to go back to hw if none + * of the states that caused swtnl previously have changed. + */ + if ((nvfx->fallback_swtnl & nvfx->dirty) + != nvfx->fallback_swtnl) + return FALSE; + + /* Attempt to go to hwtnl again */ + nvfx->pipe.flush(&nvfx->pipe, 0, NULL); + nvfx->dirty |= (NVFX_NEW_VIEWPORT | + NVFX_NEW_VERTPROG | + NVFX_NEW_ARRAYS); + nvfx->render_mode = HW; + } + + nvfx_state_do_validate(nvfx, render_states); + + if (nvfx->fallback_swtnl || nvfx->fallback_swrast) + return FALSE; + + if (was_sw) + NOUVEAU_ERR("swtnl->hw\n"); + + return TRUE; +} + +boolean +nvfx_state_validate_swtnl(struct nvfx_context *nvfx) +{ + struct draw_context *draw = nvfx->draw; + + /* Setup for swtnl */ + if (nvfx->render_mode == HW) { + NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl); + nvfx->pipe.flush(&nvfx->pipe, 0, NULL); + nvfx->dirty |= (NVFX_NEW_VIEWPORT | + NVFX_NEW_VERTPROG | + NVFX_NEW_ARRAYS); + nvfx->render_mode = SWTNL; + } + + if (nvfx->draw_dirty & NVFX_NEW_VERTPROG) + draw_bind_vertex_shader(draw, nvfx->vertprog->draw); + + if (nvfx->draw_dirty & NVFX_NEW_RAST) + draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe); + + if (nvfx->draw_dirty & NVFX_NEW_UCP) + draw_set_clip_state(draw, &nvfx->clip); + + if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT) + draw_set_viewport_state(draw, &nvfx->viewport); + + if (nvfx->draw_dirty & NVFX_NEW_ARRAYS) { + draw_set_vertex_buffers(draw, nvfx->vtxbuf_nr, nvfx->vtxbuf); + draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe); + } + + nvfx_state_do_validate(nvfx, swtnl_render_states); + + if (nvfx->fallback_swrast) { + NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast); + return FALSE; + } + + nvfx->draw_dirty = 0; + return TRUE; +} diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c new file mode 100644 index 00000000000..dd64ba4193c --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c @@ -0,0 +1,234 @@ +#include "nvfx_context.h" +#include "nouveau/nouveau_util.h" + +static struct pipe_buffer * +nvfx_do_surface_buffer(struct pipe_surface *surface) +{ + struct nvfx_miptree *mt = (struct nvfx_miptree *)surface->texture; + return mt->buffer; +} + +#define nvfx_surface_buffer(ps) nouveau_bo(nvfx_do_surface_buffer(ps)) + +static boolean +nvfx_state_framebuffer_validate(struct nvfx_context *nvfx) +{ + struct pipe_framebuffer_state *fb = &nvfx->framebuffer; + struct nouveau_channel *chan = nvfx->screen->base.channel; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct nv04_surface *rt[4], *zeta = NULL; + uint32_t rt_enable = 0, rt_format = 0; + int i, colour_format = 0, zeta_format = 0; + int depth_only = 0; + struct nouveau_stateobj *so = so_new(18, 24, 10); + unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; + unsigned w = fb->width; + unsigned h = fb->height; + int colour_bits = 32, zeta_bits = 32; + + if(!nvfx->is_nv4x) + assert(fb->nr_cbufs <= 2); + else + assert(fb->nr_cbufs <= 4); + + for (i = 0; i < fb->nr_cbufs; i++) { + if (colour_format) { + assert(colour_format == fb->cbufs[i]->format); + } else { + colour_format = fb->cbufs[i]->format; + rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i); + rt[i] = (struct nv04_surface *)fb->cbufs[i]; + } + } + + if (rt_enable & (NV34TCL_RT_ENABLE_COLOR1 | + NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) + rt_enable |= NV34TCL_RT_ENABLE_MRT; + + if (fb->zsbuf) { + zeta_format = fb->zsbuf->format; + zeta = (struct nv04_surface *)fb->zsbuf; + } + + if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0 | NV34TCL_RT_ENABLE_COLOR1 | + NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) { + /* Render to at least a colour buffer */ + if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { + assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); + for (i = 1; i < fb->nr_cbufs; i++) + assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); + + rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | + (log2i(rt[0]->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | + (log2i(rt[0]->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); + } + else + rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; + } else if (fb->zsbuf) { + depth_only = 1; + + /* Render to depth buffer only */ + if (!(zeta->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { + assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); + + rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | + (log2i(zeta->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | + (log2i(zeta->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); + } + else + rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; + } else { + return FALSE; + } + + switch (colour_format) { + case PIPE_FORMAT_B8G8R8X8_UNORM: + rt_format |= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + case 0: + rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5; + colour_bits = 16; + break; + default: + assert(0); + } + + switch (zeta_format) { + case PIPE_FORMAT_Z16_UNORM: + rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16; + zeta_bits = 16; + break; + case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + case 0: + rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8; + break; + default: + assert(0); + } + + if ((!nvfx->is_nv4x) && colour_bits > zeta_bits) { + /* TODO: does this limitation really exist? + TODO: can it be worked around somehow? */ + return FALSE; + } + + if ((rt_enable & NV34TCL_RT_ENABLE_COLOR0) + || ((!nvfx->is_nv4x) && depth_only)) { + struct nv04_surface *rt0 = (depth_only ? zeta : rt[0]); + uint32_t pitch = rt0->pitch; + + if(!nvfx->is_nv4x) + { + if (zeta) { + pitch |= (zeta->pitch << 16); + } else { + pitch |= (pitch << 16); + } + } + + so_method(so, eng3d, NV34TCL_DMA_COLOR0, 1); + so_reloc (so, nvfx_surface_buffer(&rt0->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV34TCL_COLOR0_PITCH, 2); + so_data (so, pitch); + so_reloc (so, nvfx_surface_buffer(&rt[0]->base), + rt0->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + } + + if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { + so_method(so, eng3d, NV34TCL_DMA_COLOR1, 1); + so_reloc (so, nvfx_surface_buffer(&rt[1]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV34TCL_COLOR1_OFFSET, 2); + so_reloc (so, nvfx_surface_buffer(&rt[1]->base), + rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_data (so, rt[1]->pitch); + } + + if(nvfx->is_nv4x) + { + if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { + so_method(so, eng3d, NV40TCL_DMA_COLOR2, 1); + so_reloc (so, nvfx_surface_buffer(&rt[2]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV40TCL_COLOR2_OFFSET, 1); + so_reloc (so, nvfx_surface_buffer(&rt[2]->base), + rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, eng3d, NV40TCL_COLOR2_PITCH, 1); + so_data (so, rt[2]->pitch); + } + + if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { + so_method(so, eng3d, NV40TCL_DMA_COLOR3, 1); + so_reloc (so, nvfx_surface_buffer(&rt[3]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV40TCL_COLOR3_OFFSET, 1); + so_reloc (so, nvfx_surface_buffer(&rt[3]->base), + rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, eng3d, NV40TCL_COLOR3_PITCH, 1); + so_data (so, rt[3]->pitch); + } + } + + if (zeta_format) { + so_method(so, eng3d, NV34TCL_DMA_ZETA, 1); + so_reloc (so, nvfx_surface_buffer(&zeta->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV34TCL_ZETA_OFFSET, 1); + /* TODO: reverse engineer LMA */ + so_reloc (so, nvfx_surface_buffer(&zeta->base), + zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); + if(nvfx->is_nv4x) { + so_method(so, eng3d, NV40TCL_ZETA_PITCH, 1); + so_data (so, zeta->pitch); + } + } + + so_method(so, eng3d, NV34TCL_RT_ENABLE, 1); + so_data (so, rt_enable); + so_method(so, eng3d, NV34TCL_RT_HORIZ, 3); + so_data (so, (w << 16) | 0); + so_data (so, (h << 16) | 0); + so_data (so, rt_format); + so_method(so, eng3d, NV34TCL_VIEWPORT_HORIZ, 2); + so_data (so, (w << 16) | 0); + so_data (so, (h << 16) | 0); + so_method(so, eng3d, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); + so_data (so, ((w - 1) << 16) | 0); + so_data (so, ((h - 1) << 16) | 0); + so_method(so, eng3d, 0x1d88, 1); + so_data (so, (1 << 12) | h); + + if(!nvfx->is_nv4x) { + /* Wonder why this is needed, context should all be set to zero on init */ + /* TODO: we can most likely remove this, after putting it in context init */ + so_method(so, eng3d, NV34TCL_VIEWPORT_TX_ORIGIN, 1); + so_data (so, 0); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_FB]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_framebuffer = { + .validate = nvfx_state_framebuffer_validate, + .dirty = { + .pipe = NVFX_NEW_FB, + .hw = NVFX_STATE_FB + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_rasterizer.c b/src/gallium/drivers/nvfx/nvfx_state_rasterizer.c new file mode 100644 index 00000000000..0d35ecbf209 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_rasterizer.c @@ -0,0 +1,17 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_rasterizer_validate(struct nvfx_context *nvfx) +{ + so_ref(nvfx->rasterizer->so, + &nvfx->state.hw[NVFX_STATE_RAST]); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_rasterizer = { + .validate = nvfx_state_rasterizer_validate, + .dirty = { + .pipe = NVFX_NEW_RAST, + .hw = NVFX_STATE_RAST + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_scissor.c b/src/gallium/drivers/nvfx/nvfx_state_scissor.c new file mode 100644 index 00000000000..940d8cb5c0c --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_scissor.c @@ -0,0 +1,36 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_scissor_validate(struct nvfx_context *nvfx) +{ + struct pipe_rasterizer_state *rast = &nvfx->rasterizer->pipe; + struct pipe_scissor_state *s = &nvfx->scissor; + struct nouveau_stateobj *so; + + if (nvfx->state.hw[NVFX_STATE_SCISSOR] && + (rast->scissor == 0 && nvfx->state.scissor_enabled == 0)) + return FALSE; + nvfx->state.scissor_enabled = rast->scissor; + + so = so_new(1, 2, 0); + so_method(so, nvfx->screen->eng3d, NV34TCL_SCISSOR_HORIZ, 2); + if (nvfx->state.scissor_enabled) { + so_data (so, ((s->maxx - s->minx) << 16) | s->minx); + so_data (so, ((s->maxy - s->miny) << 16) | s->miny); + } else { + so_data (so, 4096 << 16); + so_data (so, 4096 << 16); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_SCISSOR]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_scissor = { + .validate = nvfx_state_scissor_validate, + .dirty = { + .pipe = NVFX_NEW_SCISSOR | NVFX_NEW_RAST, + .hw = NVFX_STATE_SCISSOR + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_stipple.c b/src/gallium/drivers/nvfx/nvfx_state_stipple.c new file mode 100644 index 00000000000..57cd3c936a7 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_stipple.c @@ -0,0 +1,40 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_stipple_validate(struct nvfx_context *nvfx) +{ + struct pipe_rasterizer_state *rast = &nvfx->rasterizer->pipe; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct nouveau_stateobj *so; + + if (nvfx->state.hw[NVFX_STATE_STIPPLE] && + (rast->poly_stipple_enable == 0 && nvfx->state.stipple_enabled == 0)) + return FALSE; + + if (rast->poly_stipple_enable) { + unsigned i; + + so = so_new(2, 33, 0); + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); + so_data (so, 1); + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32); + for (i = 0; i < 32; i++) + so_data(so, nvfx->stipple[i]); + } else { + so = so_new(1, 1, 0); + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); + so_data (so, 0); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_STIPPLE]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_stipple = { + .validate = nvfx_state_stipple_validate, + .dirty = { + .pipe = NVFX_NEW_STIPPLE | NVFX_NEW_RAST, + .hw = NVFX_STATE_STIPPLE, + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_viewport.c b/src/gallium/drivers/nvfx/nvfx_state_viewport.c new file mode 100644 index 00000000000..82e0e9220b0 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_viewport.c @@ -0,0 +1,51 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_viewport_validate(struct nvfx_context *nvfx) +{ + struct pipe_viewport_state *vpt = &nvfx->viewport; + struct nouveau_stateobj *so; + + if (nvfx->state.hw[NVFX_STATE_VIEWPORT] && + !(nvfx->dirty & NVFX_NEW_VIEWPORT)) + return FALSE; + + so = so_new(2, 9, 0); + so_method(so, nvfx->screen->eng3d, + NV34TCL_VIEWPORT_TRANSLATE_X, 8); + if(nvfx->render_mode == HW) { + so_data (so, fui(vpt->translate[0])); + so_data (so, fui(vpt->translate[1])); + so_data (so, fui(vpt->translate[2])); + so_data (so, fui(vpt->translate[3])); + so_data (so, fui(vpt->scale[0])); + so_data (so, fui(vpt->scale[1])); + so_data (so, fui(vpt->scale[2])); + so_data (so, fui(vpt->scale[3])); + so_method(so, nvfx->screen->eng3d, 0x1d78, 1); + so_data (so, 1); + } else { + so_data (so, fui(0.0f)); + so_data (so, fui(0.0f)); + so_data (so, fui(0.0f)); + so_data (so, fui(0.0f)); + so_data (so, fui(1.0f)); + so_data (so, fui(1.0f)); + so_data (so, fui(1.0f)); + so_data (so, fui(1.0f)); + so_method(so, nvfx->screen->eng3d, 0x1d78, 1); + so_data (so, nvfx->is_nv4x ? 0x110 : 1); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_VIEWPORT]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_viewport = { + .validate = nvfx_state_viewport_validate, + .dirty = { + .pipe = NVFX_NEW_VIEWPORT, + .hw = NVFX_STATE_VIEWPORT + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_zsa.c b/src/gallium/drivers/nvfx/nvfx_state_zsa.c new file mode 100644 index 00000000000..c84fd041c1e --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_zsa.c @@ -0,0 +1,41 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_zsa_validate(struct nvfx_context *nvfx) +{ + so_ref(nvfx->zsa->so, + &nvfx->state.hw[NVFX_STATE_ZSA]); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_zsa = { + .validate = nvfx_state_zsa_validate, + .dirty = { + .pipe = NVFX_NEW_ZSA, + .hw = NVFX_STATE_ZSA + } +}; + +static boolean +nvfx_state_sr_validate(struct nvfx_context *nvfx) +{ + struct nouveau_stateobj *so = so_new(2, 2, 0); + struct pipe_stencil_ref *sr = &nvfx->stencil_ref; + + so_method(so, nvfx->screen->eng3d, NV34TCL_STENCIL_FRONT_FUNC_REF, 1); + so_data (so, sr->ref_value[0]); + so_method(so, nvfx->screen->eng3d, NV34TCL_STENCIL_BACK_FUNC_REF, 1); + so_data (so, sr->ref_value[1]); + + so_ref(so, &nvfx->state.hw[NVFX_STATE_SR]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_sr = { + .validate = nvfx_state_sr_validate, + .dirty = { + .pipe = NVFX_NEW_SR, + .hw = NVFX_STATE_SR + } +}; diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index bc18e577eee..8a05ad0a571 100644 --- a/src/gallium/drivers/nv30/nv30_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -1,9 +1,9 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -11,11 +11,11 @@ * 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. @@ -23,40 +23,40 @@ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * **************************************************************************/ -#include "nv30_context.h" +#include "nvfx_context.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_tile.h" static void -nv30_surface_copy(struct pipe_context *pipe, +nvfx_surface_copy(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, struct pipe_surface *src, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv04_surface_2d *eng2d = nv30->screen->eng2d; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); } static void -nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +nvfx_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, unsigned width, unsigned height, unsigned value) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv04_surface_2d *eng2d = nv30->screen->eng2d; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; eng2d->fill(eng2d, dest, destx, desty, width, height, value); } void -nv30_init_surface_functions(struct nv30_context *nv30) +nvfx_init_surface_functions(struct nvfx_context *nvfx) { - nv30->pipe.surface_copy = nv30_surface_copy; - nv30->pipe.surface_fill = nv30_surface_fill; + nvfx->pipe.surface_copy = nvfx_surface_copy; + nvfx->pipe.surface_fill = nvfx_surface_fill; } diff --git a/src/gallium/drivers/nvfx/nvfx_tex.h b/src/gallium/drivers/nvfx/nvfx_tex.h new file mode 100644 index 00000000000..69187a79e79 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_tex.h @@ -0,0 +1,133 @@ +#ifndef NVFX_TEX_H_ +#define NVFX_TEX_H_ + +static inline unsigned +nvfx_tex_wrap_mode(unsigned wrap) { + unsigned ret; + + switch (wrap) { + case PIPE_TEX_WRAP_REPEAT: + ret = NV34TCL_TX_WRAP_S_REPEAT; + break; + case PIPE_TEX_WRAP_MIRROR_REPEAT: + ret = NV34TCL_TX_WRAP_S_MIRRORED_REPEAT; + break; + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: + ret = NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE; + break; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: + ret = NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER; + break; + case PIPE_TEX_WRAP_CLAMP: + ret = NV34TCL_TX_WRAP_S_CLAMP; + break; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE; + break; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER; + break; + case PIPE_TEX_WRAP_MIRROR_CLAMP: + ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP; + break; + default: + NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); + ret = NV34TCL_TX_WRAP_S_REPEAT; + break; + } + + return ret >> NV34TCL_TX_WRAP_S_SHIFT; +} + +static inline unsigned +nvfx_tex_wrap_compare_mode(const struct pipe_sampler_state* cso) +{ + if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { + switch (cso->compare_func) { + case PIPE_FUNC_NEVER: + return NV34TCL_TX_WRAP_RCOMP_NEVER; + case PIPE_FUNC_GREATER: + return NV34TCL_TX_WRAP_RCOMP_GREATER; + case PIPE_FUNC_EQUAL: + return NV34TCL_TX_WRAP_RCOMP_EQUAL; + case PIPE_FUNC_GEQUAL: + return NV34TCL_TX_WRAP_RCOMP_GEQUAL; + case PIPE_FUNC_LESS: + return NV34TCL_TX_WRAP_RCOMP_LESS; + case PIPE_FUNC_NOTEQUAL: + return NV34TCL_TX_WRAP_RCOMP_NOTEQUAL; + case PIPE_FUNC_LEQUAL: + return NV34TCL_TX_WRAP_RCOMP_LEQUAL; + case PIPE_FUNC_ALWAYS: + return NV34TCL_TX_WRAP_RCOMP_ALWAYS; + default: + break; + } + } + return 0; +} + +static inline unsigned nvfx_tex_filter(const struct pipe_sampler_state* cso) +{ + unsigned filter = 0; + switch (cso->mag_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + filter |= NV34TCL_TX_FILTER_MAGNIFY_LINEAR; + break; + case PIPE_TEX_FILTER_NEAREST: + default: + filter |= NV34TCL_TX_FILTER_MAGNIFY_NEAREST; + break; + } + + switch (cso->min_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + switch (cso->min_mip_filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; + break; + case PIPE_TEX_MIPFILTER_LINEAR: + filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; + break; + case PIPE_TEX_MIPFILTER_NONE: + default: + filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR; + break; + } + break; + case PIPE_TEX_FILTER_NEAREST: + default: + switch (cso->min_mip_filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; + break; + case PIPE_TEX_MIPFILTER_LINEAR: + filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; + break; + case PIPE_TEX_MIPFILTER_NONE: + default: + filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST; + break; + } + break; + } + return filter; +} + +static inline unsigned nvfx_tex_border_color(const float* border_color) +{ + return ((float_to_ubyte(border_color[3]) << 24) | + (float_to_ubyte(border_color[0]) << 16) | + (float_to_ubyte(border_color[1]) << 8) | + (float_to_ubyte(border_color[2]) << 0)); +} + +struct nvfx_sampler_state { + uint32_t fmt; + uint32_t wrap; + uint32_t en; + uint32_t filt; + uint32_t bcol; +}; + +#endif /* NVFX_TEX_H_ */ diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c index 0462a042c38..409b354d582 100644 --- a/src/gallium/drivers/nv40/nv40_transfer.c +++ b/src/gallium/drivers/nvfx/nvfx_transfer.c @@ -5,18 +5,18 @@ #include "util/u_memory.h" #include "util/u_math.h" #include "nouveau/nouveau_winsys.h" -#include "nv40_context.h" -#include "nv40_screen.h" -#include "nv40_state.h" +#include "nvfx_context.h" +#include "nvfx_screen.h" +#include "nvfx_state.h" -struct nv40_transfer { +struct nvfx_transfer { struct pipe_transfer base; struct pipe_surface *surface; boolean direct; }; static void -nv40_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, +nvfx_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, struct pipe_texture *template) { memset(template, 0, sizeof(struct pipe_texture)); @@ -33,16 +33,17 @@ nv40_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned h } static struct pipe_transfer * -nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +nvfx_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, unsigned w, unsigned h) { - struct nv40_miptree *mt = (struct nv40_miptree *)pt; - struct nv40_transfer *tx; + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; + struct nvfx_transfer *tx; struct pipe_texture tx_tex_template, *tx_tex; - tx = CALLOC_STRUCT(nv40_transfer); + tx = CALLOC_STRUCT(nvfx_transfer); if (!tx) return NULL; @@ -71,7 +72,7 @@ nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, tx->direct = false; - nv40_compatible_transfer_tex(pt, w, h, &tx_tex_template); + nvfx_compatible_transfer_tex(pt, w, h, &tx_tex_template); tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); if (!tx_tex) @@ -80,7 +81,7 @@ nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, return NULL; } - tx->base.stride = ((struct nv40_miptree*)tx_tex)->level[0].pitch; + tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch; tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, 0, 0, 0, @@ -96,7 +97,7 @@ nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, } if (usage & PIPE_TRANSFER_READ) { - struct nv40_screen *nvscreen = nv40_screen(pscreen); + struct nvfx_screen *nvscreen = nvfx_screen(pscreen); struct pipe_surface *src; src = pscreen->get_tex_surface(pscreen, pt, @@ -117,13 +118,14 @@ nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, } static void -nv40_transfer_del(struct pipe_transfer *ptx) +nvfx_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx) { - struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = ptx->texture->screen; - struct nv40_screen *nvscreen = nv40_screen(pscreen); + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_screen *nvscreen = nvfx_screen(pscreen); struct pipe_surface *dst; dst = pscreen->get_tex_surface(pscreen, ptx->texture, @@ -145,11 +147,12 @@ nv40_transfer_del(struct pipe_transfer *ptx) } static void * -nv40_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nvfx_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) { - struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; struct nv04_surface *ns = (struct nv04_surface *)tx->surface; - struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; + struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture; void *map = pipe_buffer_map(pscreen, mt->buffer, pipe_transfer_buffer_flags(ptx)); @@ -160,19 +163,20 @@ nv40_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } static void -nv40_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nvfx_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) { - struct nv40_transfer *tx = (struct nv40_transfer *)ptx; - struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; + struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture; pipe_buffer_unmap(pscreen, mt->buffer); } void -nv40_screen_init_transfer_functions(struct pipe_screen *pscreen) +nvfx_init_transfer_functions(struct nvfx_context *nvfx) { - pscreen->get_tex_transfer = nv40_transfer_new; - pscreen->tex_transfer_destroy = nv40_transfer_del; - pscreen->transfer_map = nv40_transfer_map; - pscreen->transfer_unmap = nv40_transfer_unmap; + nvfx->pipe.get_tex_transfer = nvfx_transfer_new; + nvfx->pipe.tex_transfer_destroy = nvfx_transfer_del; + nvfx->pipe.transfer_map = nvfx_transfer_map; + nvfx->pipe.transfer_unmap = nvfx_transfer_unmap; } diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c index e48823a9138..257087f8f63 100644 --- a/src/gallium/drivers/nv30/nv30_vbo.c +++ b/src/gallium/drivers/nvfx/nvfx_vbo.c @@ -3,17 +3,24 @@ #include "util/u_inlines.h" #include "util/u_format.h" -#include "nv30_context.h" -#include "nv30_state.h" +#include "nvfx_context.h" +#include "nvfx_state.h" #include "nouveau/nouveau_channel.h" #include "nouveau/nouveau_pushbuf.h" #include "nouveau/nouveau_util.h" -#define FORCE_SWTNL 0 +static boolean +nvfx_force_swtnl(struct nvfx_context *nvfx) +{ + static int force_swtnl = -1; + if(force_swtnl < 0) + force_swtnl = debug_get_bool_option("NOUVEAU_SWTNL", 0); + return force_swtnl; +} static INLINE int -nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) +nvfx_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) { switch (pipe) { case PIPE_FORMAT_R32_FLOAT: @@ -69,15 +76,15 @@ nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) } static boolean -nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib, +nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_buffer *ib, unsigned ib_size) { - struct pipe_screen *pscreen = &nv30->screen->base.base; + struct pipe_screen *pscreen = &nvfx->screen->base.base; unsigned type; if (!ib) { - nv30->idxbuf = NULL; - nv30->idxbuf_format = 0xdeadbeef; + nvfx->idxbuf = NULL; + nvfx->idxbuf_format = 0xdeadbeef; return FALSE; } @@ -95,27 +102,27 @@ nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib, return FALSE; } - if (ib != nv30->idxbuf || - type != nv30->idxbuf_format) { - nv30->dirty |= NV30_NEW_ARRAYS; - nv30->idxbuf = ib; - nv30->idxbuf_format = type; + if (ib != nvfx->idxbuf || + type != nvfx->idxbuf_format) { + nvfx->dirty |= NVFX_NEW_ARRAYS; + nvfx->idxbuf = ib; + nvfx->idxbuf_format = type; } return TRUE; } static boolean -nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, +nvfx_vbo_static_attrib(struct nvfx_context *nvfx, struct nouveau_stateobj *so, int attrib, struct pipe_vertex_element *ve, struct pipe_vertex_buffer *vb) { - struct pipe_screen *pscreen = nv30->pipe.screen; - struct nouveau_grobj *rankine = nv30->screen->rankine; + struct pipe_screen *pscreen = nvfx->pipe.screen; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; unsigned type, ncomp; void *map; - if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) + if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) return FALSE; map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); @@ -128,25 +135,25 @@ nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, switch (ncomp) { case 4: - so_method(so, rankine, NV34TCL_VTX_ATTR_4F_X(attrib), 4); + so_method(so, eng3d, NV34TCL_VTX_ATTR_4F_X(attrib), 4); so_data (so, fui(v[0])); so_data (so, fui(v[1])); so_data (so, fui(v[2])); so_data (so, fui(v[3])); break; case 3: - so_method(so, rankine, NV34TCL_VTX_ATTR_3F_X(attrib), 3); + so_method(so, eng3d, NV34TCL_VTX_ATTR_3F_X(attrib), 3); so_data (so, fui(v[0])); so_data (so, fui(v[1])); so_data (so, fui(v[2])); break; case 2: - so_method(so, rankine, NV34TCL_VTX_ATTR_2F_X(attrib), 2); + so_method(so, eng3d, NV34TCL_VTX_ATTR_2F_X(attrib), 2); so_data (so, fui(v[0])); so_data (so, fui(v[1])); break; case 1: - so_method(so, rankine, NV34TCL_VTX_ATTR_1F(attrib), 1); + so_method(so, eng3d, NV34TCL_VTX_ATTR_1F(attrib), 1); so_data (so, fui(v[0])); break; default: @@ -165,26 +172,26 @@ nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, } void -nv30_draw_arrays(struct pipe_context *pipe, +nvfx_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; unsigned restart = 0; - nv30_vbo_set_idxbuf(nv30, NULL, 0); - if (FORCE_SWTNL || !nv30_state_validate(nv30)) { - /*return nv30_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count);*/ - return; + nvfx_vbo_set_idxbuf(nvfx, NULL, 0); + if (nvfx_force_swtnl(nvfx) || !nvfx_state_validate(nvfx)) { + nvfx_draw_elements_swtnl(pipe, NULL, 0, + mode, start, count); + return; } while (count) { unsigned vc, nr; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, mode, start, count, &restart); @@ -193,12 +200,12 @@ nv30_draw_arrays(struct pipe_context *pipe, continue; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { - BEGIN_RING(chan, rankine, NV34TCL_VB_VERTEX_BATCH, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, 1); OUT_RING (chan, ((nr - 1) << 24) | start); start += nr; } @@ -209,14 +216,14 @@ nv30_draw_arrays(struct pipe_context *pipe, nr -= push; - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_VERTEX_BATCH, push); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, push); while (push--) { OUT_RING(chan, ((0x100 - 1) << 24) | start); start += 0x100; } } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); count -= vc; @@ -227,18 +234,18 @@ nv30_draw_arrays(struct pipe_context *pipe, } static INLINE void -nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, +nvfx_draw_elements_u08(struct nvfx_context *nvfx, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nv30_screen *screen = nv30->screen; + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; while (count) { uint8_t *elts = (uint8_t *)ib + start; unsigned vc, push, restart = 0; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, mode, start, count, &restart); @@ -248,11 +255,11 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, } count -= vc; - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); if (vc & 1) { - BEGIN_RING(chan, rankine, NV34TCL_VB_ELEMENT_U32, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, elts[0]); elts++; vc--; } @@ -262,7 +269,7 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, push = MIN2(vc, 2047 * 2); - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); for (i = 0; i < push; i+=2) OUT_RING(chan, (elts[i+1] << 16) | elts[i]); @@ -270,7 +277,7 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, elts += push; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); start = restart; @@ -278,18 +285,18 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, } static INLINE void -nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, +nvfx_draw_elements_u16(struct nvfx_context *nvfx, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nv30_screen *screen = nv30->screen; + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; while (count) { uint16_t *elts = (uint16_t *)ib + start; unsigned vc, push, restart = 0; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, mode, start, count, &restart); @@ -299,11 +306,11 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, } count -= vc; - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); if (vc & 1) { - BEGIN_RING(chan, rankine, NV34TCL_VB_ELEMENT_U32, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, elts[0]); elts++; vc--; } @@ -313,7 +320,7 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, push = MIN2(vc, 2047 * 2); - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); for (i = 0; i < push; i+=2) OUT_RING(chan, (elts[i+1] << 16) | elts[i]); @@ -321,7 +328,7 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, elts += push; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); start = restart; @@ -329,18 +336,18 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, } static INLINE void -nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, +nvfx_draw_elements_u32(struct nvfx_context *nvfx, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nv30_screen *screen = nv30->screen; + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; while (count) { uint32_t *elts = (uint32_t *)ib + start; unsigned vc, push, restart = 0; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1, mode, start, count, &restart); @@ -350,20 +357,20 @@ nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, } count -= vc; - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); while (vc) { push = MIN2(vc, 2047); - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U32, push); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U32, push); OUT_RINGp (chan, elts, push); vc -= push; elts += push; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); start = restart; @@ -371,11 +378,11 @@ nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, } static void -nv30_draw_elements_inline(struct pipe_context *pipe, +nvfx_draw_elements_inline(struct pipe_context *pipe, struct pipe_buffer *ib, unsigned ib_size, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); + struct nvfx_context *nvfx = nvfx_context(pipe); struct pipe_screen *pscreen = pipe->screen; void *map; @@ -387,13 +394,13 @@ nv30_draw_elements_inline(struct pipe_context *pipe, switch (ib_size) { case 1: - nv30_draw_elements_u08(nv30, map, mode, start, count); + nvfx_draw_elements_u08(nvfx, map, mode, start, count); break; case 2: - nv30_draw_elements_u16(nv30, map, mode, start, count); + nvfx_draw_elements_u16(nvfx, map, mode, start, count); break; case 4: - nv30_draw_elements_u32(nv30, map, mode, start, count); + nvfx_draw_elements_u32(nvfx, map, mode, start, count); break; default: NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); @@ -404,19 +411,19 @@ nv30_draw_elements_inline(struct pipe_context *pipe, } static void -nv30_draw_elements_vbo(struct pipe_context *pipe, +nvfx_draw_elements_vbo(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; unsigned restart = 0; while (count) { unsigned nr, vc; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, mode, start, count, &restart); @@ -425,12 +432,12 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, continue; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { - BEGIN_RING(chan, rankine, NV34TCL_VB_INDEX_BATCH, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_INDEX_BATCH, 1); OUT_RING (chan, ((nr - 1) << 24) | start); start += nr; } @@ -441,14 +448,14 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, nr -= push; - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_INDEX_BATCH, push); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_INDEX_BATCH, push); while (push--) { OUT_RING(chan, ((0x100 - 1) << 24) | start); start += 0x100; } } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); count -= vc; @@ -457,24 +464,24 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, } void -nv30_draw_elements(struct pipe_context *pipe, +nvfx_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); + struct nvfx_context *nvfx = nvfx_context(pipe); boolean idxbuf; - idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize); - if (FORCE_SWTNL || !nv30_state_validate(nv30)) { - /*return nv30_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count);*/ + idxbuf = nvfx_vbo_set_idxbuf(nvfx, indexBuffer, indexSize); + if (nvfx_force_swtnl(nvfx) || !nvfx_state_validate(nvfx)) { + nvfx_draw_elements_swtnl(pipe, indexBuffer, indexSize, + mode, start, count); return; } if (idxbuf) { - nv30_draw_elements_vbo(pipe, mode, start, count); + nvfx_draw_elements_vbo(pipe, mode, start, count); } else { - nv30_draw_elements_inline(pipe, indexBuffer, indexSize, + nvfx_draw_elements_inline(pipe, indexBuffer, indexSize, mode, start, count); } @@ -482,49 +489,50 @@ nv30_draw_elements(struct pipe_context *pipe, } static boolean -nv30_vbo_validate(struct nv30_context *nv30) +nvfx_vbo_validate(struct nvfx_context *nvfx) { struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct pipe_buffer *ib = nv30->idxbuf; - unsigned ib_format = nv30->idxbuf_format; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct pipe_buffer *ib = nvfx->idxbuf; + unsigned ib_format = nvfx->idxbuf_format; unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; int hw; vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr); + so_method(vtxbuf, eng3d, NV34TCL_VTXBUF_ADDRESS(0), nvfx->vtxelt->num_elements); vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr); + so_method(vtxfmt, eng3d, NV34TCL_VTXFMT(0), nvfx->vtxelt->num_elements); - for (hw = 0; hw < nv30->vtxelt_nr; hw++) { + for (hw = 0; hw < nvfx->vtxelt->num_elements; hw++) { struct pipe_vertex_element *ve; struct pipe_vertex_buffer *vb; unsigned type, ncomp; - ve = &nv30->vtxelt[hw]; - vb = &nv30->vtxbuf[ve->vertex_buffer_index]; + ve = &nvfx->vtxelt->pipe[hw]; + vb = &nvfx->vtxbuf[ve->vertex_buffer_index]; if (!vb->stride) { if (!sattr) sattr = so_new(16, 16 * 4, 0); - if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) { + if (nvfx_vbo_static_attrib(nvfx, sattr, hw, ve, vb)) { so_data(vtxbuf, 0); so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT); continue; } } - if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { - /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/ + if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { + nvfx->fallback_swtnl |= NVFX_NEW_ARRAYS; so_ref(NULL, &vtxbuf); so_ref(NULL, &vtxfmt); return FALSE; } - so_reloc(vtxbuf, nouveau_bo(vb->buffer), vb->buffer_offset + - ve->src_offset, vb_flags | NOUVEAU_BO_LOW | - NOUVEAU_BO_OR, 0, NV34TCL_VTXBUF_ADDRESS_DMA1); + so_reloc(vtxbuf, nouveau_bo(vb->buffer), + vb->buffer_offset + ve->src_offset, + vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, + 0, NV34TCL_VTXBUF_ADDRESS_DMA1); so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) | (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); } @@ -532,31 +540,31 @@ nv30_vbo_validate(struct nv30_context *nv30) if (ib) { struct nouveau_bo *bo = nouveau_bo(ib); - so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2); + so_method(vtxbuf, eng3d, NV34TCL_IDXBUF_ADDRESS, 2); so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, 0, NV34TCL_IDXBUF_FORMAT_DMA1); } - so_method(vtxbuf, rankine, 0x1710, 1); + so_method(vtxbuf, eng3d, 0x1710, 1); so_data (vtxbuf, 0); - so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]); + so_ref(vtxbuf, &nvfx->state.hw[NVFX_STATE_VTXBUF]); so_ref(NULL, &vtxbuf); - nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF); - so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXBUF); + so_ref(vtxfmt, &nvfx->state.hw[NVFX_STATE_VTXFMT]); so_ref(NULL, &vtxfmt); - nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT); - so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXFMT); + so_ref(sattr, &nvfx->state.hw[NVFX_STATE_VTXATTR]); so_ref(NULL, &sattr); - nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXATTR); return FALSE; } -struct nv30_state_entry nv30_state_vbo = { - .validate = nv30_vbo_validate, +struct nvfx_state_entry nvfx_state_vbo = { + .validate = nvfx_vbo_validate, .dirty = { - .pipe = NV30_NEW_ARRAYS, + .pipe = NVFX_NEW_ARRAYS, .hw = 0, } }; diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nvfx/nvfx_vertprog.c index c93c5d127c4..2d243be16a3 100644 --- a/src/gallium/drivers/nv40/nv40_vertprog.c +++ b/src/gallium/drivers/nvfx/nvfx_vertprog.c @@ -5,10 +5,11 @@ #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_util.h" -#include "nv40_context.h" -#include "nv40_state.h" +#include "nvfx_context.h" +#include "nvfx_state.h" /* TODO (at least...): * 1. Indexed consts + ARL @@ -21,76 +22,62 @@ * 4. bugs */ -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 8 -#define MASK_Y 4 -#define MASK_Z 2 -#define MASK_W 1 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE 0 -#define DEF_CTEST 0 -#include "nv40_shader.h" +#include "nv30_vertprog.h" +#include "nv40_vertprog.h" -#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv40_sr_neg((s)) -#define abs(s) nv40_sr_abs((s)) +#define NVFX_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n)) -#define NV40_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n)) +struct nvfx_vpc { + struct nvfx_vertex_program *vp; -struct nv40_vpc { - struct nv40_vertex_program *vp; - - struct nv40_vertex_program_exec *vpi; + struct nvfx_vertex_program_exec *vpi; unsigned r_temps; unsigned r_temps_discard; - struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; - struct nv40_sreg *r_address; - struct nv40_sreg *r_temp; + struct nvfx_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; + struct nvfx_sreg *r_address; + struct nvfx_sreg *r_temp; - struct nv40_sreg *imm; + struct nvfx_sreg *imm; unsigned nr_imm; unsigned hpos_idx; }; -static struct nv40_sreg -temp(struct nv40_vpc *vpc) +static struct nvfx_sreg +temp(struct nvfx_vpc *vpc) { int idx = ffs(~vpc->r_temps) - 1; if (idx < 0) { NOUVEAU_ERR("out of temps!!\n"); assert(0); - return nv40_sr(NV40SR_TEMP, 0); + return nvfx_sr(NVFXSR_TEMP, 0); } vpc->r_temps |= (1 << idx); vpc->r_temps_discard |= (1 << idx); - return nv40_sr(NV40SR_TEMP, idx); + return nvfx_sr(NVFXSR_TEMP, idx); } static INLINE void -release_temps(struct nv40_vpc *vpc) +release_temps(struct nvfx_vpc *vpc) { vpc->r_temps &= ~vpc->r_temps_discard; vpc->r_temps_discard = 0; } -static struct nv40_sreg -constant(struct nv40_vpc *vpc, int pipe, float x, float y, float z, float w) +static struct nvfx_sreg +constant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w) { - struct nv40_vertex_program *vp = vpc->vp; - struct nv40_vertex_program_data *vpd; + struct nvfx_vertex_program *vp = vpc->vp; + struct nvfx_vertex_program_data *vpd; int idx; if (pipe >= 0) { for (idx = 0; idx < vp->nr_consts; idx++) { if (vp->consts[idx].index == pipe) - return nv40_sr(NV40SR_CONST, idx); + return nvfx_sr(NVFXSR_CONST, idx); } } @@ -103,70 +90,70 @@ constant(struct nv40_vpc *vpc, int pipe, float x, float y, float z, float w) vpd->value[1] = y; vpd->value[2] = z; vpd->value[3] = w; - return nv40_sr(NV40SR_CONST, idx); + return nvfx_sr(NVFXSR_CONST, idx); } #define arith(cc,s,o,d,m,s0,s1,s2) \ - nv40_vp_arith((cc), (s), NV40_VP_INST_##o, (d), (m), (s0), (s1), (s2)) + nvfx_vp_arith(nvfx, (cc), NVFX_VP_INST_SLOT_##s, NVFX_VP_INST_##s##_OP_##o, (d), (m), (s0), (s1), (s2)) static void -emit_src(struct nv40_vpc *vpc, uint32_t *hw, int pos, struct nv40_sreg src) +emit_src(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int pos, struct nvfx_sreg src) { - struct nv40_vertex_program *vp = vpc->vp; + struct nvfx_vertex_program *vp = vpc->vp; uint32_t sr = 0; switch (src.type) { - case NV40SR_TEMP: - sr |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT); - sr |= (src.index << NV40_VP_SRC_TEMP_SRC_SHIFT); + case NVFXSR_TEMP: + sr |= (NVFX_VP(SRC_REG_TYPE_TEMP) << NVFX_VP(SRC_REG_TYPE_SHIFT)); + sr |= (src.index << NVFX_VP(SRC_TEMP_SRC_SHIFT)); break; - case NV40SR_INPUT: - sr |= (NV40_VP_SRC_REG_TYPE_INPUT << - NV40_VP_SRC_REG_TYPE_SHIFT); + case NVFXSR_INPUT: + sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) << + NVFX_VP(SRC_REG_TYPE_SHIFT)); vp->ir |= (1 << src.index); - hw[1] |= (src.index << NV40_VP_INST_INPUT_SRC_SHIFT); + hw[1] |= (src.index << NVFX_VP(INST_INPUT_SRC_SHIFT)); break; - case NV40SR_CONST: - sr |= (NV40_VP_SRC_REG_TYPE_CONST << - NV40_VP_SRC_REG_TYPE_SHIFT); + case NVFXSR_CONST: + sr |= (NVFX_VP(SRC_REG_TYPE_CONST) << + NVFX_VP(SRC_REG_TYPE_SHIFT)); assert(vpc->vpi->const_index == -1 || vpc->vpi->const_index == src.index); vpc->vpi->const_index = src.index; break; - case NV40SR_NONE: - sr |= (NV40_VP_SRC_REG_TYPE_INPUT << - NV40_VP_SRC_REG_TYPE_SHIFT); + case NVFXSR_NONE: + sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) << + NVFX_VP(SRC_REG_TYPE_SHIFT)); break; default: assert(0); } if (src.negate) - sr |= NV40_VP_SRC_NEGATE; + sr |= NVFX_VP(SRC_NEGATE); if (src.abs) hw[0] |= (1 << (21 + pos)); - sr |= ((src.swz[0] << NV40_VP_SRC_SWZ_X_SHIFT) | - (src.swz[1] << NV40_VP_SRC_SWZ_Y_SHIFT) | - (src.swz[2] << NV40_VP_SRC_SWZ_Z_SHIFT) | - (src.swz[3] << NV40_VP_SRC_SWZ_W_SHIFT)); + sr |= ((src.swz[0] << NVFX_VP(SRC_SWZ_X_SHIFT)) | + (src.swz[1] << NVFX_VP(SRC_SWZ_Y_SHIFT)) | + (src.swz[2] << NVFX_VP(SRC_SWZ_Z_SHIFT)) | + (src.swz[3] << NVFX_VP(SRC_SWZ_W_SHIFT))); switch (pos) { case 0: - hw[1] |= ((sr & NV40_VP_SRC0_HIGH_MASK) >> - NV40_VP_SRC0_HIGH_SHIFT) << NV40_VP_INST_SRC0H_SHIFT; - hw[2] |= (sr & NV40_VP_SRC0_LOW_MASK) << - NV40_VP_INST_SRC0L_SHIFT; + hw[1] |= ((sr & NVFX_VP(SRC0_HIGH_MASK)) >> + NVFX_VP(SRC0_HIGH_SHIFT)) << NVFX_VP(INST_SRC0H_SHIFT); + hw[2] |= (sr & NVFX_VP(SRC0_LOW_MASK)) << + NVFX_VP(INST_SRC0L_SHIFT); break; case 1: - hw[2] |= sr << NV40_VP_INST_SRC1_SHIFT; + hw[2] |= sr << NVFX_VP(INST_SRC1_SHIFT); break; case 2: - hw[2] |= ((sr & NV40_VP_SRC2_HIGH_MASK) >> - NV40_VP_SRC2_HIGH_SHIFT) << NV40_VP_INST_SRC2H_SHIFT; - hw[3] |= (sr & NV40_VP_SRC2_LOW_MASK) << - NV40_VP_INST_SRC2L_SHIFT; + hw[2] |= ((sr & NVFX_VP(SRC2_HIGH_MASK)) >> + NVFX_VP(SRC2_HIGH_SHIFT)) << NVFX_VP(INST_SRC2H_SHIFT); + hw[3] |= (sr & NVFX_VP(SRC2_LOW_MASK)) << + NVFX_VP(INST_SRC2L_SHIFT); break; default: assert(0); @@ -174,78 +161,114 @@ emit_src(struct nv40_vpc *vpc, uint32_t *hw, int pos, struct nv40_sreg src) } static void -emit_dst(struct nv40_vpc *vpc, uint32_t *hw, int slot, struct nv40_sreg dst) +emit_dst(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int slot, struct nvfx_sreg dst) { - struct nv40_vertex_program *vp = vpc->vp; + struct nvfx_vertex_program *vp = vpc->vp; switch (dst.type) { - case NV40SR_TEMP: - hw[3] |= NV40_VP_INST_DEST_MASK; - if (slot == 0) { - hw[0] |= (dst.index << - NV40_VP_INST_VEC_DEST_TEMP_SHIFT); - } else { - hw[3] |= (dst.index << - NV40_VP_INST_SCA_DEST_TEMP_SHIFT); + case NVFXSR_TEMP: + if(!nvfx->is_nv4x) + hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT); + else { + hw[3] |= NV40_VP_INST_DEST_MASK; + if (slot == 0) { + hw[0] |= (dst.index << + NV40_VP_INST_VEC_DEST_TEMP_SHIFT); + } else { + hw[3] |= (dst.index << + NV40_VP_INST_SCA_DEST_TEMP_SHIFT); + } } break; - case NV40SR_OUTPUT: + case NVFXSR_OUTPUT: + /* TODO: this may be wrong because on nv30 COL0 and BFC0 are swapped */ switch (dst.index) { - case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; - case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; - case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; - case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; - case NV40_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; - case NV40_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; - case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; - case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; - case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; - case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; - case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; - case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; - case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; - case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; - case NV40_VP_INST_DEST_CLIP(0): + case NVFX_VP_INST_DEST_CLIP(0): vp->or |= (1 << 6); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE0; - dst.index = NV40_VP_INST_DEST_FOGC; + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0; + dst.index = NVFX_VP(INST_DEST_FOGC); break; - case NV40_VP_INST_DEST_CLIP(1): + case NVFX_VP_INST_DEST_CLIP(1): vp->or |= (1 << 7); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE1; - dst.index = NV40_VP_INST_DEST_FOGC; + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1; + dst.index = NVFX_VP(INST_DEST_FOGC); break; - case NV40_VP_INST_DEST_CLIP(2): + case NVFX_VP_INST_DEST_CLIP(2): vp->or |= (1 << 8); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE2; - dst.index = NV40_VP_INST_DEST_FOGC; + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2; + dst.index = NVFX_VP(INST_DEST_FOGC); break; - case NV40_VP_INST_DEST_CLIP(3): + case NVFX_VP_INST_DEST_CLIP(3): vp->or |= (1 << 9); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE3; - dst.index = NV40_VP_INST_DEST_PSZ; + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3; + dst.index = NVFX_VP(INST_DEST_PSZ); break; - case NV40_VP_INST_DEST_CLIP(4): + case NVFX_VP_INST_DEST_CLIP(4): vp->or |= (1 << 10); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE4; - dst.index = NV40_VP_INST_DEST_PSZ; + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4; + dst.index = NVFX_VP(INST_DEST_PSZ); break; - case NV40_VP_INST_DEST_CLIP(5): + case NVFX_VP_INST_DEST_CLIP(5): vp->or |= (1 << 11); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE5; - dst.index = NV40_VP_INST_DEST_PSZ; + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5; + dst.index = NVFX_VP(INST_DEST_PSZ); break; default: + if(!nvfx->is_nv4x) { + switch (dst.index) { + case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; + case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; + case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; + case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; + case NV30_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break; + case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; + case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; + case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; + case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; + case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; + case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; + case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; + case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; + case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; + } + } else { + switch (dst.index) { + case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; + case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; + case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; + case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; + case NV40_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break; + case NV40_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; + case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; + case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; + case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; + case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; + case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; + case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; + case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; + case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; + } + } break; } - hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT); - if (slot == 0) { - hw[0] |= NV40_VP_INST_VEC_RESULT; - hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + if(!nvfx->is_nv4x) { + hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT); + hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + + /*XXX: no way this is entirely correct, someone needs to + * figure out what exactly it is. + */ + hw[3] |= 0x800; } else { - hw[3] |= NV40_VP_INST_SCA_RESULT; - hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; + hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT); + if (slot == 0) { + hw[0] |= NV40_VP_INST_VEC_RESULT; + hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + } else { + hw[3] |= NV40_VP_INST_SCA_RESULT; + hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; + } } break; default: @@ -254,12 +277,12 @@ emit_dst(struct nv40_vpc *vpc, uint32_t *hw, int slot, struct nv40_sreg dst) } static void -nv40_vp_arith(struct nv40_vpc *vpc, int slot, int op, - struct nv40_sreg dst, int mask, - struct nv40_sreg s0, struct nv40_sreg s1, - struct nv40_sreg s2) +nvfx_vp_arith(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, int slot, int op, + struct nvfx_sreg dst, int mask, + struct nvfx_sreg s0, struct nvfx_sreg s1, + struct nvfx_sreg s2) { - struct nv40_vertex_program *vp = vpc->vp; + struct nvfx_vertex_program *vp = vpc->vp; uint32_t *hw; vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); @@ -269,35 +292,53 @@ nv40_vp_arith(struct nv40_vpc *vpc, int slot, int op, hw = vpc->vpi->data; - hw[0] |= (NV40_VP_INST_COND_TR << NV40_VP_INST_COND_SHIFT); - hw[0] |= ((0 << NV40_VP_INST_COND_SWZ_X_SHIFT) | - (1 << NV40_VP_INST_COND_SWZ_Y_SHIFT) | - (2 << NV40_VP_INST_COND_SWZ_Z_SHIFT) | - (3 << NV40_VP_INST_COND_SWZ_W_SHIFT)); - - if (slot == 0) { - hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT); - hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; - hw[3] |= (mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT); - } else { - hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT); - hw[0] |= (NV40_VP_INST_VEC_DEST_TEMP_MASK | (1 << 20)); - hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT); + hw[0] |= (NVFX_COND_TR << NVFX_VP(INST_COND_SHIFT)); + hw[0] |= ((0 << NVFX_VP(INST_COND_SWZ_X_SHIFT)) | + (1 << NVFX_VP(INST_COND_SWZ_Y_SHIFT)) | + (2 << NVFX_VP(INST_COND_SWZ_Z_SHIFT)) | + (3 << NVFX_VP(INST_COND_SWZ_W_SHIFT))); + + if(!nvfx->is_nv4x) { + hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT); +// hw[3] |= NVFX_VP(INST_SCA_DEST_TEMP_MASK); +// hw[3] |= (mask << NVFX_VP(INST_VEC_WRITEMASK_SHIFT)); + + if (dst.type == NVFXSR_OUTPUT) { + if (slot) + hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT); + else + hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT); + } else { + if (slot) + hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT); + else + hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT); + } + } else { + if (slot == 0) { + hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT); + hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; + hw[3] |= (mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT); + } else { + hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT); + hw[0] |= (NV40_VP_INST_VEC_DEST_TEMP_MASK | (1 << 20)); + hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT); + } } - emit_dst(vpc, hw, slot, dst); - emit_src(vpc, hw, 0, s0); - emit_src(vpc, hw, 1, s1); - emit_src(vpc, hw, 2, s2); + emit_dst(nvfx, vpc, hw, slot, dst); + emit_src(nvfx, vpc, hw, 0, s0); + emit_src(nvfx, vpc, hw, 1, s1); + emit_src(nvfx, vpc, hw, 2, s2); } -static INLINE struct nv40_sreg -tgsi_src(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc) { - struct nv40_sreg src; +static INLINE struct nvfx_sreg +tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) { + struct nvfx_sreg src; switch (fsrc->Register.File) { case TGSI_FILE_INPUT: - src = nv40_sr(NV40SR_INPUT, fsrc->Register.Index); + src = nvfx_sr(NVFXSR_INPUT, fsrc->Register.Index); break; case TGSI_FILE_CONSTANT: src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0); @@ -322,9 +363,9 @@ tgsi_src(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc) { return src; } -static INLINE struct nv40_sreg -tgsi_dst(struct nv40_vpc *vpc, const struct tgsi_full_dst_register *fdst) { - struct nv40_sreg dst; +static INLINE struct nvfx_sreg +tgsi_dst(struct nvfx_vpc *vpc, const struct tgsi_full_dst_register *fdst) { + struct nvfx_sreg dst; switch (fdst->Register.File) { case TGSI_FILE_OUTPUT: @@ -349,52 +390,19 @@ tgsi_mask(uint tgsi) { int mask = 0; - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; + if (tgsi & TGSI_WRITEMASK_X) mask |= NVFX_VP_MASK_X; + if (tgsi & TGSI_WRITEMASK_Y) mask |= NVFX_VP_MASK_Y; + if (tgsi & TGSI_WRITEMASK_Z) mask |= NVFX_VP_MASK_Z; + if (tgsi & TGSI_WRITEMASK_W) mask |= NVFX_VP_MASK_W; return mask; } static boolean -src_native_swz(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc, - struct nv40_sreg *src) -{ - const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - struct nv40_sreg tgsi = tgsi_src(vpc, fsrc); - uint mask = 0; - uint c; - - for (c = 0; c < 4; c++) { - switch (tgsi_util_get_full_src_register_swizzle(fsrc, c)) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - mask |= tgsi_mask(1 << c); - break; - default: - assert(0); - } - } - - if (mask == MASK_ALL) - return TRUE; - - *src = temp(vpc); - - if (mask) - arith(vpc, 0, OP_MOV, *src, mask, tgsi, none, none); - - return FALSE; -} - -static boolean -nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, +nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, const struct tgsi_full_instruction *finst) { - struct nv40_sreg src[3], dst, tmp; - struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); + struct nvfx_sreg src[3], dst, tmp; + struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0); int mask; int ai = -1, ci = -1, ii = -1; int i; @@ -418,23 +426,12 @@ nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, switch (fsrc->Register.File) { case TGSI_FILE_INPUT: - case TGSI_FILE_CONSTANT: - case TGSI_FILE_TEMPORARY: - if (!src_native_swz(vpc, fsrc, &src[i])) - continue; - break; - default: - break; - } - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: if (ai == -1 || ai == fsrc->Register.Index) { ai = fsrc->Register.Index; src[i] = tgsi_src(vpc, fsrc); } else { src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, + arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL, tgsi_src(vpc, fsrc), none, none); } break; @@ -445,7 +442,7 @@ nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, src[i] = tgsi_src(vpc, fsrc); } else { src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, + arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL, tgsi_src(vpc, fsrc), none, none); } break; @@ -456,7 +453,7 @@ nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, src[i] = tgsi_src(vpc, fsrc); } else { src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, + arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL, tgsi_src(vpc, fsrc), none, none); } break; @@ -474,93 +471,96 @@ nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, switch (finst->Instruction.Opcode) { case TGSI_OPCODE_ABS: - arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); + arith(vpc, VEC, MOV, dst, mask, abs(src[0]), none, none); break; case TGSI_OPCODE_ADD: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); + arith(vpc, VEC, ADD, dst, mask, src[0], none, src[1]); break; case TGSI_OPCODE_ARL: - arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); + arith(vpc, VEC, ARL, dst, mask, src[0], none, none); break; case TGSI_OPCODE_DP3: - arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); + arith(vpc, VEC, DP3, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_DP4: - arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); + arith(vpc, VEC, DP4, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_DPH: - arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); + arith(vpc, VEC, DPH, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_DST: - arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); + arith(vpc, VEC, DST, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_EX2: - arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); + arith(vpc, SCA, EX2, dst, mask, none, none, src[0]); break; case TGSI_OPCODE_EXP: - arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); + arith(vpc, SCA, EXP, dst, mask, none, none, src[0]); break; case TGSI_OPCODE_FLR: - arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); + arith(vpc, VEC, FLR, dst, mask, src[0], none, none); break; case TGSI_OPCODE_FRC: - arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); + arith(vpc, VEC, FRC, dst, mask, src[0], none, none); break; case TGSI_OPCODE_LG2: - arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); + arith(vpc, SCA, LG2, dst, mask, none, none, src[0]); break; case TGSI_OPCODE_LIT: - arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); + arith(vpc, SCA, LIT, dst, mask, none, none, src[0]); break; case TGSI_OPCODE_LOG: - arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); + arith(vpc, SCA, LOG, dst, mask, none, none, src[0]); break; case TGSI_OPCODE_MAD: - arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); + arith(vpc, VEC, MAD, dst, mask, src[0], src[1], src[2]); break; case TGSI_OPCODE_MAX: - arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); + arith(vpc, VEC, MAX, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_MIN: - arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); + arith(vpc, VEC, MIN, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_MOV: - arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); + arith(vpc, VEC, MOV, dst, mask, src[0], none, none); break; case TGSI_OPCODE_MUL: - arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); + arith(vpc, VEC, MUL, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_POW: tmp = temp(vpc); - arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, + arith(vpc, SCA, LG2, tmp, NVFX_VP_MASK_X, none, none, swz(src[0], X, X, X, X)); - arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), + arith(vpc, VEC, MUL, tmp, NVFX_VP_MASK_X, swz(tmp, X, X, X, X), swz(src[1], X, X, X, X), none); - arith(vpc, 1, OP_EX2, dst, mask, none, none, + arith(vpc, SCA, EX2, dst, mask, none, none, swz(tmp, X, X, X, X)); break; case TGSI_OPCODE_RCP: - arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); + arith(vpc, SCA, RCP, dst, mask, none, none, src[0]); break; case TGSI_OPCODE_RET: break; case TGSI_OPCODE_RSQ: - arith(vpc, 1, OP_RSQ, dst, mask, none, none, abs(src[0])); + arith(vpc, SCA, RSQ, dst, mask, none, none, abs(src[0])); break; case TGSI_OPCODE_SGE: - arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); + arith(vpc, VEC, SGE, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_SGT: + arith(vpc, VEC, SGT, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_SLT: - arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); + arith(vpc, VEC, SLT, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_SUB: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); + arith(vpc, VEC, ADD, dst, mask, src[0], none, neg(src[1])); break; case TGSI_OPCODE_XPD: tmp = temp(vpc); - arith(vpc, 0, OP_MUL, tmp, mask, + arith(vpc, VEC, MUL, tmp, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), + arith(vpc, VEC, MAD, dst, (mask & ~NVFX_VP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)); break; @@ -574,7 +574,7 @@ nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, } static boolean -nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc, +nvfx_vertprog_parse_decl_output(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, const struct tgsi_full_declaration *fdec) { unsigned idx = fdec->Range.First; @@ -582,15 +582,15 @@ nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc, switch (fdec->Semantic.Name) { case TGSI_SEMANTIC_POSITION: - hw = NV40_VP_INST_DEST_POS; + hw = NVFX_VP(INST_DEST_POS); vpc->hpos_idx = idx; break; case TGSI_SEMANTIC_COLOR: if (fdec->Semantic.Index == 0) { - hw = NV40_VP_INST_DEST_COL0; + hw = NVFX_VP(INST_DEST_COL0); } else if (fdec->Semantic.Index == 1) { - hw = NV40_VP_INST_DEST_COL1; + hw = NVFX_VP(INST_DEST_COL1); } else { NOUVEAU_ERR("bad colour semantic index\n"); return FALSE; @@ -598,24 +598,24 @@ nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc, break; case TGSI_SEMANTIC_BCOLOR: if (fdec->Semantic.Index == 0) { - hw = NV40_VP_INST_DEST_BFC0; + hw = NVFX_VP(INST_DEST_BFC0); } else if (fdec->Semantic.Index == 1) { - hw = NV40_VP_INST_DEST_BFC1; + hw = NVFX_VP(INST_DEST_BFC1); } else { NOUVEAU_ERR("bad bcolour semantic index\n"); return FALSE; } break; case TGSI_SEMANTIC_FOG: - hw = NV40_VP_INST_DEST_FOGC; + hw = NVFX_VP(INST_DEST_FOGC); break; case TGSI_SEMANTIC_PSIZE: - hw = NV40_VP_INST_DEST_PSZ; + hw = NVFX_VP(INST_DEST_PSZ); break; case TGSI_SEMANTIC_GENERIC: if (fdec->Semantic.Index <= 7) { - hw = NV40_VP_INST_DEST_TC(fdec->Semantic.Index); + hw = NVFX_VP(INST_DEST_TC(fdec->Semantic.Index)); } else { NOUVEAU_ERR("bad generic semantic index\n"); return FALSE; @@ -630,12 +630,12 @@ nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc, return FALSE; } - vpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw); + vpc->r_result[idx] = nvfx_sr(NVFXSR_OUTPUT, hw); return TRUE; } static boolean -nv40_vertprog_prepare(struct nv40_vpc *vpc) +nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc) { struct tgsi_parse_context p; int high_temp = -1, high_addr = -1, nr_imm = 0, i; @@ -670,7 +670,7 @@ nv40_vertprog_prepare(struct nv40_vpc *vpc) break; #endif case TGSI_FILE_OUTPUT: - if (!nv40_vertprog_parse_decl_output(vpc, fdec)) + if (!nvfx_vertprog_parse_decl_output(nvfx, vpc, fdec)) return FALSE; break; default: @@ -691,7 +691,7 @@ nv40_vertprog_prepare(struct nv40_vpc *vpc) if (fdst->Register.Index > high_addr) high_addr = fdst->Register.Index; } - + } break; #endif @@ -702,18 +702,18 @@ nv40_vertprog_prepare(struct nv40_vpc *vpc) tgsi_parse_free(&p); if (nr_imm) { - vpc->imm = CALLOC(nr_imm, sizeof(struct nv40_sreg)); + vpc->imm = CALLOC(nr_imm, sizeof(struct nvfx_sreg)); assert(vpc->imm); } if (++high_temp) { - vpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg)); + vpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_sreg)); for (i = 0; i < high_temp; i++) vpc->r_temp[i] = temp(vpc); } if (++high_addr) { - vpc->r_address = CALLOC(high_addr, sizeof(struct nv40_sreg)); + vpc->r_address = CALLOC(high_addr, sizeof(struct nvfx_sreg)); for (i = 0; i < high_addr; i++) vpc->r_address[i] = temp(vpc); } @@ -723,20 +723,20 @@ nv40_vertprog_prepare(struct nv40_vpc *vpc) } static void -nv40_vertprog_translate(struct nv40_context *nv40, - struct nv40_vertex_program *vp) +nvfx_vertprog_translate(struct nvfx_context *nvfx, + struct nvfx_vertex_program *vp) { struct tgsi_parse_context parse; - struct nv40_vpc *vpc = NULL; - struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); + struct nvfx_vpc *vpc = NULL; + struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0); int i; - vpc = CALLOC(1, sizeof(struct nv40_vpc)); + vpc = CALLOC(1, sizeof(struct nvfx_vpc)); if (!vpc) return; vpc->vp = vp; - if (!nv40_vertprog_prepare(vpc)) { + if (!nvfx_vertprog_prepare(nvfx, vpc)) { FREE(vpc); return; } @@ -775,7 +775,7 @@ nv40_vertprog_translate(struct nv40_context *nv40, { const struct tgsi_full_instruction *finst; finst = &parse.FullToken.FullInstruction; - if (!nv40_vertprog_parse_instruction(vpc, finst)) + if (!nvfx_vertprog_parse_instruction(nvfx, vpc, finst)) goto out_err; } break; @@ -785,74 +785,74 @@ nv40_vertprog_translate(struct nv40_context *nv40, } /* Write out HPOS if it was redirected to a temp earlier */ - if (vpc->r_result[vpc->hpos_idx].type != NV40SR_OUTPUT) { - struct nv40_sreg hpos = nv40_sr(NV40SR_OUTPUT, - NV40_VP_INST_DEST_POS); - struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx]; + if (vpc->r_result[vpc->hpos_idx].type != NVFXSR_OUTPUT) { + struct nvfx_sreg hpos = nvfx_sr(NVFXSR_OUTPUT, + NVFX_VP(INST_DEST_POS)); + struct nvfx_sreg htmp = vpc->r_result[vpc->hpos_idx]; - arith(vpc, 0, OP_MOV, hpos, MASK_ALL, htmp, none, none); + arith(vpc, VEC, MOV, hpos, NVFX_VP_MASK_ALL, htmp, none, none); } /* Insert code to handle user clip planes */ for (i = 0; i < vp->ucp.nr; i++) { - struct nv40_sreg cdst = nv40_sr(NV40SR_OUTPUT, - NV40_VP_INST_DEST_CLIP(i)); - struct nv40_sreg ceqn = constant(vpc, -1, - nv40->clip.ucp[i][0], - nv40->clip.ucp[i][1], - nv40->clip.ucp[i][2], - nv40->clip.ucp[i][3]); - struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx]; + struct nvfx_sreg cdst = nvfx_sr(NVFXSR_OUTPUT, + NVFX_VP_INST_DEST_CLIP(i)); + struct nvfx_sreg ceqn = constant(vpc, -1, + nvfx->clip.ucp[i][0], + nvfx->clip.ucp[i][1], + nvfx->clip.ucp[i][2], + nvfx->clip.ucp[i][3]); + struct nvfx_sreg htmp = vpc->r_result[vpc->hpos_idx]; unsigned mask; switch (i) { - case 0: case 3: mask = MASK_Y; break; - case 1: case 4: mask = MASK_Z; break; - case 2: case 5: mask = MASK_W; break; + case 0: case 3: mask = NVFX_VP_MASK_Y; break; + case 1: case 4: mask = NVFX_VP_MASK_Z; break; + case 2: case 5: mask = NVFX_VP_MASK_W; break; default: NOUVEAU_ERR("invalid clip dist #%d\n", i); goto out_err; } - arith(vpc, 0, OP_DP4, cdst, mask, htmp, ceqn, none); + arith(vpc, VEC, DP4, cdst, mask, htmp, ceqn, none); } - vp->insns[vp->nr_insns - 1].data[3] |= NV40_VP_INST_LAST; + vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST; vp->translated = TRUE; out_err: tgsi_parse_free(&parse); if (vpc->r_temp) - FREE(vpc->r_temp); + FREE(vpc->r_temp); if (vpc->r_address) - FREE(vpc->r_address); - if (vpc->imm) - FREE(vpc->imm); + FREE(vpc->r_address); + if (vpc->imm) + FREE(vpc->imm); FREE(vpc); } static boolean -nv40_vertprog_validate(struct nv40_context *nv40) -{ - struct pipe_screen *pscreen = nv40->pipe.screen; - struct nv40_screen *screen = nv40->screen; +nvfx_vertprog_validate(struct nvfx_context *nvfx) +{ + struct pipe_screen *pscreen = nvfx->pipe.screen; + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - struct nv40_vertex_program *vp; + struct nouveau_grobj *eng3d = screen->eng3d; + struct nvfx_vertex_program *vp; struct pipe_buffer *constbuf; boolean upload_code = FALSE, upload_data = FALSE; int i; - if (nv40->render_mode == HW) { - vp = nv40->vertprog; - constbuf = nv40->constbuf[PIPE_SHADER_VERTEX]; + if (nvfx->render_mode == HW) { + vp = nvfx->vertprog; + constbuf = nvfx->constbuf[PIPE_SHADER_VERTEX]; - if ((nv40->dirty & NV40_NEW_UCP) || - memcmp(&nv40->clip, &vp->ucp, sizeof(vp->ucp))) { - nv40_vertprog_destroy(nv40, vp); - memcpy(&vp->ucp, &nv40->clip, sizeof(vp->ucp)); + if ((nvfx->dirty & NVFX_NEW_UCP) || + memcmp(&nvfx->clip, &vp->ucp, sizeof(vp->ucp))) { + nvfx_vertprog_destroy(nvfx, vp); + memcpy(&vp->ucp, &nvfx->clip, sizeof(vp->ucp)); } } else { - vp = nv40->swtnl.vertprog; + vp = nvfx->swtnl.vertprog; constbuf = NULL; } @@ -860,24 +860,24 @@ nv40_vertprog_validate(struct nv40_context *nv40) if (vp->translated) goto check_gpu_resources; - nv40->fallback_swtnl &= ~NV40_NEW_VERTPROG; - nv40_vertprog_translate(nv40, vp); + nvfx->fallback_swtnl &= ~NVFX_NEW_VERTPROG; + nvfx_vertprog_translate(nvfx, vp); if (!vp->translated) { - nv40->fallback_swtnl |= NV40_NEW_VERTPROG; - return FALSE; + nvfx->fallback_swtnl |= NVFX_NEW_VERTPROG; + return FALSE; } check_gpu_resources: /* Allocate hw vtxprog exec slots */ if (!vp->exec) { - struct nouveau_resource *heap = nv40->screen->vp_exec_heap; + struct nouveau_resource *heap = nvfx->screen->vp_exec_heap; struct nouveau_stateobj *so; uint vplen = vp->nr_insns; if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) { while (heap->next && heap->size < vplen) { - struct nv40_vertex_program *evict; - + struct nvfx_vertex_program *evict; + evict = heap->next->priv; nouveau_resource_free(&evict->exec); } @@ -887,12 +887,14 @@ check_gpu_resources: } so = so_new(3, 4, 0); - so_method(so, curie, NV40TCL_VP_START_FROM_ID, 1); + so_method(so, eng3d, NV34TCL_VP_START_FROM_ID, 1); so_data (so, vp->exec->start); - so_method(so, curie, NV40TCL_VP_ATTRIB_EN, 2); - so_data (so, vp->ir); - so_data (so, vp->or); - so_method(so, curie, NV40TCL_CLIP_PLANE_ENABLE, 1); + if(nvfx->is_nv4x) { + so_method(so, eng3d, NV40TCL_VP_ATTRIB_EN, 2); + so_data (so, vp->ir); + so_data (so, vp->or); + } + so_method(so, eng3d, NV34TCL_VP_CLIP_PLANES_ENABLE, 1); so_data (so, vp->clip_ctrl); so_ref(so, &vp->so); so_ref(NULL, &so); @@ -902,12 +904,12 @@ check_gpu_resources: /* Allocate hw vtxprog const slots */ if (vp->nr_consts && !vp->data) { - struct nouveau_resource *heap = nv40->screen->vp_data_heap; + struct nouveau_resource *heap = nvfx->screen->vp_data_heap; if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) { while (heap->next && heap->size < vp->nr_consts) { - struct nv40_vertex_program *evict; - + struct nvfx_vertex_program *evict; + evict = heap->next->priv; nouveau_resource_free(&evict->data); } @@ -929,7 +931,7 @@ check_gpu_resources: */ if (vp->exec_start != vp->exec->start) { for (i = 0; i < vp->nr_insns; i++) { - struct nv40_vertex_program_exec *vpi = &vp->insns[i]; + struct nvfx_vertex_program_exec *vpi = &vp->insns[i]; if (vpi->has_branch_offset) { assert(0); @@ -941,13 +943,13 @@ check_gpu_resources: if (vp->nr_consts && vp->data_start != vp->data->start) { for (i = 0; i < vp->nr_insns; i++) { - struct nv40_vertex_program_exec *vpi = &vp->insns[i]; + struct nvfx_vertex_program_exec *vpi = &vp->insns[i]; if (vpi->const_index >= 0) { - vpi->data[1] &= ~NV40_VP_INST_CONST_SRC_MASK; + vpi->data[1] &= ~NVFX_VP(INST_CONST_SRC_MASK); vpi->data[1] |= (vpi->const_index + vp->data->start) << - NV40_VP_INST_CONST_SRC_SHIFT; + NVFX_VP(INST_CONST_SRC_SHIFT); } } @@ -965,7 +967,7 @@ check_gpu_resources: } for (i = 0; i < vp->nr_consts; i++) { - struct nv40_vertex_program_data *vpd = &vp->consts[i]; + struct nvfx_vertex_program_data *vpd = &vp->consts[i]; if (vpd->index >= 0) { if (!upload_data && @@ -976,13 +978,13 @@ check_gpu_resources: 4 * sizeof(float)); } - BEGIN_RING(chan, curie, NV40TCL_VP_UPLOAD_CONST_ID, 5); + BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_CONST_ID, 5); OUT_RING (chan, i + vp->data->start); OUT_RINGp (chan, (uint32_t *)vpd->value, 4); } if (constbuf) - pscreen->buffer_unmap(pscreen, constbuf); + pipe_buffer_unmap(pscreen, constbuf); } /* Upload vtxprog */ @@ -995,16 +997,16 @@ check_gpu_resources: NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[3]); } #endif - BEGIN_RING(chan, curie, NV40TCL_VP_UPLOAD_FROM_ID, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_FROM_ID, 1); OUT_RING (chan, vp->exec->start); for (i = 0; i < vp->nr_insns; i++) { - BEGIN_RING(chan, curie, NV40TCL_VP_UPLOAD_INST(0), 4); + BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_INST(0), 4); OUT_RINGp (chan, vp->insns[i].data, 4); } } - if (vp->so != nv40->state.hw[NV40_STATE_VERTPROG]) { - so_ref(vp->so, &nv40->state.hw[NV40_STATE_VERTPROG]); + if (vp->so != nvfx->state.hw[NVFX_STATE_VERTPROG]) { + so_ref(vp->so, &nvfx->state.hw[NVFX_STATE_VERTPROG]); return TRUE; } @@ -1012,7 +1014,7 @@ check_gpu_resources: } void -nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp) +nvfx_vertprog_destroy(struct nvfx_context *nvfx, struct nvfx_vertex_program *vp) { vp->translated = FALSE; @@ -1038,11 +1040,10 @@ nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp) so_ref(NULL, &vp->so); } -struct nv40_state_entry nv40_state_vertprog = { - .validate = nv40_vertprog_validate, +struct nvfx_state_entry nvfx_state_vertprog = { + .validate = nvfx_vertprog_validate, .dirty = { - .pipe = NV40_NEW_VERTPROG | NV40_NEW_UCP, - .hw = NV40_STATE_VERTPROG, + .pipe = NVFX_NEW_VERTPROG | NVFX_NEW_UCP, + .hw = NVFX_STATE_VERTPROG, } }; - diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 1f69daec819..a6529b20604 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -14,12 +14,14 @@ C_SOURCES = \ r300_query.c \ r300_render.c \ r300_screen.c \ + r300_screen_buffer.c \ r300_state.c \ r300_state_derived.c \ r300_state_invariant.c \ r300_vs.c \ r300_texture.c \ - r300_tgsi_to_rc.c + r300_tgsi_to_rc.c \ + r300_transfer.c LIBRARY_INCLUDES = \ -I$(TOP)/src/mesa/drivers/dri/r300/compiler \ diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript index 183aa17f9b3..27b2e309932 100644 --- a/src/gallium/drivers/r300/SConscript +++ b/src/gallium/drivers/r300/SConscript @@ -30,6 +30,7 @@ r300 = env.ConvenienceLibrary( 'r300_vs.c', 'r300_texture.c', 'r300_tgsi_to_rc.c', + 'r300_transfer.c', ] + r300compiler) + r300compiler Export('r300') diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 513cc0f5d44..f99f9dffaa5 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -36,6 +36,7 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state); util_blitter_save_viewport(r300->blitter, &r300->viewport); util_blitter_save_clip(r300->blitter, &r300->clip); + util_blitter_save_vertex_elements(r300->blitter, r300->velems); } /* Clear currently bound buffers. */ @@ -112,9 +113,9 @@ static void r300_hw_copy(struct pipe_context* pipe, util_blitter_save_fragment_sampler_states( r300->blitter, state->sampler_count, (void**)state->sampler_states); - util_blitter_save_fragment_sampler_textures( + util_blitter_save_fragment_sampler_views( r300->blitter, state->texture_count, - (struct pipe_texture**)state->textures); + state->fragment_sampler_views); /* Do a copy */ util_blitter_copy(r300->blitter, diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 86b98a4ba52..d994a46ccfe 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -24,6 +24,7 @@ #include "util/u_memory.h" #include "util/u_simple_list.h" +#include "util/u_upload_mgr.h" #include "r300_blit.h" #include "r300_context.h" @@ -34,6 +35,7 @@ #include "r300_screen.h" #include "r300_state_invariant.h" #include "r300_texture.h" +#include "r300_transfer.h" #include "radeon_winsys.h" @@ -54,13 +56,15 @@ static void r300_destroy_context(struct pipe_context* context) FREE(query); } + u_upload_destroy(r300->upload_vb); + u_upload_destroy(r300->upload_ib); + FREE(r300->blend_color_state.state); FREE(r300->clip_state.state); FREE(r300->fb_state.state); FREE(r300->rs_block_state.state); FREE(r300->scissor_state.state); FREE(r300->textures_state.state); - FREE(r300->vertex_stream_state.state); FREE(r300->vap_output_state.state); FREE(r300->viewport_state.state); FREE(r300->ztop_state.state); @@ -72,11 +76,7 @@ r300_is_texture_referenced(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level) { - struct pipe_buffer* buf = 0; - - r300_get_texture_buffer(pipe->screen, texture, &buf, NULL); - - return pipe->is_buffer_referenced(pipe, buf); + return 0; } static unsigned int @@ -86,7 +86,14 @@ r300_is_buffer_referenced(struct pipe_context *pipe, /* This only checks to see whether actual hardware buffers are * referenced. Since we use managed BOs and transfers, it's actually not * possible for pipe_buffers to ever reference the actual hardware, so - * buffers are never referenced. */ + * buffers are never referenced. + */ + + /* XXX: that doesn't make sense given that + * r300_is_texture_referenced is implemented on top of this + * function and hardware can certainly refer to textures + * directly... + */ return 0; } @@ -143,7 +150,6 @@ static void r300_setup_atoms(struct r300_context* r300) r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); r300->textures_state.state = CALLOC_STRUCT(r300_textures_state); - r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state); r300->vap_output_state.state = CALLOC_STRUCT(r300_vap_output_state); r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); @@ -154,14 +160,14 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, { struct r300_context* r300 = CALLOC_STRUCT(r300_context); struct r300_screen* r300screen = r300_screen(screen); - struct radeon_winsys* radeon_winsys = r300screen->radeon_winsys; + struct r300_winsys_screen *rws = r300screen->rws; if (!r300) return NULL; - r300->winsys = radeon_winsys; + r300->rws = rws; - r300->context.winsys = (struct pipe_winsys*)radeon_winsys; + r300->context.winsys = (struct pipe_winsys*)rws; r300->context.screen = screen; r300->context.priv = priv; @@ -205,17 +211,35 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_query_functions(r300); - /* r300_init_surface_functions(r300); */ + r300_init_transfer_functions(r300); r300_init_state_functions(r300); r300->invariant_state.dirty = TRUE; - r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); - r300->dirty_state = R300_NEW_KITCHEN_SINK; + rws->set_flush_cb(r300->rws, r300_flush_cb, r300); r300->dirty_hw++; r300->blitter = util_blitter_create(&r300->context); + r300->upload_ib = u_upload_create(screen, + 32 * 1024, 16, + PIPE_BUFFER_USAGE_INDEX); + + if (r300->upload_ib == NULL) + goto no_upload_ib; + + r300->upload_vb = u_upload_create(screen, + 128 * 1024, 16, + PIPE_BUFFER_USAGE_VERTEX); + if (r300->upload_vb == NULL) + goto no_upload_vb; + return &r300->context; + + no_upload_ib: + u_upload_destroy(r300->upload_ib); + no_upload_vb: + FREE(r300); + return NULL; } diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 0d1518a05bc..0c8fb6860eb 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -32,6 +32,7 @@ #include "r300_screen.h" +struct u_upload_mgr; struct r300_context; struct r300_fragment_shader; @@ -124,19 +125,21 @@ struct r300_texture_format_state { uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */ }; +#define R300_MAX_TEXTURE_LEVELS 13 + struct r300_texture_fb_state { /* Colorbuffer. */ - uint32_t colorpitch[PIPE_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/ + uint32_t colorpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/ uint32_t us_out_fmt; /* R300_US_OUT_FMT[0-3] */ /* Zbuffer. */ - uint32_t depthpitch[PIPE_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */ + uint32_t depthpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */ uint32_t zb_format; /* R300_ZB_FORMAT */ }; struct r300_textures_state { /* Textures. */ - struct r300_texture *textures[8]; + struct pipe_sampler_view *fragment_sampler_views[8]; int texture_count; /* Sampler states. */ struct r300_sampler_state *sampler_states[8]; @@ -236,16 +239,16 @@ struct r300_texture { struct pipe_texture tex; /* Offsets into the buffer. */ - unsigned offset[PIPE_MAX_TEXTURE_LEVELS]; + unsigned offset[R300_MAX_TEXTURE_LEVELS]; /* A pitch for each mip-level */ - unsigned pitch[PIPE_MAX_TEXTURE_LEVELS]; + unsigned pitch[R300_MAX_TEXTURE_LEVELS]; /* Size of one zslice or face based on the texture target */ - unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS]; + unsigned layer_size[R300_MAX_TEXTURE_LEVELS]; /* Whether the mipmap level is macrotiled. */ - enum r300_buffer_tiling mip_macrotile[PIPE_MAX_TEXTURE_LEVELS]; + enum r300_buffer_tiling mip_macrotile[R300_MAX_TEXTURE_LEVELS]; /** * If non-zero, override the natural texture layout with @@ -266,7 +269,7 @@ struct r300_texture { boolean is_npot; /* Pipe buffer backing this texture. */ - struct pipe_buffer* buffer; + struct r300_winsys_buffer *buffer; /* Registers carrying texture format data. */ struct r300_texture_format_state state; @@ -276,6 +279,23 @@ struct r300_texture { enum r300_buffer_tiling microtile, macrotile; }; +struct r300_vertex_info { + /* Parent class */ + struct vertex_info vinfo; + + /* R300_VAP_PROG_STREAK_CNTL_[0-7] */ + uint32_t vap_prog_stream_cntl[8]; + /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */ + uint32_t vap_prog_stream_cntl_ext[8]; +}; + +struct r300_vertex_element_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; + + struct r300_vertex_stream_state vertex_stream; +}; + extern struct pipe_viewport_state r300_viewport_identity; struct r300_context { @@ -283,7 +303,7 @@ struct r300_context { struct pipe_context context; /* The interface to the windowing system, etc. */ - struct radeon_winsys* winsys; + struct r300_winsys_screen *rws; /* Draw module. Used mostly for SW TCL. */ struct draw_context* draw; /* Accelerated blit support. */ @@ -348,8 +368,8 @@ struct r300_context { int vertex_buffer_count; int vertex_buffer_max_index; /* Vertex elements for Gallium. */ - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; - int vertex_element_count; + struct r300_vertex_element_state *velems; + bool any_user_vbs; /* Vertex info for Draw. */ struct vertex_info vertex_info; @@ -368,6 +388,11 @@ struct r300_context { boolean polygon_offset_enabled; /* Z buffer bit depth. */ uint32_t zbuffer_bpp; + /* Whether scissor is enabled. */ + boolean scissor_enabled; + /* upload managers */ + struct u_upload_mgr *upload_vb; + struct u_upload_mgr *upload_ib; }; /* Convenience cast wrapper. */ @@ -384,6 +409,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_state_functions(struct r300_context* r300); void r300_init_surface_functions(struct r300_context* r300); +void r300_init_tex_functions( struct pipe_context *pipe ); static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags) { diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 151f72b0fe4..ad07efbffdb 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -51,7 +51,7 @@ #define CS_LOCALS(context) \ struct r300_context* const cs_context_copy = (context); \ - struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \ + struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \ int cs_count = 0; (void) cs_count; #define CHECK_CS(size) \ @@ -105,22 +105,34 @@ cs_count--; \ } while (0) -#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \ +#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \ DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, offset %d, " \ "domains (%d, %d, %d)\n", \ bo, offset, rd, wd, flags); \ assert(bo); \ cs_winsys->write_cs_dword(cs_winsys, offset); \ - cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ + r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ cs_count -= 3; \ } while (0) -#define OUT_CS_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ + +#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \ + DBG(cs_context_copy, DBG_CS, "r300: writing relocation for texture %p, offset %d, " \ + "domains (%d, %d, %d)\n", \ + tex, offset, rd, wd, flags); \ + assert(tex); \ + cs_winsys->write_cs_dword(cs_winsys, offset); \ + r300_texture_write_reloc(cs_winsys, tex, rd, wd, flags); \ + cs_count -= 3; \ +} while (0) + + +#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, " \ "domains (%d, %d, %d)\n", \ bo, rd, wd, flags); \ assert(bo); \ - cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ + r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ cs_count -= 2; \ } while (0) diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index b881730848a..d6177577c8d 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -37,6 +37,7 @@ static struct debug_option debug_options[] = { { "draw", DBG_DRAW, "Draw and emit" }, { "tex", DBG_TEX, "Textures" }, { "fall", DBG_FALL, "Fallbacks" }, + { "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking purposes only!)" }, { "all", ~0, "Convenience option that enables all debug flags" }, diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index addb28bded3..3ad0e561bc1 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -32,6 +32,8 @@ #include "r300_emit.h" #include "r300_fs.h" #include "r300_screen.h" +#include "r300_screen_buffer.h" +#include "r300_state_inlines.h" #include "r300_vs.h" void r300_emit_blend_state(struct r300_context* r300, @@ -163,7 +165,7 @@ static const float * get_shader_constant( /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ case RC_STATE_R300_TEXRECT_FACTOR: - tex = &texstate->textures[constant->u.State[1]]->tex; + tex = texstate->fragment_sampler_views[constant->u.State[1]]->texture; vec[0] = 1.0 / tex->width0; vec[1] = 1.0 / tex->height0; break; @@ -415,10 +417,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) assert(tex && tex->buffer && "cbuf is marked, but NULL!"); OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); - OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); - OUT_CS_RELOC(tex->buffer, tex->fb_state.colorpitch[surf->level], + OUT_CS_TEX_RELOC(tex, tex->fb_state.colorpitch[surf->level], 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), tex->fb_state.us_out_fmt); @@ -434,12 +436,12 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_ZB_FORMAT, tex->fb_state.zb_format); OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(tex->buffer, tex->fb_state.depthpitch[surf->level], + OUT_CS_TEX_RELOC(tex, tex->fb_state.depthpitch[surf->level], 0, RADEON_GEM_DOMAIN_VRAM, 0); } @@ -448,7 +450,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) END_CS; } -static void r300_emit_query_start(struct r300_context *r300) +void r300_emit_query_start(struct r300_context *r300) { struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps; struct r300_query *query = r300->query_current; @@ -491,13 +493,13 @@ static void r300_emit_query_finish(struct r300_context *r300, /* pipe 3 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), 0, RADEON_GEM_DOMAIN_GTT, 0); case 3: /* pipe 2 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), 0, RADEON_GEM_DOMAIN_GTT, 0); case 2: /* pipe 1 only */ @@ -505,13 +507,13 @@ static void r300_emit_query_finish(struct r300_context *r300, OUT_CS_REG(R300_SU_REG_DEST, 1 << (caps->high_second_pipe ? 3 : 1)); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), 0, RADEON_GEM_DOMAIN_GTT, 0); case 1: /* pipe 0 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), 0, RADEON_GEM_DOMAIN_GTT, 0); break; default: @@ -533,7 +535,7 @@ static void rv530_emit_query_single(struct r300_context *r300, BEGIN_CS(8); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -546,10 +548,10 @@ static void rv530_emit_query_double(struct r300_context *r300, BEGIN_CS(14); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -675,7 +677,7 @@ void r300_emit_scissor_state(struct r300_context* r300, maxx = fb->width; maxy = fb->height; - if (((struct r300_rs_state*)r300->rs_state.state)->rs.scissor) { + if (r300->scissor_enabled) { minx = MAX2(minx, scissor->minx); miny = MAX2(miny, scissor->miny); maxx = MIN2(maxx, scissor->maxx); @@ -747,8 +749,9 @@ void r300_emit_textures_state(struct r300_context *r300, OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]); OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_CS_RELOC(allstate->textures[i]->buffer, texstate->tile_config, - RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); + OUT_CS_TEX_RELOC((struct r300_texture *)allstate->fragment_sampler_views[i]->texture, + texstate->tile_config, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); } } END_CS; @@ -757,9 +760,9 @@ void r300_emit_textures_state(struct r300_context *r300, void r300_emit_aos(struct r300_context* r300, unsigned offset) { struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_vertex_element *velem = r300->velems->velem; int i; - unsigned size1, size2, aos_count = r300->vertex_element_count; + unsigned size1, size2, aos_count = r300->velems->count; unsigned packet_size = (aos_count * 3 + 1) / 2; CS_LOCALS(r300); @@ -788,12 +791,36 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) } for (i = 0; i < aos_count; i++) { - OUT_CS_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer, - RADEON_GEM_DOMAIN_GTT, 0, 0); + OUT_CS_BUF_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer, + RADEON_GEM_DOMAIN_GTT, 0, 0); } END_CS; } +void r300_emit_vertex_buffer(struct r300_context* r300) +{ + CS_LOCALS(r300); + + DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, " + "vertex size %d\n", r300->vbo, + r300->vertex_info.size); + /* Set the pointer to our vertex buffer. The emitted values are this: + * PACKET3 [3D_LOAD_VBPNTR] + * COUNT [1] + * FORMAT [size | stride << 8] + * OFFSET [offset into BO] + * VBPNTR [relocated BO] + */ + BEGIN_CS(7); + OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3); + OUT_CS(1); + OUT_CS(r300->vertex_info.size | + (r300->vertex_info.size << 8)); + OUT_CS(r300->vbo_offset); + OUT_CS_BUF_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); + END_CS; +} + void r300_emit_vertex_stream_state(struct r300_context* r300, unsigned size, void* state) { @@ -868,7 +895,7 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) CS_LOCALS(r300); if (!r300screen->caps->has_tcl) { - debug_printf("r300: Implementation error: emit_vertex_shader called," + debug_printf("r300: Implementation error: emit_vs_state called," " but has_tcl is FALSE!\n"); return; } @@ -907,7 +934,7 @@ void r300_emit_vs_constant_buffer(struct r300_context* r300, CS_LOCALS(r300); if (!r300screen->caps->has_tcl) { - debug_printf("r300: Implementation error: emit_vertex_shader called," + debug_printf("r300: Implementation error: emit_vs_constant_buffer called," " but has_tcl is FALSE!\n"); return; } @@ -980,21 +1007,27 @@ void r300_emit_buffer_validate(struct r300_context *r300, (struct r300_textures_state*)r300->textures_state.state; struct r300_texture* tex; struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_vertex_element *velem = r300->velems->velem; struct pipe_buffer *pbuf; unsigned i; boolean invalid = FALSE; + /* upload buffers first */ + if (r300->any_user_vbs) { + r300_upload_user_buffers(r300); + r300->any_user_vbs = false; + } + /* Clean out BOs. */ - r300->winsys->reset_bos(r300->winsys); + r300->rws->reset_bos(r300->rws); validate: /* Color buffers... */ for (i = 0; i < fb->nr_cbufs; i++) { tex = (struct r300_texture*)fb->cbufs[i]->texture; assert(tex && tex->buffer && "cbuf is marked, but NULL!"); - if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM)) { + if (!r300_add_texture(r300->rws, tex, + 0, RADEON_GEM_DOMAIN_VRAM)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } @@ -1003,61 +1036,60 @@ validate: if (fb->zsbuf) { tex = (struct r300_texture*)fb->zsbuf->texture; assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); - if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM)) { + if (!r300_add_texture(r300->rws, tex, + 0, RADEON_GEM_DOMAIN_VRAM)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } /* ...textures... */ for (i = 0; i < texstate->count; i++) { - tex = texstate->textures[i]; + tex = (struct r300_texture*)texstate->fragment_sampler_views[i]->texture; if (!tex || !texstate->sampler_states[i]) continue; - if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, - RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { + if (!r300_add_texture(r300->rws, tex, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } /* ...occlusion query buffer... */ if (r300->dirty_state & R300_NEW_QUERY) { - if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, - 0, RADEON_GEM_DOMAIN_GTT)) { + if (!r300_add_buffer(r300->rws, r300->oqbo, + 0, RADEON_GEM_DOMAIN_GTT)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } /* ...vertex buffer for SWTCL path... */ if (r300->vbo) { - if (!r300->winsys->add_buffer(r300->winsys, r300->vbo, - RADEON_GEM_DOMAIN_GTT, 0)) { + if (!r300_add_buffer(r300->rws, r300->vbo, + RADEON_GEM_DOMAIN_GTT, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } /* ...vertex buffers for HWTCL path... */ if (do_validate_vertex_buffers) { - for (i = 0; i < r300->vertex_element_count; i++) { + for (i = 0; i < r300->velems->count; i++) { pbuf = vbuf[velem[i].vertex_buffer_index].buffer; - if (!r300->winsys->add_buffer(r300->winsys, pbuf, - RADEON_GEM_DOMAIN_GTT, 0)) { - r300->context.flush(&r300->context, 0, NULL); + if (!r300_add_buffer(r300->rws, pbuf, + RADEON_GEM_DOMAIN_GTT, 0)) { + r300->context.flush(&r300->context, 0, NULL); goto validate; } } } /* ...and index buffer for HWTCL path. */ if (index_buffer) { - if (!r300->winsys->add_buffer(r300->winsys, index_buffer, - RADEON_GEM_DOMAIN_GTT, 0)) { + if (!r300_add_buffer(r300->rws, index_buffer, + RADEON_GEM_DOMAIN_GTT, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } - - if (!r300->winsys->validate(r300->winsys)) { + if (!r300->rws->validate(r300->rws)) { r300->context.flush(&r300->context, 0, NULL); if (invalid) { /* Well, hell. */ @@ -1135,8 +1167,10 @@ void r300_emit_dirty_state(struct r300_context* r300) assert(r300->dirty_state == 0); */ - /* Finally, emit the VBO. */ - /* r300_emit_vertex_buffer(r300); */ + /* Emit the VBO for SWTCL. */ + if (!r300screen->caps->has_tcl) { + r300_emit_vertex_buffer(r300); + } r300->dirty_hw++; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 449e640a884..7db2fc6a1a1 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -57,8 +57,7 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300, void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state); -void r300_emit_query_begin(struct r300_context* r300, - struct r300_query* query); +void r300_emit_query_start(struct r300_context* r300); void r300_emit_query_end(struct r300_context* r300); diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index e37d3092703..70de152713d 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -61,6 +61,12 @@ static void r300_flush(struct pipe_context* pipe, atom->dirty = TRUE; } } + + /* Unmark HWTCL state for SWTCL. */ + if (!r300_screen(pipe->screen)->caps->has_tcl) { + r300->vs_state.dirty = FALSE; + r300->dirty_state &= ~R300_NEW_VERTEX_SHADER_CONSTANTS; + } } /* reset flushed query */ diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 3c2625269b8..9e71e61c303 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -207,6 +207,7 @@ static void r300_translate_fragment_shader( DBG(r300, DBG_FP, "r300: Error compiling fragment program: %s\n", compiler.Base.ErrorMsg); assert(0); + abort(); } /* And, finally... */ diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index c67cc868713..1c2b2528877 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -1500,6 +1500,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_ANISO_THRESHOLD_MASK (7<<17) # define R500_MACRO_SWITCH (1<<22) +# define R500_TX_MAX_ANISO(x) ((x) << 23) +# define R500_TX_MAX_ANISO_MASK (63 << 23) +# define R500_TX_ANISO_HIGH_QUALITY (1 << 30) + # define R500_BORDER_FIX (1<<31) #define R300_TX_FORMAT0_0 0x4480 diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 6c891029a56..47100c83b0b 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -30,10 +30,12 @@ #include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_upload_mgr.h" #include "util/u_prim.h" #include "r300_cs.h" #include "r300_context.h" +#include "r300_screen_buffer.h" #include "r300_emit.h" #include "r300_reg.h" #include "r300_render.h" @@ -123,7 +125,7 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, static boolean r300_reserve_cs_space(struct r300_context *r300, unsigned dwords) { - if (!r300->winsys->check_cs(r300->winsys, dwords)) { + if (!r300->rws->check_cs(r300->rws, dwords)) { r300->context.flush(&r300->context, 0, NULL); return TRUE; } @@ -131,9 +133,37 @@ static boolean r300_reserve_cs_space(struct r300_context *r300, } static boolean immd_is_good_idea(struct r300_context *r300, - unsigned count) + unsigned count) { - return count <= 4; + struct pipe_vertex_element* velem; + struct pipe_vertex_buffer* vbuf; + boolean checked[PIPE_MAX_ATTRIBS] = {0}; + unsigned vertex_element_count = r300->velems->count; + unsigned i, vbi; + + if (count > 4) { + return FALSE; + } + + /* We shouldn't map buffers referenced by CS, busy buffers, + * and ones placed in VRAM. */ + /* XXX Check for VRAM buffers. */ + for (i = 0; i < vertex_element_count; i++) { + velem = &r300->velems->velem[i]; + vbi = velem->vertex_buffer_index; + + if (!checked[vbi]) { + vbuf = &r300->vertex_buffer[vbi]; + + if (r300_buffer_is_referenced(r300, + vbuf->buffer)) { + /* It's a very bad idea to map it... */ + return FALSE; + } + checked[vbi] = TRUE; + } + } + return TRUE; } static void r300_emit_draw_arrays_immediate(struct r300_context *r300, @@ -143,7 +173,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; - unsigned vertex_element_count = r300->vertex_element_count; + unsigned vertex_element_count = r300->velems->count; unsigned i, v, vbi, dw, elem_offset, dwords; /* Size of the vertex, in dwords. */ @@ -166,7 +196,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { - velem = &r300->vertex_element[i]; + velem = &r300->velems->velem[i]; offset[i] = velem->src_offset / 4; size[i] = util_format_get_blocksize(velem->src_format) / 4; vertex_size += size[i]; @@ -183,18 +213,19 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, } } - dwords = 10 + count * vertex_size; + dwords = 9 + count * vertex_size; r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); - r300_emit_buffer_validate(r300, FALSE, 0); + r300_emit_buffer_validate(r300, FALSE, NULL); r300_emit_dirty_state(r300); BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(count - 1); + OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); @@ -202,7 +233,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Emit vertices. */ for (v = 0; v < count; v++) { for (i = 0; i < vertex_element_count; i++) { - velem = &r300->vertex_element[i]; + velem = &r300->velems->velem[i]; vbi = velem->vertex_buffer_index; elem_offset = offset[i] + stride[vbi] * (v + start); @@ -215,7 +246,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Unmap buffers. */ for (i = 0; i < vertex_element_count; i++) { - vbi = r300->vertex_element[i].vertex_buffer_index; + vbi = r300->velems->velem[i].vertex_buffer_index; if (map[vbi]) { vbuf = &r300->vertex_buffer[vbi]; @@ -238,15 +269,16 @@ static void r300_emit_draw_arrays(struct r300_context *r300, if (alt_num_verts) { assert(count < (1 << 24)); - BEGIN_CS(10); + BEGIN_CS(9); OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } else { - BEGIN_CS(8); + BEGIN_CS(7); } OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(count - 1); + OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300_translate_primitive(mode) | @@ -272,24 +304,25 @@ static void r300_emit_draw_elements(struct r300_context *r300, #endif CS_LOCALS(r300); - assert((start * indexSize) % 4 == 0); + assert((start * indexSize) % 4 == 0); assert(count < (1 << 24)); + maxIndex = MIN3(maxIndex, r300->vertex_buffer_max_index, count - minIndex); + DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); - maxIndex = MIN2(maxIndex, ((1 << 24) - 1)); - if (alt_num_verts) { - BEGIN_CS(16); + BEGIN_CS(15); OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } else { - BEGIN_CS(14); + BEGIN_CS(13); } OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, minIndex); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(maxIndex); + OUT_CS(minIndex); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); if (indexSize == 4) { count_dwords = count; @@ -313,8 +346,8 @@ static void r300_emit_draw_elements(struct r300_context *r300, OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | (0 << R300_INDX_BUFFER_SKIP_SHIFT)); OUT_CS(offset_dwords << 2); - OUT_CS_RELOC(indexBuffer, count_dwords, - RADEON_GEM_DOMAIN_GTT, 0, 0); + OUT_CS_BUF_RELOC(indexBuffer, count_dwords, + RADEON_GEM_DOMAIN_GTT, 0, 0); END_CS; } @@ -381,12 +414,16 @@ void r300_draw_range_elements(struct pipe_context* pipe, r300_update_derived_state(r300); + r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count); + /* 128 dwords for emit_aos and emit_draw_elements */ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); r300_emit_buffer_validate(r300, TRUE, indexBuffer); r300_emit_dirty_state(r300); r300_emit_aos(r300, 0); + u_upload_flush(r300->upload_vb); + u_upload_flush(r300->upload_ib); if (alt_num_verts || count <= 65535) { r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); @@ -409,7 +446,7 @@ void r300_draw_range_elements(struct pipe_context* pipe, } if (indexBuffer != orgIndexBuffer) { - pipe->screen->buffer_destroy(indexBuffer); + pipe_buffer_reference( &indexBuffer, NULL ); } } @@ -450,7 +487,7 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, /* Make sure there are at least 128 spare dwords in the command buffer. * (most of it being consumed by emit_aos) */ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); - r300_emit_buffer_validate(r300, TRUE, 0); + r300_emit_buffer_validate(r300, TRUE, NULL); r300_emit_dirty_state(r300); if (alt_num_verts || count <= 65535) { @@ -468,11 +505,12 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, /* Again, we emit both AOS and draw_arrays so there should be * at least 128 spare dwords. */ if (count && r300_reserve_cs_space(r300, 128)) { - r300_emit_buffer_validate(r300, TRUE, 0); + r300_emit_buffer_validate(r300, TRUE, NULL); r300_emit_dirty_state(r300); } } while (count); } + u_upload_flush(r300->upload_vb); } } @@ -688,6 +726,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render, CS_LOCALS(r300); r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2); + r300_emit_buffer_validate(r300, FALSE, NULL); r300_emit_dirty_state(r300); DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); @@ -711,6 +750,7 @@ static void r300_render_draw(struct vbuf_render* render, CS_LOCALS(r300); r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); + r300_emit_buffer_validate(r300, FALSE, NULL); r300_emit_dirty_state(r300); BEGIN_CS(dwords); diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index d397a8eb2b4..3e31688f8e8 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,17 +21,15 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_memory.h" -#include "util/u_simple_screen.h" #include "r300_context.h" -#include "r300_screen.h" #include "r300_texture.h" #include "radeon_winsys.h" -#include "r300_winsys.h" + +#include "r300_screen_buffer.h" /* Return the identifier behind whom the brave coders responsible for this * amalgamation of code, sweat, and duct tape, routinely obscure their names. @@ -231,14 +230,16 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, /* Check colorbuffer format support. */ if ((usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) && + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) && /* 2101010 cannot be rendered to on non-r5xx. */ (is_r500 || !is_color2101010) && r300_is_colorbuffer_format_supported(format)) { retval |= usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED); } /* Check depth-stencil format support. */ @@ -250,82 +251,22 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, return retval == usage; } -static struct pipe_transfer* -r300_get_tex_transfer(struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, unsigned x, unsigned y, - unsigned w, unsigned h) -{ - struct r300_texture *tex = (struct r300_texture *)texture; - struct r300_transfer *trans; - struct r300_screen *rscreen = r300_screen(screen); - unsigned offset; - - offset = r300_texture_get_offset(tex, level, zslice, face); /* in bytes */ - - trans = CALLOC_STRUCT(r300_transfer); - if (trans) { - pipe_texture_reference(&trans->transfer.texture, texture); - trans->transfer.x = x; - trans->transfer.y = y; - trans->transfer.width = w; - trans->transfer.height = h; - trans->transfer.stride = r300_texture_get_stride(rscreen, tex, level); - trans->transfer.usage = usage; - trans->transfer.zslice = zslice; - trans->transfer.face = face; - - trans->offset = offset; - } - return &trans->transfer; -} - -static void -r300_tex_transfer_destroy(struct pipe_transfer *trans) -{ - pipe_texture_reference(&trans->texture, NULL); - FREE(trans); -} - -static void* r300_transfer_map(struct pipe_screen* screen, - struct pipe_transfer* transfer) -{ - struct r300_texture* tex = (struct r300_texture*)transfer->texture; - char* map; - enum pipe_format format = tex->tex.format; - - map = pipe_buffer_map(screen, tex->buffer, - pipe_transfer_buffer_flags(transfer)); - - if (!map) { - return NULL; - } - - return map + r300_transfer(transfer)->offset + - transfer->y / util_format_get_blockheight(format) * transfer->stride + - transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); -} - -static void r300_transfer_unmap(struct pipe_screen* screen, - struct pipe_transfer* transfer) -{ - struct r300_texture* tex = (struct r300_texture*)transfer->texture; - pipe_buffer_unmap(screen, tex->buffer); -} - static void r300_destroy_screen(struct pipe_screen* pscreen) { struct r300_screen* r300screen = r300_screen(pscreen); + struct r300_winsys_screen *rws = r300_winsys_screen(pscreen); + + if (rws) + rws->destroy(rws); FREE(r300screen->caps); FREE(r300screen); } -struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) +struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws) { - struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen); - struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities); + struct r300_screen *r300screen = CALLOC_STRUCT(r300_screen); + struct r300_capabilities *caps = CALLOC_STRUCT(r300_capabilities); if (!r300screen || !caps) { FREE(r300screen); @@ -333,16 +274,16 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) return NULL; } - caps->pci_id = radeon_winsys->pci_id; - caps->num_frag_pipes = radeon_winsys->gb_pipes; - caps->num_z_pipes = radeon_winsys->z_pipes; + caps->pci_id = rws->get_value(rws, R300_VID_PCI_ID); + caps->num_frag_pipes = rws->get_value(rws, R300_VID_GB_PIPES); + caps->num_z_pipes = rws->get_value(rws, R300_VID_Z_PIPES); r300_init_debug(r300screen); r300_parse_chipset(caps); r300screen->caps = caps; - r300screen->radeon_winsys = radeon_winsys; - r300screen->screen.winsys = (struct pipe_winsys*)radeon_winsys; + r300screen->rws = rws; + r300screen->screen.winsys = (struct pipe_winsys*)rws; r300screen->screen.destroy = r300_destroy_screen; r300screen->screen.get_name = r300_get_name; r300screen->screen.get_vendor = r300_get_vendor; @@ -350,13 +291,15 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) r300screen->screen.get_paramf = r300_get_paramf; r300screen->screen.is_format_supported = r300_is_format_supported; r300screen->screen.context_create = r300_create_context; - r300screen->screen.get_tex_transfer = r300_get_tex_transfer; - r300screen->screen.tex_transfer_destroy = r300_tex_transfer_destroy; - r300screen->screen.transfer_map = r300_transfer_map; - r300screen->screen.transfer_unmap = r300_transfer_unmap; r300_init_screen_texture_functions(&r300screen->screen); - u_simple_screen_init(&r300screen->screen); + r300_screen_init_buffer_functions(r300screen); return &r300screen->screen; } + +struct r300_winsys_screen * +r300_winsys_screen(struct pipe_screen *screen) +{ + return r300_screen(screen)->rws; +} diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 502fbfa5a24..1ccc0bfb7a5 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,13 +28,15 @@ #include "r300_chipset.h" +#define R300_TEXTURE_USAGE_TRANSFER PIPE_TEXTURE_USAGE_CUSTOM + struct radeon_winsys; struct r300_screen { /* Parent class */ struct pipe_screen screen; - struct radeon_winsys* radeon_winsys; + struct r300_winsys_screen *rws; /* Chipset capabilities */ struct r300_capabilities* caps; @@ -42,26 +45,12 @@ struct r300_screen { unsigned debug; }; -struct r300_transfer { - /* Parent class */ - struct pipe_transfer transfer; - - /* Offset from start of buffer. */ - unsigned offset; -}; /* Convenience cast wrapper. */ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { return (struct r300_screen*)screen; } -/* Convenience cast wrapper. */ -static INLINE struct r300_transfer* -r300_transfer(struct pipe_transfer* transfer) -{ - return (struct r300_transfer*)transfer; -} - /* Debug functionality. */ /** @@ -81,6 +70,7 @@ r300_transfer(struct pipe_transfer* transfer) #define DBG_DRAW 0x0000010 #define DBG_TEX 0x0000020 #define DBG_FALL 0x0000040 +#define DBG_ANISOHQ 0x0000080 /*@}*/ static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags) diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c new file mode 100644 index 00000000000..b97d0d76a4a --- /dev/null +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -0,0 +1,314 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * 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 AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + */ +#include <stdio.h> + +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_upload_mgr.h" +#include "util/u_math.h" + +#include "r300_screen_buffer.h" + +#include "r300_winsys.h" + +boolean r300_buffer_is_referenced(struct r300_context *r300, + struct pipe_buffer *buf) +{ + struct r300_buffer *rbuf = r300_buffer(buf); + if (r300_buffer_is_user_buffer(buf)) + return FALSE; + + return r300->rws->is_buffer_referenced(r300->rws, rbuf->buf); + +} +int r300_upload_index_buffer(struct r300_context *r300, + struct pipe_buffer **index_buffer, + unsigned index_size, + unsigned start, + unsigned count) +{ + struct pipe_buffer *upload_buffer = NULL; + unsigned index_offset = start * index_size; + int ret = 0; + + if (r300_buffer_is_user_buffer(*index_buffer)) { + ret = u_upload_buffer(r300->upload_ib, + index_offset, + count * index_size, + *index_buffer, + &index_offset, + &upload_buffer); + if (ret) { + goto done; + } + *index_buffer = upload_buffer; + } + done: + // if (upload_buffer) + // pipe_buffer_reference(&upload_buffer, NULL); + return ret; +} + +int r300_upload_user_buffers(struct r300_context *r300) +{ + enum pipe_error ret = PIPE_OK; + int i, nr; + + nr = r300->vertex_buffer_count; + + for (i = 0; i < nr; i++) { + + if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) { + struct pipe_buffer *upload_buffer = NULL; + unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/ + unsigned size = r300->vertex_buffer[i].buffer->size; + unsigned upload_offset; + ret = u_upload_buffer(r300->upload_vb, + offset, size, + r300->vertex_buffer[i].buffer, + &upload_offset, &upload_buffer); + if (ret) + return ret; + + pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); + r300->vertex_buffer[i].buffer = upload_buffer; + r300->vertex_buffer[i].buffer_offset = upload_offset; + } + } + return ret; +} + +static struct r300_winsys_buffer * +r300_winsys_buffer_create(struct r300_screen *r300screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct r300_winsys_screen *rws = r300screen->rws; + struct r300_winsys_buffer *buf; + + buf = rws->buffer_create(rws, alignment, usage, size); + return buf; +} + +static void r300_winsys_buffer_destroy(struct r300_screen *r300screen, + struct r300_buffer *rbuf) +{ + struct r300_winsys_screen *rws = r300screen->rws; + + if (rbuf->buf) { + rws->buffer_reference(rws, &rbuf->buf, NULL); + rbuf->buf = NULL; + } +} + +static struct pipe_buffer *r300_buffer_create(struct pipe_screen *screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_buffer *rbuf; + + rbuf = CALLOC_STRUCT(r300_buffer); + if (!rbuf) + goto error1; + + rbuf->magic = R300_BUFFER_MAGIC; + + pipe_reference_init(&rbuf->base.reference, 1); + rbuf->base.screen = screen; + rbuf->base.alignment = alignment; + rbuf->base.usage = usage; + rbuf->base.size = size; + + rbuf->buf = r300_winsys_buffer_create(r300screen, + alignment, + usage, + size); + + if (!rbuf->buf) + goto error2; + + return &rbuf->base; +error2: + FREE(rbuf); +error1: + return NULL; +} + + +static struct pipe_buffer *r300_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes) +{ + struct r300_buffer *rbuf; + + rbuf = CALLOC_STRUCT(r300_buffer); + if (!rbuf) + goto no_rbuf; + + rbuf->magic = R300_BUFFER_MAGIC; + + pipe_reference_init(&rbuf->base.reference, 1); + rbuf->base.screen = screen; + rbuf->base.alignment = 1; + rbuf->base.usage = 0; + rbuf->base.size = bytes; + + rbuf->user_buffer = ptr; + return &rbuf->base; + +no_rbuf: + return NULL; +} + +static void r300_buffer_destroy(struct pipe_buffer *buf) +{ + struct r300_screen *r300screen = r300_screen(buf->screen); + struct r300_buffer *rbuf = r300_buffer(buf); + + r300_winsys_buffer_destroy(r300screen, rbuf); + FREE(rbuf); +} + +static void * +r300_buffer_map_range(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned offset, unsigned length, + unsigned usage ) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_winsys_screen *rws = r300screen->rws; + struct r300_buffer *rbuf = r300_buffer(buf); + void *map; + int flush = 0; + int i; + + if (rbuf->user_buffer) + return rbuf->user_buffer; + + if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT) + goto just_map; + + /* check if the mapping is to a range we already flushed */ + if (usage & PIPE_BUFFER_USAGE_DISCARD) { + for (i = 0; i < rbuf->num_ranges; i++) { + + if ((offset >= rbuf->ranges[i].start) && + (offset < rbuf->ranges[i].end)) + flush = 1; + + if (flush) { + /* unreference this hw buffer and allocate a new one */ + rws->buffer_reference(rws, &rbuf->buf, NULL); + + rbuf->num_ranges = 0; + rbuf->map = NULL; + rbuf->buf = r300_winsys_buffer_create(r300screen, + rbuf->base.alignment, + rbuf->base.usage, + rbuf->base.size); + break; + } + } + } +just_map: + map = rws->buffer_map(rws, rbuf->buf, usage | R300_USAGE_FLAG_DONT_SYNC); + + return map; +} + +static void +r300_buffer_flush_mapped_range( struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned offset, + unsigned length ) +{ + struct r300_buffer *rbuf = r300_buffer(buf); + int i; + + if (rbuf->user_buffer) + return; + + if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT) + return; + + /* mark the range as used */ + for(i = 0; i < rbuf->num_ranges; ++i) { + if(offset <= rbuf->ranges[i].end && rbuf->ranges[i].start <= (offset+length)) { + rbuf->ranges[i].start = MIN2(rbuf->ranges[i].start, offset); + rbuf->ranges[i].end = MAX2(rbuf->ranges[i].end, (offset+length)); + return; + } + } + + rbuf->ranges[rbuf->num_ranges].start = offset; + rbuf->ranges[rbuf->num_ranges].end = offset+length; + rbuf->num_ranges++; +} + +static void * +r300_buffer_map(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned usage) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_winsys_screen *rws = r300screen->rws; + struct r300_buffer *rbuf = r300_buffer(buf); + void *map; + + if (rbuf->user_buffer) + return rbuf->user_buffer; + + map = rws->buffer_map(rws, rbuf->buf, usage); + + return map; +} + +static void +r300_buffer_unmap(struct pipe_screen *screen, + struct pipe_buffer *buf) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_winsys_screen *rws = r300screen->rws; + struct r300_buffer *rbuf = r300_buffer(buf); + + if (rbuf->buf) { + rws->buffer_unmap(rws, rbuf->buf); + } +} + +void r300_screen_init_buffer_functions(struct r300_screen *r300screen) +{ + r300screen->screen.buffer_create = r300_buffer_create; + r300screen->screen.user_buffer_create = r300_user_buffer_create; + r300screen->screen.buffer_map = r300_buffer_map; + r300screen->screen.buffer_map_range = r300_buffer_map_range; + r300screen->screen.buffer_flush_mapped_range = r300_buffer_flush_mapped_range; + r300screen->screen.buffer_unmap = r300_buffer_unmap; + r300screen->screen.buffer_destroy = r300_buffer_destroy; +} diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h new file mode 100644 index 00000000000..0cf349c25cd --- /dev/null +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -0,0 +1,99 @@ +#ifndef R300_SCREEN_BUFFER_H +#define R300_SCREEN_BUFFER_H +#include <stdio.h> +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" +#include "r300_screen.h" + +#include "r300_winsys.h" +#include "r300_context.h" + +#define R300_BUFFER_MAGIC 0xabcd1234 + +struct r300_buffer_range { + uint32_t start; + uint32_t end; +}; +#define R300_BUFFER_MAX_RANGES 32 + +struct r300_buffer +{ + struct pipe_buffer base; + + uint32_t magic; + + struct r300_winsys_buffer *buf; + + void *user_buffer; + struct r300_buffer_range ranges[R300_BUFFER_MAX_RANGES]; + unsigned num_ranges; + + void *map; +}; + +static INLINE struct r300_buffer * +r300_buffer(struct pipe_buffer *buffer) +{ + if (buffer) { + assert(((struct r300_buffer *)buffer)->magic == R300_BUFFER_MAGIC); + return (struct r300_buffer *)buffer; + } + return NULL; +} + +static INLINE boolean +r300_buffer_is_user_buffer(struct pipe_buffer *buffer) +{ + return r300_buffer(buffer)->user_buffer ? true : false; +} + +static INLINE boolean r300_add_buffer(struct r300_winsys_screen *rws, + struct pipe_buffer *buffer, + int rd, int wr) +{ + struct r300_buffer *buf = r300_buffer(buffer); + + if (!buf->buf) + return true; + + return rws->add_buffer(rws, buf->buf, rd, wr); +} + + +static INLINE boolean r300_add_texture(struct r300_winsys_screen *rws, + struct r300_texture *tex, + int rd, int wr) +{ + return rws->add_buffer(rws, tex->buffer, rd, wr); +} + +void r300_screen_init_buffer_functions(struct r300_screen *r300screen); + +static INLINE void r300_buffer_write_reloc(struct r300_winsys_screen *rws, + struct r300_buffer *buf, + uint32_t rd, uint32_t wd, uint32_t flags) +{ + if (!buf->buf) + return; + + rws->write_cs_reloc(rws, buf->buf, rd, wd, flags); +} + +static INLINE void r300_texture_write_reloc(struct r300_winsys_screen *rws, + struct r300_texture *texture, + uint32_t rd, uint32_t wd, uint32_t flags) +{ + rws->write_cs_reloc(rws, texture->buffer, rd, wd, flags); +} + +int r300_upload_user_buffers(struct r300_context *r300); + +int r300_upload_index_buffer(struct r300_context *r300, + struct pipe_buffer **index_buffer, + unsigned index_size, + unsigned start, + unsigned count); + +boolean r300_buffer_is_referenced(struct r300_context *r300, + struct pipe_buffer *buf); +#endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 1f6f99d3e52..d7d654dc315 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -34,6 +34,7 @@ #include "r300_context.h" #include "r300_reg.h" #include "r300_screen.h" +#include "r300_screen_buffer.h" #include "r300_state_inlines.h" #include "r300_fs.h" #include "r300_vs.h" @@ -525,7 +526,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex = (struct r300_texture*)old_state->cbufs[i]->texture; if (tex) { - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[0], tex->microtile != 0, tex->macrotile != 0); @@ -537,7 +538,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex = (struct r300_texture*)old_state->zsbuf->texture; if (tex) { - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[0], tex->microtile != 0, tex->macrotile != 0); @@ -549,7 +550,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex = (struct r300_texture*)new_state->cbufs[i]->texture; level = new_state->cbufs[i]->level; - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[level], tex->microtile != 0, tex->mip_macrotile[level] != 0); @@ -558,7 +559,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex = (struct r300_texture*)new_state->zsbuf->texture; level = new_state->zsbuf->level; - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[level], tex->microtile != 0, tex->mip_macrotile[level] != 0); @@ -571,6 +572,7 @@ static void { struct r300_context* r300 = r300_context(pipe); struct r300_screen* r300screen = r300_screen(pipe->screen); + struct pipe_framebuffer_state *old_state = r300->fb_state.state; unsigned max_width, max_height; uint32_t zbuffer_bpp = 0; @@ -595,23 +597,30 @@ static void return; } - if (r300->draw) { draw_flush(r300->draw); } - memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); + r300->fb_state.dirty = TRUE; - r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + - (state->zsbuf ? 10 : 0) + 8; + /* If nr_cbufs is changed from zero to non-zero or vice versa... */ + if (!!old_state->nr_cbufs != !!state->nr_cbufs) { + r300->blend_state.dirty = TRUE; + } + /* If zsbuf is set from NULL to non-NULL or vice versa.. */ + if (!!old_state->zsbuf != !!state->zsbuf) { + r300->dsa_state.dirty = TRUE; + } + if (!r300->scissor_enabled) { + r300->scissor_state.dirty = TRUE; + } r300_fb_update_tiling_flags(r300, r300->fb_state.state, state); - /* XXX wait what */ - r300->blend_state.dirty = TRUE; - r300->dsa_state.dirty = TRUE; - r300->fb_state.dirty = TRUE; - r300->scissor_state.dirty = TRUE; + memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); + + r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + + (state->zsbuf ? 10 : 0) + 8; /* Polygon offset depends on the zbuffer bit depth. */ if (state->zsbuf && r300->polygon_offset_enabled) { @@ -716,8 +725,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->vap_control_status = R300_VC_32BIT_SWAP; #endif - /* If bypassing TCL, or if no TCL engine is present, turn off the HW TCL. - * Else, enable HW TCL and force Draw's TCL off. */ + /* If no TCL engine is present, turn off the HW TCL. */ if (!r300screen->caps->has_tcl) { rs->vap_control_status |= R300_VAP_TCL_BYPASS; } @@ -807,6 +815,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; + boolean scissor_was_enabled = r300->scissor_enabled; if (r300->draw) { draw_flush(r300->draw); @@ -815,20 +824,17 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; + r300->scissor_enabled = rs->rs.scissor; } else { r300->polygon_offset_enabled = FALSE; + r300->scissor_enabled = FALSE; } UPDATE_STATE(state, r300->rs_state); r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0); - /* XXX Why is this still needed, dammit!? */ - r300->scissor_state.dirty = TRUE; - r300->viewport_state.dirty = TRUE; - - /* XXX Clean these up when we move to atom emits */ - if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { - r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + if (scissor_was_enabled != r300->scissor_enabled) { + r300->scissor_state.dirty = TRUE; } } @@ -844,6 +850,7 @@ static void* { struct r300_context* r300 = r300_context(pipe); struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state); + boolean is_r500 = r300_screen(pipe->screen)->caps->is_r500; int lod_bias; union util_color uc; @@ -859,6 +866,8 @@ static void* state->min_mip_filter, state->max_anisotropy > 0); + sampler->filter0 |= r300_anisotropy(state->max_anisotropy); + /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */ /* We must pass these to the merge function to clamp them properly. */ sampler->min_lod = MAX2((unsigned)state->min_lod, 0); @@ -868,7 +877,13 @@ static void* sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT; - sampler->filter1 |= r300_anisotropy(state->max_anisotropy); + /* This is very high quality anisotropic filtering for R5xx. + * It's good for benchmarking the performance of texturing but + * in practice we don't want to slow down the driver because it's + * a pretty good performance killer. Feel free to play with it. */ + if (DBG_ON(r300, DBG_ANISOHQ) && is_r500) { + sampler->filter1 |= r500_anisotropy(state->max_anisotropy); + } util_pack_color(state->border_color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); sampler->border_color = uc.ui; @@ -918,9 +933,9 @@ static void r300_delete_sampler_state(struct pipe_context* pipe, void* state) FREE(state); } -static void r300_set_sampler_textures(struct pipe_context* pipe, - unsigned count, - struct pipe_texture** texture) +static void r300_set_fragment_sampler_views(struct pipe_context* pipe, + unsigned count, + struct pipe_sampler_view** views) { struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = @@ -935,13 +950,17 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, } for (i = 0; i < count; i++) { - if (state->textures[i] != (struct r300_texture*)texture[i]) { - pipe_texture_reference((struct pipe_texture**)&state->textures[i], - texture[i]); + if (state->fragment_sampler_views[i] != views[i]) { + struct r300_texture *texture; + + pipe_sampler_view_reference(&state->fragment_sampler_views[i], + views[i]); dirty_tex = TRUE; + texture = (struct r300_texture *)views[i]->texture; + /* R300-specific - set the texrect factor in the fragment shader */ - if (!is_r500 && state->textures[i]->is_npot) { + if (!is_r500 && texture->is_npot) { /* XXX It would be nice to re-emit just 1 constant, * XXX not all of them */ r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -950,9 +969,9 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, } for (i = count; i < 8; i++) { - if (state->textures[i]) { - pipe_texture_reference((struct pipe_texture**)&state->textures[i], - NULL); + if (state->fragment_sampler_views[i]) { + pipe_sampler_view_reference(&state->fragment_sampler_views[i], + NULL); } } @@ -965,6 +984,33 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, } } +static struct pipe_sampler_view * +r300_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +r300_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + static void r300_set_scissor_state(struct pipe_context* pipe, const struct pipe_scissor_state* state) { @@ -973,7 +1019,9 @@ static void r300_set_scissor_state(struct pipe_context* pipe, memcpy(r300->scissor_state.state, state, sizeof(struct pipe_scissor_state)); - r300->scissor_state.dirty = TRUE; + if (r300->scissor_enabled) { + r300->scissor_state.dirty = TRUE; + } } static void r300_set_viewport_state(struct pipe_context* pipe, @@ -1024,34 +1072,45 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - unsigned i, max_index = ~0; + int i; + unsigned max_index = (1 << 24) - 1; + boolean any_user_buffer = false; - memcpy(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count); + if (count == r300->vertex_buffer_count && + memcmp(r300->vertex_buffer, buffers, count * sizeof(buffers[0])) == 0) + return; for (i = 0; i < count; i++) { + pipe_buffer_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer); + if (r300_buffer_is_user_buffer(buffers[i].buffer)) + any_user_buffer = true; max_index = MIN2(buffers[i].max_index, max_index); } + for ( ; i < r300->vertex_buffer_count; i++) + pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); + + memcpy(r300->vertex_buffer, buffers, + sizeof(struct pipe_vertex_buffer) * count); + r300->vertex_buffer_count = count; r300->vertex_buffer_max_index = max_index; + r300->any_user_vbs = any_user_buffer; if (r300->draw) { draw_flush(r300->draw); draw_set_vertex_buffers(r300->draw, count, buffers); - } else { - r300->vertex_stream_state.dirty = TRUE; } } static boolean r300_validate_aos(struct r300_context *r300) { struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_vertex_element *velem = r300->velems->velem; int i; /* Check if formats and strides are aligned to the size of DWORD. */ - for (i = 0; i < r300->vertex_element_count; i++) { + for (i = 0; i < r300->velems->count; i++) { if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || util_format_get_blocksize(velem[i].src_format) % 4 != 0) { return FALSE; @@ -1060,20 +1119,209 @@ static boolean r300_validate_aos(struct r300_context *r300) return TRUE; } -static void r300_set_vertex_elements(struct pipe_context* pipe, - unsigned count, - const struct pipe_vertex_element* elements) +static void r300_draw_emit_attrib(struct r300_context* r300, + enum attrib_emit emit, + enum interp_mode interp, + int index) { - struct r300_context* r300 = r300_context(pipe); + struct r300_vertex_shader* vs = r300->vs_state.state; + struct tgsi_shader_info* info = &vs->info; + int output; + + output = draw_find_shader_output(r300->draw, + info->output_semantic_name[index], + info->output_semantic_index[index]); + draw_emit_vertex_attr(&r300->vertex_info, emit, interp, output); +} + +static void r300_draw_emit_all_attribs(struct r300_context* r300) +{ + struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_shader_semantics* vs_outputs = &vs->outputs; + int i, gen_count; + + /* Position. */ + if (vs_outputs->pos != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->pos); + } else { + assert(0); + } + + /* Point size. */ + if (vs_outputs->psize != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_1F_PSIZE, INTERP_POS, + vs_outputs->psize); + } + + /* Colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (vs_outputs->color[i] != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_LINEAR, + vs_outputs->color[i]); + } + } + + /* XXX Back-face colors. */ + + /* Texture coordinates. */ + gen_count = 0; + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (vs_outputs->generic[i] != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->generic[i]); + gen_count++; + } + } + + /* Fog coordinates. */ + if (vs_outputs->fog != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->fog); + gen_count++; + } + + /* XXX magic */ + assert(gen_count <= 8); +} + +/* Update the PSC tables. */ +static void r300_vertex_psc(struct r300_vertex_element_state *velems) +{ + struct r300_vertex_stream_state *vstream = &velems->vertex_stream; + uint16_t type, swizzle; + enum pipe_format format; + unsigned i; - memcpy(r300->vertex_element, - elements, - sizeof(struct pipe_vertex_element) * count); - r300->vertex_element_count = count; + assert(velems->count <= 16); + + /* Vertex shaders have no semantics on their inputs, + * so PSC should just route stuff based on the vertex elements, + * and not on attrib information. */ + for (i = 0; i < velems->count; i++) { + format = velems->velem[i].src_format; + + type = r300_translate_vertex_data_type(format) | + (i << R300_DST_VEC_LOC_SHIFT); + swizzle = r300_translate_vertex_data_swizzle(format); + + if (i & 1) { + vstream->vap_prog_stream_cntl[i >> 1] |= type << 16; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; + } else { + vstream->vap_prog_stream_cntl[i >> 1] |= type; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; + } + } + + /* Set the last vector in the PSC. */ + if (i) { + i -= 1; + } + vstream->vap_prog_stream_cntl[i >> 1] |= + (R300_LAST_VEC << (i & 1 ? 16 : 0)); + + vstream->count = (i >> 1) + 1; +} + +/* Update the PSC tables for SW TCL, using Draw. */ +static void r300_swtcl_vertex_psc(struct r300_context *r300, + struct r300_vertex_element_state *velems) +{ + struct r300_vertex_stream_state *vstream = &velems->vertex_stream; + struct r300_vertex_shader* vs = r300->vs_state.state; + struct vertex_info* vinfo = &r300->vertex_info; + uint16_t type, swizzle; + enum pipe_format format; + unsigned i, attrib_count; + int* vs_output_tab = vs->stream_loc_notcl; + + /* For each Draw attribute, route it to the fragment shader according + * to the vs_output_tab. */ + attrib_count = vinfo->num_attribs; + DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count); + for (i = 0; i < attrib_count; i++) { + DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d," + " vs_output_tab %d\n", vinfo->attrib[i].src_index, + vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, + vs_output_tab[i]); + } + + for (i = 0; i < attrib_count; i++) { + /* Make sure we have a proper destination for our attribute. */ + assert(vs_output_tab[i] != -1); + + format = draw_translate_vinfo_format(vinfo->attrib[i].emit); + + /* Obtain the type of data in this attribute. */ + type = r300_translate_vertex_data_type(format) | + vs_output_tab[i] << R300_DST_VEC_LOC_SHIFT; + + /* Obtain the swizzle for this attribute. Note that the default + * swizzle in the hardware is not XYZW! */ + swizzle = r300_translate_vertex_data_swizzle(format); + + /* Add the attribute to the PSC table. */ + if (i & 1) { + vstream->vap_prog_stream_cntl[i >> 1] |= type << 16; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; + } else { + vstream->vap_prog_stream_cntl[i >> 1] |= type; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; + } + } + + /* Set the last vector in the PSC. */ + if (i) { + i -= 1; + } + vstream->vap_prog_stream_cntl[i >> 1] |= + (R300_LAST_VEC << (i & 1 ? 16 : 0)); + + vstream->count = (i >> 1) + 1; +} + +static void* r300_create_vertex_elements_state(struct pipe_context* pipe, + unsigned count, + const struct pipe_vertex_element* attribs) +{ + struct r300_context *r300 = r300_context(pipe); + struct r300_screen* r300screen = r300_screen(pipe->screen); + struct r300_vertex_element_state *velems; + + assert(count <= PIPE_MAX_ATTRIBS); + velems = CALLOC_STRUCT(r300_vertex_element_state); + if (velems != NULL) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); + + if (r300screen->caps->has_tcl) { + r300_vertex_psc(velems); + } else { + memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); + r300_draw_emit_all_attribs(r300); + draw_compute_vertex_size(&r300->vertex_info); + r300_swtcl_vertex_psc(r300, velems); + } + } + return velems; +} + +static void r300_bind_vertex_elements_state(struct pipe_context *pipe, + void *state) +{ + struct r300_context *r300 = r300_context(pipe); + struct r300_vertex_element_state *velems = state; + + if (velems == NULL) { + return; + } + + r300->velems = velems; if (r300->draw) { draw_flush(r300->draw); - draw_set_vertex_elements(r300->draw, count, elements); + draw_set_vertex_elements(r300->draw, velems->count, velems->velem); } if (!r300_validate_aos(r300)) { @@ -1081,6 +1329,14 @@ static void r300_set_vertex_elements(struct pipe_context* pipe, assert(0); abort(); } + + UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); + r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2; +} + +static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state) +{ + FREE(state); } static void* r300_create_vs_state(struct pipe_context* pipe, @@ -1088,68 +1344,71 @@ static void* r300_create_vs_state(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); - if (r300_screen(pipe->screen)->caps->has_tcl) { - struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); - /* Copy state directly into shader. */ - vs->state = *shader; - vs->state.tokens = tgsi_dup_tokens(shader->tokens); - - tgsi_scan_shader(shader->tokens, &vs->info); + struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); + r300_vertex_shader_common_init(vs, shader); - return (void*)vs; + if (r300_screen(pipe->screen)->caps->has_tcl) { + r300_translate_vertex_shader(r300, vs); } else { - return draw_create_vertex_shader(r300->draw, shader); + vs->draw_vs = draw_create_vertex_shader(r300->draw, shader); } + + return vs; } static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); + struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; - if (r300_screen(pipe->screen)->caps->has_tcl) { - struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; + if (vs == NULL) { + r300->vs_state.state = NULL; + return; + } + if (vs == r300->vs_state.state) { + return; + } + r300->vs_state.state = vs; - if (vs == NULL) { - r300->vs_state.state = NULL; - return; - } else if (!vs->translated) { - r300_translate_vertex_shader(r300, vs); - } + // VS output mapping for HWTCL or stream mapping for SWTCL to the RS block + if (r300->fs) { + r300_vertex_shader_setup_wpos(r300); + } + memcpy(r300->vap_output_state.state, &vs->vap_out, + sizeof(struct r300_vap_output_state)); + r300->vap_output_state.dirty = TRUE; + + /* The majority of the RS block bits is dependent on the vertex shader. */ + r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ - UPDATE_STATE(shader, r300->vs_state); + if (r300_screen(pipe->screen)->caps->has_tcl) { + r300->vs_state.dirty = TRUE; r300->vs_state.size = vs->code.length + 9; - r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ - r300->vap_output_state.dirty = TRUE; - r300->vertex_stream_state.dirty = TRUE; /* XXX needed for TCL bypass */ r300->pvs_flush.dirty = TRUE; - if (r300->fs) { - r300_vertex_shader_setup_wpos(r300); - } - r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; } else { draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, - (struct draw_vertex_shader*)shader); + (struct draw_vertex_shader*)vs->draw_vs); } } static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); + struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; if (r300_screen(pipe->screen)->caps->has_tcl) { - struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; - rc_constants_destroy(&vs->code.constants); - FREE((void*)vs->state.tokens); - FREE(shader); } else { draw_delete_vertex_shader(r300->draw, - (struct draw_vertex_shader*)shader); + (struct draw_vertex_shader*)vs->draw_vs); } + + FREE((void*)vs->state.tokens); + FREE(shader); } static void r300_set_constant_buffer(struct pipe_context *pipe, @@ -1201,8 +1460,10 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, pipe_buffer_unmap(pipe->screen, buf); if (shader == PIPE_SHADER_VERTEX) { - r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; - r300->pvs_flush.dirty = TRUE; + if (r300screen->caps->has_tcl) { + r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; + r300->pvs_flush.dirty = TRUE; + } } else if (shader == PIPE_SHADER_FRAGMENT) r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -1243,14 +1504,19 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.bind_vertex_sampler_states = r300_lacks_vertex_textures; r300->context.delete_sampler_state = r300_delete_sampler_state; - r300->context.set_fragment_sampler_textures = r300_set_sampler_textures; + r300->context.set_fragment_sampler_views = r300_set_fragment_sampler_views; + r300->context.create_sampler_view = r300_create_sampler_view; + r300->context.sampler_view_destroy = r300_sampler_view_destroy; r300->context.set_scissor_state = r300_set_scissor_state; r300->context.set_viewport_state = r300_set_viewport_state; r300->context.set_vertex_buffers = r300_set_vertex_buffers; - r300->context.set_vertex_elements = r300_set_vertex_elements; + + r300->context.create_vertex_elements_state = r300_create_vertex_elements_state; + r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state; + r300->context.delete_vertex_elements_state = r300_delete_vertex_elements_state; r300->context.create_vs_state = r300_create_vs_state; r300->context.bind_vs_state = r300_bind_vs_state; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 9c8e907fdf7..7947ec6641d 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -37,187 +37,6 @@ /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ -static void r300_draw_emit_attrib(struct r300_context* r300, - enum attrib_emit emit, - enum interp_mode interp, - int index) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct tgsi_shader_info* info = &vs->info; - int output; - - output = draw_find_shader_output(r300->draw, - info->output_semantic_name[index], - info->output_semantic_index[index]); - draw_emit_vertex_attr(&r300->vertex_info, emit, interp, output); -} - -static void r300_draw_emit_all_attribs(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_shader_semantics* vs_outputs = &vs->outputs; - int i, gen_count; - - /* Position. */ - if (vs_outputs->pos != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->pos); - } else { - assert(0); - } - - /* Point size. */ - if (vs_outputs->psize != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_1F_PSIZE, INTERP_POS, - vs_outputs->psize); - } - - /* Colors. */ - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_LINEAR, - vs_outputs->color[i]); - } - } - - /* XXX Back-face colors. */ - - /* Texture coordinates. */ - gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->generic[i]); - gen_count++; - } - } - - /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->fog); - gen_count++; - } - - /* XXX magic */ - assert(gen_count <= 8); -} - -/* Update the PSC tables. */ -/* XXX move this function into r300_state.c after TCL-bypass gets removed - * XXX because this one is dependent only on vertex elements. */ -static void r300_vertex_psc(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_vertex_stream_state *vformat = - (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; - uint16_t type, swizzle; - enum pipe_format format; - unsigned i; - int identity[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - int* stream_tab; - - memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); - - stream_tab = identity; - - /* Vertex shaders have no semantics on their inputs, - * so PSC should just route stuff based on the vertex elements, - * and not on attrib information. */ - DBG(r300, DBG_DRAW, "r300: vs expects %d attribs, routing %d elements" - " in psc\n", - vs->info.num_inputs, - r300->vertex_element_count); - - for (i = 0; i < r300->vertex_element_count; i++) { - format = r300->vertex_element[i].src_format; - - type = r300_translate_vertex_data_type(format) | - (stream_tab[i] << R300_DST_VEC_LOC_SHIFT); - swizzle = r300_translate_vertex_data_swizzle(format); - - if (i & 1) { - vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; - } else { - vformat->vap_prog_stream_cntl[i >> 1] |= type; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; - } - } - - assert(i <= 15); - - /* Set the last vector in the PSC. */ - if (i) { - i -= 1; - } - vformat->vap_prog_stream_cntl[i >> 1] |= - (R300_LAST_VEC << (i & 1 ? 16 : 0)); - - vformat->count = (i >> 1) + 1; - r300->vertex_stream_state.size = (1 + vformat->count) * 2; -} - -/* Update the PSC tables for SW TCL, using Draw. */ -static void r300_swtcl_vertex_psc(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_vertex_stream_state *vformat = - (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; - struct vertex_info* vinfo = &r300->vertex_info; - uint16_t type, swizzle; - enum pipe_format format; - unsigned i, attrib_count; - int* vs_output_tab = vs->stream_loc_notcl; - - memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); - - /* For each Draw attribute, route it to the fragment shader according - * to the vs_output_tab. */ - attrib_count = vinfo->num_attribs; - DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count); - for (i = 0; i < attrib_count; i++) { - DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d," - " vs_output_tab %d\n", vinfo->attrib[i].src_index, - vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, - vs_output_tab[i]); - } - - for (i = 0; i < attrib_count; i++) { - /* Make sure we have a proper destination for our attribute. */ - assert(vs_output_tab[i] != -1); - - format = draw_translate_vinfo_format(vinfo->attrib[i].emit); - - /* Obtain the type of data in this attribute. */ - type = r300_translate_vertex_data_type(format) | - vs_output_tab[i] << R300_DST_VEC_LOC_SHIFT; - - /* Obtain the swizzle for this attribute. Note that the default - * swizzle in the hardware is not XYZW! */ - swizzle = r300_translate_vertex_data_swizzle(format); - - /* Add the attribute to the PSC table. */ - if (i & 1) { - vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; - } else { - vformat->vap_prog_stream_cntl[i >> 1] |= type; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; - } - } - - /* Set the last vector in the PSC. */ - if (i) { - i -= 1; - } - vformat->vap_prog_stream_cntl[i >> 1] |= - (R300_LAST_VEC << (i & 1 ? 16 : 0)); - - vformat->count = (i >> 1) + 1; - r300->vertex_stream_state.size = (1 + vformat->count) * 2; -} - static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr, boolean swizzle_0001) { @@ -432,23 +251,8 @@ static void r300_update_rs_block(struct r300_context* r300, static void r300_update_derived_shader_state(struct r300_context* r300) { struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_screen* r300screen = r300_screen(r300->context.screen); - struct r300_vap_output_state *vap_out = - (struct r300_vap_output_state*)r300->vap_output_state.state; - - /* XXX Mmm, delicious hax */ - memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); - memcpy(vap_out, vs->hwfmt, sizeof(uint)*4); r300_update_rs_block(r300, &vs->outputs, &r300->fs->inputs); - - if (r300screen->caps->has_tcl) { - r300_vertex_psc(r300); - } else { - r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info); - r300_swtcl_vertex_psc(r300); - } } static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) @@ -536,10 +340,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) size = 2; for (i = 0; i < count; i++) { - if (state->textures[i] && state->sampler_states[i]) { + if (state->fragment_sampler_views[i] && state->sampler_states[i]) { state->tx_enable |= 1 << i; - tex = state->textures[i]; + tex = (struct r300_texture *)state->fragment_sampler_views[i]->texture; sampler = state->sampler_states[i]; texstate = &state->regs[i]; @@ -581,9 +385,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) void r300_update_derived_state(struct r300_context* r300) { - if (r300->rs_block_state.dirty || - r300->vertex_stream_state.dirty || /* XXX put updating this state out of this file */ - r300->rs_state.dirty) { /* XXX and remove this one (tcl_bypass dependency) */ + if (r300->rs_block_state.dirty) { r300_update_derived_shader_state(r300); } diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 2f3a56e1fbc..8485d4f8f94 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -327,6 +327,18 @@ static INLINE uint32_t r300_anisotropy(unsigned max_aniso) } } +static INLINE uint32_t r500_anisotropy(unsigned max_aniso) +{ + if (!max_aniso) { + return 0; + } + max_aniso -= 1; + + // Map the range [0, 15] to [0, 63]. + return R500_TX_MAX_ANISO(MIN2((unsigned)(max_aniso*4.2001), 63)) | + R500_TX_ANISO_HIGH_QUALITY;; +} + /* Non-CSO state. (For now.) */ static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) @@ -348,39 +360,12 @@ static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) return 0; } -/* Utility function to count the number of components in RGBAZS formats. - * XXX should go to util or p_format.h */ -static INLINE unsigned pf_component_count(enum pipe_format format) { - unsigned count = 0; - - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 1)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 2)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 3)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { - count++; - } - - return count; -} - /* Translate pipe_formats into PSC vertex types. */ static INLINE uint16_t r300_translate_vertex_data_type(enum pipe_format format) { uint32_t result = 0; const struct util_format_description *desc; - unsigned components = pf_component_count(format); + unsigned components = util_format_get_nr_components(format); desc = util_format_description(format); @@ -453,7 +438,6 @@ r300_translate_vertex_data_type(enum pipe_format format) { static INLINE uint16_t r300_translate_vertex_data_swizzle(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); - unsigned swizzle[4], i; assert(format); @@ -463,25 +447,10 @@ r300_translate_vertex_data_swizzle(enum pipe_format format) { return 0; } - /* Swizzles for 8bits formats are in the reversed order, not sure why. */ - if (desc->channel[0].size == 8) { - for (i = 0; i < 4; i++) { - if (desc->swizzle[i] <= 3) { - swizzle[i] = 3 - desc->swizzle[i]; - } else { - swizzle[i] = desc->swizzle[i]; - } - } - } else { - for (i = 0; i < 4; i++) { - swizzle[i] = desc->swizzle[i]; - } - } - - return ((swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | - (swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | - (swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | - (swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | + return ((desc->swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | + (desc->swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | + (desc->swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | + (desc->swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | (0xf << R300_WRITE_ENA_SHIFT)); } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index c0144f64b4a..7c7656068bb 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -617,18 +617,23 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex, /* Return true if macrotiling should be enabled on the miplevel. */ static boolean r300_texture_macro_switch(struct r300_texture *tex, unsigned level, - boolean rv350_mode) + boolean rv350_mode, + int dim) { - unsigned tile_width, width; + unsigned tile, texdim; - tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, TRUE); - width = u_minify(tex->tex.width0, level); + tile = r300_texture_get_tile_size(tex, dim, TRUE); + if (dim == TILE_WIDTH) { + texdim = u_minify(tex->tex.width0, level); + } else { + texdim = u_minify(tex->tex.height0, level); + } /* See TX_FILTER1_n.MACRO_SWITCH. */ if (rv350_mode) { - return width >= tile_width; + return texdim >= tile; } else { - return width > tile_width; + return texdim > tile; } } @@ -692,9 +697,10 @@ static void r300_setup_miptree(struct r300_screen* screen, for (i = 0; i <= base->last_level; i++) { /* Let's see if this miplevel can be macrotiled. */ - tex->mip_macrotile[i] = (tex->macrotile == R300_BUFFER_TILED && - r300_texture_macro_switch(tex, i, rv350_mode)) ? - R300_BUFFER_TILED : R300_BUFFER_LINEAR; + tex->mip_macrotile[i] = + (tex->macrotile == R300_BUFFER_TILED && + r300_texture_macro_switch(tex, i, rv350_mode, TILE_WIDTH)) ? + R300_BUFFER_TILED : R300_BUFFER_LINEAR; stride = r300_texture_get_stride(screen, tex, i); nblocksy = r300_texture_get_nblocksy(tex, i); @@ -724,14 +730,50 @@ static void r300_setup_flags(struct r300_texture* tex) !util_is_power_of_two(tex->tex.height0); } +static void r300_setup_tiling(struct pipe_screen *screen, + struct r300_texture *tex) +{ + enum pipe_format format = tex->tex.format; + boolean rv350_mode = r300_screen(screen)->caps->family >= CHIP_FAMILY_RV350; + + if (util_format_is_compressed(format)) { + return; + } + + if (tex->tex.width0 == 1 || + tex->tex.height0 == 1) { + return; + } + + /* Set microtiling. */ + switch (util_format_get_blocksize(format)) { + case 1: + case 4: + tex->microtile = R300_BUFFER_TILED; + break; + + /* XXX Square-tiling doesn't work with kernel older than 2.6.34, + * XXX need to check the DRM version */ + /*case 2: + case 8: + tex->microtile = R300_BUFFER_SQUARETILED; + break;*/ + } + + /* Set macrotiling. */ + if (r300_texture_macro_switch(tex, 0, rv350_mode, TILE_WIDTH) && + r300_texture_macro_switch(tex, 0, rv350_mode, TILE_HEIGHT)) { + tex->macrotile = R300_BUFFER_TILED; + } +} + /* Create a new texture. */ -static struct pipe_texture* - r300_texture_create(struct pipe_screen* screen, - const struct pipe_texture* template) +static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, + const struct pipe_texture* template) { struct r300_texture* tex = CALLOC_STRUCT(r300_texture); struct r300_screen* rscreen = r300_screen(screen); - struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; if (!tex) { return NULL; @@ -742,16 +784,19 @@ static struct pipe_texture* tex->tex.screen = screen; r300_setup_flags(tex); + if (!(template->tex_usage & R300_TEXTURE_USAGE_TRANSFER)) { + r300_setup_tiling(screen, tex); + } r300_setup_miptree(rscreen, tex); r300_setup_texture_state(rscreen, tex); - tex->buffer = screen->buffer_create(screen, 2048, - PIPE_BUFFER_USAGE_PIXEL, - tex->size); - winsys->buffer_set_tiling(winsys, tex->buffer, - tex->pitch[0], - tex->microtile != R300_BUFFER_LINEAR, - tex->macrotile != R300_BUFFER_LINEAR); + tex->buffer = rws->buffer_create(rws, 2048, + PIPE_BUFFER_USAGE_PIXEL, + tex->size); + rws->buffer_set_tiling(rws, tex->buffer, + tex->pitch[0], + tex->microtile != R300_BUFFER_LINEAR, + tex->macrotile != R300_BUFFER_LINEAR); if (!tex->buffer) { FREE(tex); @@ -764,9 +809,9 @@ static struct pipe_texture* static void r300_texture_destroy(struct pipe_texture* texture) { struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; - pipe_buffer_reference(&tex->buffer, NULL); - + rws->buffer_reference(rws, &tex->buffer, NULL); FREE(tex); } @@ -806,14 +851,17 @@ static void r300_tex_surface_destroy(struct pipe_surface* s) FREE(s); } + static struct pipe_texture* - r300_texture_blanket(struct pipe_screen* screen, - const struct pipe_texture* base, - const unsigned* stride, - struct pipe_buffer* buffer) + r300_texture_from_handle(struct pipe_screen* screen, + const struct pipe_texture* base, + struct winsys_handle *whandle) { - struct r300_texture* tex; + struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; struct r300_screen* rscreen = r300_screen(screen); + struct r300_winsys_buffer *buffer; + struct r300_texture* tex; + unsigned stride; /* Support only 2D textures without mipmaps */ if (base->target != PIPE_TEXTURE_2D || @@ -822,6 +870,11 @@ static struct pipe_texture* return NULL; } + buffer = rws->buffer_from_handle(rws, screen, whandle, &stride); + if (!buffer) { + return NULL; + } + tex = CALLOC_STRUCT(r300_texture); if (!tex) { return NULL; @@ -831,17 +884,38 @@ static struct pipe_texture* pipe_reference_init(&tex->tex.reference, 1); tex->tex.screen = screen; - tex->stride_override = *stride; - tex->pitch[0] = *stride / util_format_get_blocksize(base->format); + tex->stride_override = stride; + tex->pitch[0] = stride / util_format_get_blocksize(base->format); r300_setup_flags(tex); r300_setup_texture_state(rscreen, tex); - pipe_buffer_reference(&tex->buffer, buffer); + /* one ref already taken */ + tex->buffer = buffer; return (struct pipe_texture*)tex; } +static boolean + r300_texture_get_handle(struct pipe_screen* screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; + struct r300_texture* tex = (struct r300_texture*)texture; + unsigned stride; + + if (!tex) { + return FALSE; + } + + stride = r300_texture_get_stride(r300_screen(screen), tex, 0); + + rws->buffer_get_handle(rws, tex->buffer, stride, whandle); + + return TRUE; +} + static struct pipe_video_surface * r300_video_surface_create(struct pipe_screen *screen, enum pipe_video_chroma_format chroma_format, @@ -893,10 +967,11 @@ static void r300_video_surface_destroy(struct pipe_video_surface *vsfc) void r300_init_screen_texture_functions(struct pipe_screen* screen) { screen->texture_create = r300_texture_create; + screen->texture_from_handle = r300_texture_from_handle; + screen->texture_get_handle = r300_texture_get_handle; screen->texture_destroy = r300_texture_destroy; screen->get_tex_surface = r300_get_tex_surface; screen->tex_surface_destroy = r300_tex_surface_destroy; - screen->texture_blanket = r300_texture_blanket; screen->video_surface_create = r300_video_surface_create; screen->video_surface_destroy= r300_video_surface_destroy; @@ -904,19 +979,23 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen) boolean r300_get_texture_buffer(struct pipe_screen* screen, struct pipe_texture* texture, - struct pipe_buffer** buffer, + struct r300_winsys_buffer** buffer, unsigned* stride) { struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; + struct r300_winsys_buffer *buf; + if (!tex) { return FALSE; } - pipe_buffer_reference(buffer, tex->buffer); + rws->buffer_reference(rws, &buf, tex->buffer); if (stride) { *stride = r300_texture_get_stride(r300_screen(screen), tex, 0); } + *buffer = buf; return TRUE; } diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 46a5fb6188b..60c7fa83420 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -60,13 +60,11 @@ r300_video_surface(struct pipe_video_surface *pvs) return (struct r300_video_surface *)pvs; } -#ifndef R300_WINSYS_H - +/* Used internally for texture_is_referenced() + */ boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture* texture, - struct pipe_buffer** buffer, + struct pipe_texture *texture, + struct r300_winsys_buffer** buffer, unsigned* stride); -#endif /* R300_WINSYS_H */ - #endif /* R300_TEXTURE_H */ diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c new file mode 100644 index 00000000000..987a040698f --- /dev/null +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -0,0 +1,280 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> + * + * 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 AUTHOR(S) 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. */ + +#include "r300_context.h" +#include "r300_transfer.h" +#include "r300_texture.h" +#include "r300_screen.h" + +#include "r300_winsys.h" + +#include "util/u_memory.h" +#include "util/u_format.h" + +struct r300_transfer { + /* Parent class */ + struct pipe_transfer transfer; + + /* Pipe context. */ + struct pipe_context *ctx; + + /* Parameters of get_tex_transfer. */ + unsigned x, y, level, zslice, face; + + /* Offset from start of buffer. */ + unsigned offset; + + /* Detiled texture. */ + struct r300_texture *detiled_texture; + + /* Transfer and format flags. */ + unsigned buffer_usage, render_target_usage; +}; + +/* Convenience cast wrapper. */ +static INLINE struct r300_transfer* +r300_transfer(struct pipe_transfer* transfer) +{ + return (struct r300_transfer*)transfer; +} + +/* Copy from a tiled texture to a detiled one. */ +static void r300_copy_from_tiled_texture(struct pipe_context *ctx, + struct r300_transfer *r300transfer) +{ + struct pipe_screen *screen = ctx->screen; + struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; + struct pipe_texture *tex = transfer->texture; + struct pipe_surface *src, *dst; + + src = screen->get_tex_surface(screen, tex, r300transfer->face, + r300transfer->level, r300transfer->zslice, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_PIXEL); + + dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE | + PIPE_BUFFER_USAGE_PIXEL | + r300transfer->buffer_usage); + + ctx->surface_copy(ctx, dst, 0, 0, src, r300transfer->x, r300transfer->y, + transfer->width, transfer->height); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +/* Copy a detiled texture to a tiled one. */ +static void r300_copy_into_tiled_texture(struct pipe_context *ctx, + struct r300_transfer *r300transfer) +{ + struct pipe_screen *screen = ctx->screen; + struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; + struct pipe_texture *tex = transfer->texture; + struct pipe_surface *src, *dst; + + src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_PIXEL); + + dst = screen->get_tex_surface(screen, tex, r300transfer->face, + r300transfer->level, r300transfer->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE | + PIPE_BUFFER_USAGE_PIXEL); + + /* XXX this flush prevents the following DRM error from occuring: + * [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation ! + * Reproducible with perf/copytex. */ + ctx->flush(ctx, 0, NULL); + + ctx->surface_copy(ctx, dst, r300transfer->x, r300transfer->y, src, 0, 0, + transfer->width, transfer->height); + + /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */ + ctx->flush(ctx, 0, NULL); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +static struct pipe_transfer* +r300_get_tex_transfer(struct pipe_context *ctx, + struct pipe_texture *texture, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, unsigned x, unsigned y, + unsigned w, unsigned h) +{ + struct r300_texture *tex = (struct r300_texture *)texture; + struct r300_screen *r300screen = r300_screen(ctx->screen); + struct r300_transfer *trans; + struct pipe_texture template; + + trans = CALLOC_STRUCT(r300_transfer); + if (trans) { + /* Initialize the transfer object. */ + pipe_texture_reference(&trans->transfer.texture, texture); + trans->transfer.usage = usage; + trans->transfer.width = w; + trans->transfer.height = h; + trans->ctx = ctx; + trans->x = x; + trans->y = y; + trans->level = level; + trans->zslice = zslice; + trans->face = face; + + /* If the texture is tiled, we must create a temporary detiled texture + * for this transfer. */ + if (tex->microtile || tex->macrotile) { + trans->buffer_usage = pipe_transfer_buffer_flags(&trans->transfer); + trans->render_target_usage = + util_format_is_depth_or_stencil(texture->format) ? + PIPE_TEXTURE_USAGE_DEPTH_STENCIL : + PIPE_TEXTURE_USAGE_RENDER_TARGET; + + template.target = PIPE_TEXTURE_2D; + template.format = texture->format; + template.width0 = w; + template.height0 = h; + template.depth0 = 0; + template.last_level = 0; + template.nr_samples = 0; + template.tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + R300_TEXTURE_USAGE_TRANSFER; + + /* For texture reading, the temporary (detiled) texture is used as + * a render target when blitting from a tiled texture. */ + if (usage & PIPE_TRANSFER_READ) { + template.tex_usage |= trans->render_target_usage; + } + /* For texture writing, the temporary texture is used as a sampler + * when blitting into a tiled texture. */ + if (usage & PIPE_TRANSFER_WRITE) { + template.tex_usage |= PIPE_TEXTURE_USAGE_SAMPLER; + } + + /* Create the temporary texture. */ + trans->detiled_texture = (struct r300_texture*) + ctx->screen->texture_create(ctx->screen, + &template); + + assert(!trans->detiled_texture->microtile && + !trans->detiled_texture->macrotile); + + /* Set the stride. + * Parameters x, y, level, zslice, and face remain zero. */ + trans->transfer.stride = + r300_texture_get_stride(r300screen, trans->detiled_texture, 0); + + if (usage & PIPE_TRANSFER_READ) { + /* We cannot map a tiled texture directly because the data is + * in a different order, therefore we do detiling using a blit. */ + r300_copy_from_tiled_texture(ctx, trans); + } + } else { + trans->transfer.x = x; + trans->transfer.y = y; + trans->transfer.stride = + r300_texture_get_stride(r300screen, tex, level); + trans->transfer.level = level; + trans->transfer.zslice = zslice; + trans->transfer.face = face; + trans->offset = r300_texture_get_offset(tex, level, zslice, face); + } + } + return &trans->transfer; +} + +static void r300_tex_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *trans) +{ + struct r300_transfer *r300transfer = r300_transfer(trans); + + if (r300transfer->detiled_texture) { + if (trans->usage & PIPE_TRANSFER_WRITE) { + r300_copy_into_tiled_texture(r300transfer->ctx, r300transfer); + } + + pipe_texture_reference( + (struct pipe_texture**)&r300transfer->detiled_texture, NULL); + } + pipe_texture_reference(&trans->texture, NULL); + FREE(trans); +} + +static void* r300_transfer_map(struct pipe_context *ctx, + struct pipe_transfer *transfer) +{ + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; + struct r300_transfer *r300transfer = r300_transfer(transfer); + struct r300_texture *tex = (struct r300_texture*)transfer->texture; + char *map; + enum pipe_format format = tex->tex.format; + + if (r300transfer->detiled_texture) { + /* The detiled texture is of the same size as the region being mapped + * (no offset needed). */ + return rws->buffer_map(rws, + r300transfer->detiled_texture->buffer, + pipe_transfer_buffer_flags(transfer)); + } else { + /* Tiling is disabled. */ + map = rws->buffer_map(rws, tex->buffer, + pipe_transfer_buffer_flags(transfer)); + + if (!map) { + return NULL; + } + + return map + r300_transfer(transfer)->offset + + transfer->y / util_format_get_blockheight(format) * transfer->stride + + transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + } +} + +static void r300_transfer_unmap(struct pipe_context *ctx, + struct pipe_transfer *transfer) +{ + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; + struct r300_transfer *r300transfer = r300_transfer(transfer); + struct r300_texture *tex = (struct r300_texture*)transfer->texture; + + if (r300transfer->detiled_texture) { + rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer); + } else { + rws->buffer_unmap(rws, tex->buffer); + } +} + + +void r300_init_transfer_functions( struct r300_context *r300ctx ) +{ + struct pipe_context *ctx = &r300ctx->context; + + ctx->get_tex_transfer = r300_get_tex_transfer; + ctx->tex_transfer_destroy = r300_tex_transfer_destroy; + ctx->transfer_map = r300_transfer_map; + ctx->transfer_unmap = r300_transfer_unmap; +} diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h new file mode 100644 index 00000000000..79baf6d0480 --- /dev/null +++ b/src/gallium/drivers/r300/r300_transfer.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> + * + * 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 AUTHOR(S) 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 R300_TRANSFER +#define R300_TRANSFER + +#include "pipe/p_screen.h" + +struct r300_context; + +void r300_init_transfer_functions(struct r300_context *r300ctx); + +#endif diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 60a04bbfeda..bd6b95dccba 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -34,8 +34,6 @@ #include "radeon_compiler.h" -#include "util/u_math.h" - /* Convert info about VS output semantics into r300_shader_semantics. */ static void r300_shader_read_vs_outputs( struct tgsi_shader_info* info, @@ -89,95 +87,41 @@ static void r300_shader_read_vs_outputs( assert(0); } } + + /* WPOS is a straight copy of POSITION and it's always emitted. */ + vs_outputs->wpos = i; } -static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs) +/* This function sets up: + * - VAP mapping, which maps VS registers to output semantics and + * at the same time it indicates which attributes are enabled and should + * be rasterized. + * - Stream mapping to VS outputs if TCL is not present. */ +static void r300_init_vs_output_mapping(struct r300_vertex_shader* vs) { struct r300_shader_semantics* vs_outputs = &vs->outputs; - uint32_t* hwfmt = vs->hwfmt; - int i, gen_count; + struct r300_vap_output_state *vap_out = &vs->vap_out; + int *stream_loc = vs->stream_loc_notcl; + int i, gen_count, tabi = 0; boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || vs_outputs->bcolor[1] != ATTR_UNUSED; - /* Do the actual vertex_info setup. - * - * vertex_info has four uints of hardware-specific data in it. - * vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL - * vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM - * vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0 - * vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */ - - hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */ + vap_out->vap_vtx_state_cntl = 0x5555; /* XXX this is classic Mesa bonghits */ /* Position. */ if (vs_outputs->pos != ATTR_UNUSED) { - hwfmt[1] |= R300_INPUT_CNTL_POS; - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_POS; + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + + stream_loc[tabi++] = 0; } else { assert(0); } /* Point size. */ if (vs_outputs->psize != ATTR_UNUSED) { - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; - } - - /* Colors. */ - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || - vs_outputs->color[1] != ATTR_UNUSED) { - hwfmt[1] |= R300_INPUT_CNTL_COLOR; - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; - } - } - - /* Back-face colors. */ - if (any_bcolor_used) { - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - hwfmt[1] |= R300_INPUT_CNTL_COLOR; - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); - } - } - - /* Texture coordinates. */ - gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { - hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); - hwfmt[3] |= (4 << (3 * gen_count)); - gen_count++; - } - } - - /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { - hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); - hwfmt[3] |= (4 << (3 * gen_count)); - gen_count++; - } - - /* XXX magic */ - assert(gen_count <= 8); + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; - /* WPOS. */ - vs->wpos_tex_output = gen_count; -} - -/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed - * or isn't present. */ -static void r300_stream_locations_notcl( - struct r300_shader_semantics* vs_outputs, - int* stream_loc) -{ - int i, tabi = 0, gen_count; - boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || - vs_outputs->bcolor[1] != ATTR_UNUSED; - - /* Position. */ - stream_loc[tabi++] = 0; - - /* Point size. */ - if (vs_outputs->psize != ATTR_UNUSED) { stream_loc[tabi++] = 1; } @@ -185,6 +129,9 @@ static void r300_stream_locations_notcl( for (i = 0; i < ATTR_COLOR_COUNT; i++) { if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || vs_outputs->color[1] != ATTR_UNUSED) { + vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; + stream_loc[tabi++] = 2 + i; } } @@ -192,6 +139,9 @@ static void r300_stream_locations_notcl( /* Back-face colors. */ if (any_bcolor_used) { for (i = 0; i < ATTR_COLOR_COUNT; i++) { + vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); + stream_loc[tabi++] = 4 + i; } } @@ -200,6 +150,9 @@ static void r300_stream_locations_notcl( gen_count = 0; for (i = 0; i < ATTR_GENERIC_COUNT; i++) { if (vs_outputs->generic[i] != ATTR_UNUSED) { + vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count); + vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count)); + assert(tabi < 16); stream_loc[tabi++] = 6 + gen_count; gen_count++; @@ -208,17 +161,22 @@ static void r300_stream_locations_notcl( /* Fog coordinates. */ if (vs_outputs->fog != ATTR_UNUSED) { + vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count); + vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count)); + assert(tabi < 16); stream_loc[tabi++] = 6 + gen_count; gen_count++; } + /* XXX magic */ + assert(gen_count <= 8); + /* WPOS. */ - if (vs_outputs->wpos != ATTR_UNUSED) { - assert(tabi < 16); - stream_loc[tabi++] = 6 + gen_count; - gen_count++; - } + vs->wpos_tex_output = gen_count; + + assert(tabi < 16); + stream_loc[tabi++] = 6 + gen_count; for (; tabi < 16;) { stream_loc[tabi++] = -1; @@ -294,26 +252,16 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) } } -static void r300_insert_wpos(struct r300_vertex_program_compiler* c, - struct r300_shader_semantics* outputs) +void r300_vertex_shader_common_init(struct r300_vertex_shader *vs, + const struct pipe_shader_state *shader) { - int i, lastOutput = 0; + /* Copy state directly into shader. */ + vs->state = *shader; + vs->state.tokens = tgsi_dup_tokens(shader->tokens); + tgsi_scan_shader(shader->tokens, &vs->info); - /* Find the max output index. */ - lastOutput = MAX2(lastOutput, outputs->psize); - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - lastOutput = MAX2(lastOutput, outputs->color[i]); - lastOutput = MAX2(lastOutput, outputs->bcolor[i]); - } - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - lastOutput = MAX2(lastOutput, outputs->generic[i]); - } - lastOutput = MAX2(lastOutput, outputs->fog); - - /* Set WPOS after the last output. */ - lastOutput++; - rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */ - outputs->wpos = lastOutput; + r300_shader_read_vs_outputs(&vs->info, &vs->outputs); + r300_init_vs_output_mapping(vs); } void r300_translate_vertex_shader(struct r300_context* r300, @@ -322,9 +270,6 @@ void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; - /* Initialize. */ - r300_shader_read_vs_outputs(&vs->info, &vs->outputs); - /* Setup the compiler */ rc_init(&compiler.Base); @@ -348,10 +293,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, compiler.SetHwInputOutput = &set_vertex_inputs_outputs; /* Insert the WPOS output. */ - r300_insert_wpos(&compiler, &vs->outputs); - - r300_shader_vap_output_fmt(vs); - r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl); + rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); /* Invoke the compiler */ r3xx_compile_vertex_program(&compiler); @@ -363,30 +305,29 @@ void r300_translate_vertex_shader(struct r300_context* r300, /* And, finally... */ rc_destroy(&compiler.Base); - vs->translated = TRUE; } boolean r300_vertex_shader_setup_wpos(struct r300_context* r300) { struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_vap_output_state *vap_out = &vs->vap_out; int tex_output = vs->wpos_tex_output; uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output; - uint32_t* hwfmt = vs->hwfmt; if (r300->fs->inputs.wpos != ATTR_UNUSED) { /* Enable WPOS in VAP. */ - if (!(hwfmt[1] & tex_fmt)) { - hwfmt[1] |= tex_fmt; - hwfmt[3] |= (4 << (3 * tex_output)); + if (!(vap_out->vap_vsm_vtx_assm & tex_fmt)) { + vap_out->vap_vsm_vtx_assm |= tex_fmt; + vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * tex_output)); assert(tex_output < 8); return TRUE; } } else { /* Disable WPOS in VAP. */ - if (hwfmt[1] & tex_fmt) { - hwfmt[1] &= ~tex_fmt; - hwfmt[3] &= ~(4 << (3 * tex_output)); + if (vap_out->vap_vsm_vtx_assm & tex_fmt) { + vap_out->vap_vsm_vtx_assm &= ~tex_fmt; + vap_out->vap_out_vtx_fmt[1] &= ~(4 << (3 * tex_output)); return TRUE; } } diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 18cfeee3cd4..f6f0b86b683 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -28,6 +28,7 @@ #include "tgsi/tgsi_scan.h" #include "radeon_code.h" +#include "r300_context.h" #include "r300_shader_semantics.h" struct r300_context; @@ -38,7 +39,7 @@ struct r300_vertex_shader { struct tgsi_shader_info info; struct r300_shader_semantics outputs; - uint hwfmt[4]; + struct r300_vap_output_state vap_out; /* Stream locations for SWTCL or if TCL is bypassed. */ int stream_loc_notcl[16]; @@ -46,13 +47,17 @@ struct r300_vertex_shader { /* Output stream location for WPOS. */ int wpos_tex_output; - /* Has this shader been translated yet? */ - boolean translated; - + /* HWTCL-specific. */ /* Machine code (if translated) */ struct r300_vertex_program_code code; + + /* SWTCL-specific. */ + void *draw_vs; }; +void r300_vertex_shader_common_init(struct r300_vertex_shader *vs, + const struct pipe_shader_state *shader); + void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 40fb8a95ca5..e5183a8239c 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -23,10 +23,6 @@ #ifndef R300_WINSYS_H #define R300_WINSYS_H -#ifdef __cplusplus -extern "C" { -#endif - /* The public interface header for the r300 pipe driver. * Any winsys hosting this pipe needs to implement r300_winsys and then * call r300_create_screen to start things. */ @@ -34,19 +30,146 @@ extern "C" { #include "pipe/p_defines.h" #include "pipe/p_state.h" -struct radeon_winsys; +struct r300_winsys_screen; /* Creates a new r300 screen. */ -struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); +struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws); + +struct r300_winsys_buffer; boolean r300_get_texture_buffer(struct pipe_screen* screen, struct pipe_texture* texture, - struct pipe_buffer** buffer, - unsigned* stride); + struct r300_winsys_buffer** buffer, + unsigned *stride); + +enum r300_value_id { + R300_VID_PCI_ID, + R300_VID_GB_PIPES, + R300_VID_Z_PIPES, +}; + +#define R300_USAGE_FLAG_DONT_SYNC (1 << 17) + +struct r300_winsys_screen { + void (*destroy)(struct r300_winsys_screen *ws); + + /** + * Buffer management. Buffer attributes are mostly fixed over its lifetime. + * + * Remember that gallium gets to choose the interface it needs, and the + * window systems must then implement that interface (rather than the + * other way around...). + * + * usage is a bitmask of R300_WINSYS_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This + * usage argument is only an optimization hint, not a guarantee, therefore + * proper behavior must be observed in all circumstances. + * + * alignment indicates the client's alignment requirements, eg for + * SSE instructions. + */ + struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws, + unsigned alignment, + unsigned usage, + unsigned size); + + /** + * Map the entire data store of a buffer object into the client's address. + * flags is bitmask of R300_WINSYS_BUFFER_USAGE_CPU_READ/WRITE flags. + */ + void *(*buffer_map)( struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf, + unsigned usage); + + void (*buffer_unmap)( struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf ); + + void (*buffer_destroy)( struct r300_winsys_buffer *buf ); + + + void (*buffer_reference)(struct r300_winsys_screen *rws, + struct r300_winsys_buffer **pdst, + struct r300_winsys_buffer *src); + + boolean (*buffer_references)(struct r300_winsys_buffer *a, + struct r300_winsys_buffer *b); + + void (*buffer_flush_range)(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, + unsigned offset, + unsigned length); + + /* Add a pipe_buffer to the list of buffer objects to validate. */ + boolean (*add_buffer)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buf, + uint32_t rd, + uint32_t wd); + + + /* Revalidate all currently setup pipe_buffers. + * Returns TRUE if a flush is required. */ + boolean (*validate)(struct r300_winsys_screen* winsys); + + /* Check to see if there's room for commands. */ + boolean (*check_cs)(struct r300_winsys_screen* winsys, int size); + + /* Start a command emit. */ + void (*begin_cs)(struct r300_winsys_screen* winsys, + int size, + const char* file, + const char* function, + int line); + + /* Write a dword to the command buffer. */ + void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword); + + /* Write a relocated dword to the command buffer. */ + void (*write_cs_reloc)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buf, + uint32_t rd, + uint32_t wd, + uint32_t flags); + + /* Finish a command emit. */ + void (*end_cs)(struct r300_winsys_screen* winsys, + const char* file, + const char* function, + int line); + + /* Flush the CS. */ + void (*flush_cs)(struct r300_winsys_screen* winsys); + + /* winsys flush - callback from winsys when flush required */ + void (*set_flush_cb)(struct r300_winsys_screen *winsys, + void (*flush_cb)(void *), void *data); + + void (*reset_bos)(struct r300_winsys_screen *winsys); + + void (*buffer_set_tiling)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buffer, + uint32_t pitch, + boolean microtiled, + boolean macrotiled); + + uint32_t (*get_value)(struct r300_winsys_screen *winsys, + enum r300_value_id vid); + + struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys, + struct pipe_screen *screen, + struct winsys_handle *whandle, + unsigned *stride); + boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buffer, + unsigned stride, + struct winsys_handle *whandle); + + boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buffer); + + +}; -#ifdef __cplusplus -} -#endif +struct r300_winsys_screen * +r300_winsys_screen(struct pipe_screen *screen); #endif /* R300_WINSYS_H */ diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index e4ac49fa85f..239655d628b 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -6,7 +6,9 @@ LIBNAME = softpipe C_SOURCES = \ sp_fs_exec.c \ sp_fs_sse.c \ + sp_buffer.c \ sp_clear.c \ + sp_fence.c \ sp_flush.c \ sp_query.c \ sp_context.c \ @@ -32,7 +34,6 @@ C_SOURCES = \ sp_tex_tile_cache.c \ sp_tile_cache.c \ sp_surface.c \ - sp_video_context.c \ - sp_winsys.c + sp_video_context.c include ../../Makefile.template diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index 3042e556c64..9949a53adfd 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -7,9 +7,11 @@ softpipe = env.ConvenienceLibrary( source = [ 'sp_fs_exec.c', 'sp_fs_sse.c', + 'sp_buffer.c', 'sp_clear.c', 'sp_context.c', 'sp_draw_arrays.c', + 'sp_fence.c', 'sp_flush.c', 'sp_prim_vbuf.c', 'sp_setup.c', @@ -33,8 +35,7 @@ softpipe = env.ConvenienceLibrary( 'sp_tex_tile_cache.c', 'sp_texture.c', 'sp_tile_cache.c', - 'sp_video_context.c', - 'sp_winsys.c' + 'sp_video_context.c' ]) Export('softpipe') diff --git a/src/gallium/drivers/softpipe/sp_buffer.c b/src/gallium/drivers/softpipe/sp_buffer.c new file mode 100644 index 00000000000..8f390250869 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_buffer.c @@ -0,0 +1,118 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "sp_screen.h" +#include "sp_buffer.h" + + +static void * +softpipe_buffer_map(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned flags) +{ + struct softpipe_buffer *softpipe_buf = softpipe_buffer(buf); + return softpipe_buf->data; +} + + +static void +softpipe_buffer_unmap(struct pipe_screen *screen, + struct pipe_buffer *buf) +{ +} + + +static void +softpipe_buffer_destroy(struct pipe_buffer *buf) +{ + struct softpipe_buffer *sbuf = softpipe_buffer(buf); + + if (!sbuf->userBuffer) + align_free(sbuf->data); + + FREE(sbuf); +} + + +static struct pipe_buffer * +softpipe_buffer_create(struct pipe_screen *screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct softpipe_buffer *buffer = CALLOC_STRUCT(softpipe_buffer); + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.alignment = MAX2(alignment, 16); + buffer->base.usage = usage; + buffer->base.size = size; + + buffer->data = align_malloc(size, alignment); + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +softpipe_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes) +{ + struct softpipe_buffer *buffer; + + buffer = CALLOC_STRUCT(softpipe_buffer); + if(!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + +void +softpipe_init_screen_buffer_funcs(struct pipe_screen *screen) +{ + screen->buffer_create = softpipe_buffer_create; + screen->user_buffer_create = softpipe_user_buffer_create; + screen->buffer_map = softpipe_buffer_map; + screen->buffer_unmap = softpipe_buffer_unmap; + screen->buffer_destroy = softpipe_buffer_destroy; +} diff --git a/src/gallium/drivers/softpipe/sp_buffer.h b/src/gallium/drivers/softpipe/sp_buffer.h new file mode 100644 index 00000000000..9d8e56a176b --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_buffer.h @@ -0,0 +1,55 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SP_BUFFER_H +#define SP_BUFFER_H + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + + +struct softpipe_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; +}; + + +/** Cast wrapper */ +static INLINE struct softpipe_buffer * +softpipe_buffer( struct pipe_buffer *buf ) +{ + return (struct softpipe_buffer *)buf; +} + + +void +softpipe_init_screen_buffer_funcs(struct pipe_screen *screen); + + +#endif /* SP_BUFFER_H */ diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index ddc35bcd629..937a573092f 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -44,6 +44,7 @@ #include "sp_surface.h" #include "sp_tile_cache.h" #include "sp_tex_tile_cache.h" +#include "sp_texture.h" #include "sp_query.h" @@ -103,12 +104,12 @@ softpipe_destroy( struct pipe_context *pipe ) for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { sp_destroy_tex_tile_cache(softpipe->tex_cache[i]); - pipe_texture_reference(&softpipe->texture[i], NULL); + pipe_sampler_view_reference(&softpipe->sampler_views[i], NULL); } for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { sp_destroy_tex_tile_cache(softpipe->vertex_tex_cache[i]); - pipe_texture_reference(&softpipe->vertex_textures[i], NULL); + pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], NULL); } for (i = 0; i < PIPE_SHADER_TYPES; i++) { @@ -210,7 +211,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE ); softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE ); - softpipe->pipe.winsys = screen->winsys; + softpipe->pipe.winsys = NULL; softpipe->pipe.screen = screen; softpipe->pipe.destroy = softpipe_destroy; softpipe->pipe.priv = priv; @@ -245,6 +246,10 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.bind_gs_state = softpipe_bind_gs_state; softpipe->pipe.delete_gs_state = softpipe_delete_gs_state; + softpipe->pipe.create_vertex_elements_state = softpipe_create_vertex_elements_state; + softpipe->pipe.bind_vertex_elements_state = softpipe_bind_vertex_elements_state; + softpipe->pipe.delete_vertex_elements_state = softpipe_delete_vertex_elements_state; + softpipe->pipe.set_blend_color = softpipe_set_blend_color; softpipe->pipe.set_stencil_ref = softpipe_set_stencil_ref; softpipe->pipe.set_clip_state = softpipe_set_clip_state; @@ -252,12 +257,13 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple; softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; - softpipe->pipe.set_fragment_sampler_textures = softpipe_set_sampler_textures; - softpipe->pipe.set_vertex_sampler_textures = softpipe_set_vertex_sampler_textures; + softpipe->pipe.set_fragment_sampler_views = softpipe_set_sampler_views; + softpipe->pipe.set_vertex_sampler_views = softpipe_set_vertex_sampler_views; + softpipe->pipe.create_sampler_view = softpipe_create_sampler_view; + softpipe->pipe.sampler_view_destroy = softpipe_sampler_view_destroy; softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers; - softpipe->pipe.set_vertex_elements = softpipe_set_vertex_elements; softpipe->pipe.draw_arrays = softpipe_draw_arrays; softpipe->pipe.draw_elements = softpipe_draw_elements; @@ -272,6 +278,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.is_buffer_referenced = softpipe_is_buffer_referenced; softpipe_init_query_funcs( softpipe ); + softpipe_init_texture_funcs( &softpipe->pipe ); softpipe->pipe.render_condition = softpipe_render_condition; @@ -280,13 +287,13 @@ softpipe_create_context( struct pipe_screen *screen, * Must be before quad stage setup! */ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) - softpipe->cbuf_cache[i] = sp_create_tile_cache( screen ); - softpipe->zsbuf_cache = sp_create_tile_cache( screen ); + softpipe->cbuf_cache[i] = sp_create_tile_cache( &softpipe->pipe ); + softpipe->zsbuf_cache = sp_create_tile_cache( &softpipe->pipe ); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) - softpipe->tex_cache[i] = sp_create_tex_tile_cache( screen ); + softpipe->tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache(screen); + softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); } /* setup quad rendering stages */ diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 95def72c541..75e03c8ae6b 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -45,6 +45,7 @@ struct softpipe_tile_cache; struct softpipe_tex_tile_cache; struct sp_fragment_shader; struct sp_vertex_shader; +struct sp_velems_state; struct softpipe_context { @@ -59,6 +60,7 @@ struct softpipe_context { struct sp_fragment_shader *fs; struct sp_vertex_shader *vs; struct sp_geometry_shader *gs; + struct sp_velems_state *velems; /** Other rendering state */ struct pipe_blend_color blend_color; @@ -68,17 +70,15 @@ struct softpipe_context { struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; - struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; - struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; unsigned num_samplers; - unsigned num_textures; + unsigned num_sampler_views; unsigned num_vertex_samplers; - unsigned num_vertex_textures; - unsigned num_vertex_elements; + unsigned num_vertex_sampler_views; unsigned num_vertex_buffers; unsigned dirty; /**< Mask of SP_NEW_x flags */ @@ -93,7 +93,7 @@ struct softpipe_context { ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; /** Mapped constant buffers */ - void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; + const void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; /** Vertex format */ struct vertex_info vertex_info; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index b2acc36bf7a..7b77eb239fd 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -33,90 +33,19 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" #include "util/u_prim.h" #include "sp_context.h" #include "sp_query.h" #include "sp_state.h" +#include "sp_buffer.h" #include "draw/draw_context.h" -static void -softpipe_map_constant_buffers(struct softpipe_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - - for (i = 0; i < PIPE_SHADER_TYPES; i++) { - uint j; - - for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { - if (sp->constants[i][j] && sp->constants[i][j]->size) { - sp->mapped_constants[i][j] = ws->buffer_map(ws, - sp->constants[i][j], - PIPE_BUFFER_USAGE_CPU_READ); - } - } - } - - for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { - if (sp->constants[PIPE_SHADER_VERTEX][i]) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_VERTEX, - i, - sp->mapped_constants[PIPE_SHADER_VERTEX][i], - sp->constants[PIPE_SHADER_VERTEX][i]->size); - } - if (sp->constants[PIPE_SHADER_GEOMETRY][i]) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_GEOMETRY, - i, - sp->mapped_constants[PIPE_SHADER_GEOMETRY][i], - sp->constants[PIPE_SHADER_GEOMETRY][i]->size); - } - } -} - - -static void -softpipe_unmap_constant_buffers(struct softpipe_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - /* really need to flush all prims since the vert/frag shaders const buffers - * are going away now. - */ - draw_flush(sp->draw); - - for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_VERTEX, - i, - NULL, - 0); - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_GEOMETRY, - i, - NULL, - 0); - } - - for (i = 0; i < PIPE_SHADER_TYPES; i++) { - uint j; - - for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { - if (sp->constants[i][j] && sp->constants[i][j]->size) { - ws->buffer_unmap(ws, sp->constants[i][j]); - } - sp->mapped_constants[i][j] = NULL; - } - } -} /** @@ -261,25 +190,16 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, } softpipe_map_transfers(sp); - softpipe_map_constant_buffers(sp); /* Map vertex buffers */ for (i = 0; i < sp->num_vertex_buffers; i++) { - void *buf; - - buf = pipe_buffer_map(pipe->screen, - sp->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *buf = softpipe_buffer(sp->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { - void *mapped_indexes; - - mapped_indexes = pipe_buffer_map(pipe->screen, - indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *mapped_indexes = softpipe_buffer(indexBuffer)->data; draw_set_mapped_element_buffer_range(draw, indexSize, minIndex, @@ -300,15 +220,18 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, /* unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); - pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer); } if (indexBuffer) { draw_set_mapped_element_buffer(draw, 0, NULL); - pipe_buffer_unmap(pipe->screen, indexBuffer); } - /* Note: leave drawing surfaces mapped */ - softpipe_unmap_constant_buffers(sp); + /* + * TODO: Flush only when a user vertex/index buffer is present + * (or even better, modify draw module to do this + * internally when this condition is seen?) + */ + draw_flush(draw); + /* Note: leave drawing surfaces mapped */ sp->dirty_render_cache = TRUE; } diff --git a/src/gallium/drivers/softpipe/sp_fence.c b/src/gallium/drivers/softpipe/sp_fence.c new file mode 100644 index 00000000000..66c52141132 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_fence.c @@ -0,0 +1,70 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#include "pipe/p_screen.h" +#include "util/u_debug.h" +#include "sp_fence.h" + + +static void +softpipe_fence_reference(struct pipe_screen *screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + assert(!*ptr); + assert(!fence); +} + + +static int +softpipe_fence_signalled(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + assert(!fence); + return 0; +} + + +static int +softpipe_fence_finish(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + assert(!fence); + return 0; +} + + +void +softpipe_init_screen_fence_funcs(struct pipe_screen *screen) +{ + screen->fence_reference = softpipe_fence_reference; + screen->fence_finish = softpipe_fence_finish; + screen->fence_signalled = softpipe_fence_signalled; +} diff --git a/src/gallium/drivers/softpipe/sp_fence.h b/src/gallium/drivers/softpipe/sp_fence.h new file mode 100644 index 00000000000..39c33243bd5 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_fence.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#ifndef SP_FENCE_H_ +#define SP_FENCE_H_ + + +struct pipe_screen; + + +void +softpipe_init_screen_fence_funcs(struct pipe_screen *screen); + + +#endif /* SP_FENCE_H_ */ diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index e8952bf4fb8..508fe8f764d 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -50,10 +50,10 @@ softpipe_flush( struct pipe_context *pipe, draw_flush(softpipe->draw); if (flags & PIPE_FLUSH_TEXTURE_CACHE) { - for (i = 0; i < softpipe->num_textures; i++) { + for (i = 0; i < softpipe->num_sampler_views; i++) { sp_flush_tex_tile_cache(softpipe->tex_cache[i]); } - for (i = 0; i < softpipe->num_vertex_textures; i++) { + for (i = 0; i < softpipe->num_vertex_sampler_views; i++) { sp_flush_tex_tile_cache(softpipe->vertex_tex_cache[i]); } } @@ -93,9 +93,9 @@ softpipe_flush( struct pipe_context *pipe, static unsigned frame_no = 1; static char filename[256]; util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no); - debug_dump_surface_bmp(filename, softpipe->framebuffer.cbufs[0]); + debug_dump_surface_bmp(softpipe, filename, softpipe->framebuffer.cbufs[0]); util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no); - debug_dump_surface_bmp(filename, softpipe->framebuffer.zsbuf); + debug_dump_surface_bmp(softpipe, filename, softpipe->framebuffer.zsbuf); ++frame_no; } #endif diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c index 27fa126b7c3..67e2c8f8bc4 100644 --- a/src/gallium/drivers/softpipe/sp_fs_exec.c +++ b/src/gallium/drivers/softpipe/sp_fs_exec.c @@ -145,8 +145,13 @@ exec_run( const struct sp_fragment_shader *base, case TGSI_SEMANTIC_COLOR: { uint cbuf = sem_index[i]; + + assert(sizeof(quad->output.color[cbuf]) == + sizeof(machine->Outputs[i])); + + /* copy float[4][4] result */ memcpy(quad->output.color[cbuf], - &machine->Outputs[i].xyzw[0].f[0], + &machine->Outputs[i], sizeof(quad->output.color[0]) ); } break; diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index acee2136706..daa158df7c4 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -156,8 +156,13 @@ fs_sse_run( const struct sp_fragment_shader *base, case TGSI_SEMANTIC_COLOR: { uint cbuf = sem_index[i]; + + assert(sizeof(quad->output.color[cbuf]) == + sizeof(machine->Outputs[i])); + + /* copy float[4][4] result */ memcpy(quad->output.color[cbuf], - &machine->Outputs[i].xyzw[0].f[0], + &machine->Outputs[i], sizeof(quad->output.color[0]) ); } break; diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index 98c08eaffaf..6749243ab41 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -264,57 +264,29 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_QUADS: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-3], stride), get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - } } break; case PIPE_PRIM_QUAD_STRIP: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride)); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-3], stride), get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-3], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - } } break; @@ -448,56 +420,28 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_QUADS: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-3, stride), get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); - } } break; case PIPE_PRIM_QUAD_STRIP: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-3, stride), get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-3, stride), get_vert(vertex_buffer, i-0, stride) ); - } } break; diff --git a/src/gallium/drivers/softpipe/sp_public.h b/src/gallium/drivers/softpipe/sp_public.h new file mode 100644 index 00000000000..62d0903d87a --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_public.h @@ -0,0 +1,10 @@ +#ifndef SP_PUBLIC_H +#define SP_PUBLIC_H + +struct pipe_screen; +struct sw_winsys; + +struct pipe_screen * +softpipe_create_screen(struct sw_winsys *winsys); + +#endif diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 6ec63fe698a..757dc861284 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -27,15 +27,17 @@ #include "util/u_memory.h" -#include "util/u_simple_screen.h" -#include "util/u_simple_screen.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" +#include "state_tracker/sw_winsys.h" + #include "sp_texture.h" -#include "sp_winsys.h" #include "sp_screen.h" #include "sp_context.h" +#include "sp_buffer.h" +#include "sp_fence.h" +#include "sp_public.h" static const char * @@ -83,11 +85,11 @@ softpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 13; /* max 4Kx4K */ + return SP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 9; /* max 256x256x256 */ + return SP_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 13; /* max 4Kx4K */ + return SP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_CONT_SUPPORTED: return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: @@ -145,6 +147,8 @@ softpipe_is_format_supported( struct pipe_screen *screen, unsigned tex_usage, unsigned geom_flags ) { + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + assert(target == PIPE_TEXTURE_1D || target == PIPE_TEXTURE_2D || target == PIPE_TEXTURE_3D || @@ -166,15 +170,27 @@ softpipe_is_format_supported( struct pipe_screen *screen, case PIPE_FORMAT_NONE: return FALSE; default: - return TRUE; + break; } + + if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) + return FALSE; + } + + /* XXX: this is often a lie. Pull in logic from llvmpipe to fix. + */ + return TRUE; } static void softpipe_destroy_screen( struct pipe_screen *screen ) { - struct pipe_winsys *winsys = screen->winsys; + struct softpipe_screen *sp_screen = softpipe_screen(screen); + struct sw_winsys *winsys = sp_screen->winsys; if(winsys->destroy) winsys->destroy(winsys); @@ -183,21 +199,37 @@ softpipe_destroy_screen( struct pipe_screen *screen ) } +/* This is often overriden by the co-state tracker. + */ +static void +softpipe_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *surface, + void *context_private) +{ + struct softpipe_screen *screen = softpipe_screen(_screen); + struct sw_winsys *winsys = screen->winsys; + struct softpipe_texture *texture = softpipe_texture(surface->texture); + + assert(texture->dt); + if (texture->dt) + winsys->displaytarget_display(winsys, texture->dt, context_private); +} /** * Create a new pipe_screen object * Note: we're not presently subclassing pipe_screen (no softpipe_screen). */ struct pipe_screen * -softpipe_create_screen(struct pipe_winsys *winsys) +softpipe_create_screen(struct sw_winsys *winsys) { struct softpipe_screen *screen = CALLOC_STRUCT(softpipe_screen); if (!screen) return NULL; - screen->base.winsys = winsys; + screen->winsys = winsys; + screen->base.winsys = NULL; screen->base.destroy = softpipe_destroy_screen; screen->base.get_name = softpipe_get_name; @@ -206,9 +238,11 @@ softpipe_create_screen(struct pipe_winsys *winsys) screen->base.get_paramf = softpipe_get_paramf; screen->base.is_format_supported = softpipe_is_format_supported; screen->base.context_create = softpipe_create_context; + screen->base.flush_frontbuffer = softpipe_flush_frontbuffer; softpipe_init_screen_texture_funcs(&screen->base); - u_simple_screen_init(&screen->base); + softpipe_init_screen_buffer_funcs(&screen->base); + softpipe_init_screen_fence_funcs(&screen->base); return &screen->base; } diff --git a/src/gallium/drivers/softpipe/sp_screen.h b/src/gallium/drivers/softpipe/sp_screen.h index 3d4bfd3e840..f741454c9e5 100644 --- a/src/gallium/drivers/softpipe/sp_screen.h +++ b/src/gallium/drivers/softpipe/sp_screen.h @@ -35,10 +35,13 @@ #include "pipe/p_defines.h" +struct sw_winsys; struct softpipe_screen { struct pipe_screen base; + struct sw_winsys *winsys; + /* Increments whenever textures are modified. Contexts can track * this. */ @@ -55,4 +58,5 @@ softpipe_screen( struct pipe_screen *pipe ) } + #endif /* SP_SCREEN_H */ diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 4370bbeaee2..ade96b0fd4c 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -100,6 +100,11 @@ struct sp_geometry_shader { struct draw_geometry_shader *draw_data; }; +struct sp_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; + void * softpipe_create_blend_state(struct pipe_context *, @@ -160,28 +165,39 @@ void *softpipe_create_gs_state(struct pipe_context *, void softpipe_bind_gs_state(struct pipe_context *, void *); void softpipe_delete_gs_state(struct pipe_context *, void *); +void *softpipe_create_vertex_elements_state(struct pipe_context *, + unsigned count, + const struct pipe_vertex_element *); +void softpipe_bind_vertex_elements_state(struct pipe_context *, void *); +void softpipe_delete_vertex_elements_state(struct pipe_context *, void *); + void softpipe_set_polygon_stipple( struct pipe_context *, - const struct pipe_poly_stipple * ); + const struct pipe_poly_stipple * ); void softpipe_set_scissor_state( struct pipe_context *, const struct pipe_scissor_state * ); -void softpipe_set_sampler_textures( struct pipe_context *, - unsigned num, - struct pipe_texture ** ); +void softpipe_set_sampler_views( struct pipe_context *, + unsigned num, + struct pipe_sampler_view ** ); void -softpipe_set_vertex_sampler_textures(struct pipe_context *, - unsigned num_textures, - struct pipe_texture **); +softpipe_set_vertex_sampler_views(struct pipe_context *, + unsigned num, + struct pipe_sampler_view **); + +struct pipe_sampler_view * +softpipe_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ); + +void +softpipe_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view); void softpipe_set_viewport_state( struct pipe_context *, const struct pipe_viewport_state * ); -void softpipe_set_vertex_elements(struct pipe_context *, - unsigned count, - const struct pipe_vertex_element *); - void softpipe_set_vertex_buffers(struct pipe_context *, unsigned count, const struct pipe_vertex_buffer *); diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index c88e2137510..2b089c28316 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -28,6 +28,7 @@ #include "sp_context.h" #include "sp_state.h" #include "sp_fs.h" +#include "sp_buffer.h" #include "pipe/p_defines.h" #include "util/u_memory.h" @@ -163,26 +164,33 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) FREE( state ); } - - void softpipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_buffer *constants) { struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned size = constants ? constants->size : 0; + const void *data = constants ? softpipe_buffer(constants)->data : NULL; assert(shader < PIPE_SHADER_TYPES); - assert(index < PIPE_MAX_CONSTANT_BUFFERS); + assert(index == 0); draw_flush(softpipe->draw); /* note: reference counting */ - pipe_buffer_reference(&softpipe->constants[shader][index], buf); + pipe_buffer_reference(&softpipe->constants[shader][index], constants); + if(shader == PIPE_SHADER_VERTEX) { + draw_set_mapped_constant_buffer(softpipe->draw, PIPE_SHADER_VERTEX, index, + data, size); + } + + softpipe->mapped_constants[shader][index] = data; softpipe->dirty |= SP_NEW_CONSTANTS; } + void * softpipe_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index ceb4e338f1a..d501952bba9 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -121,9 +121,38 @@ softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, } +struct pipe_sampler_view * +softpipe_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + void -softpipe_set_sampler_textures(struct pipe_context *pipe, - unsigned num, struct pipe_texture **texture) +softpipe_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + + +void +softpipe_set_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct softpipe_context *softpipe = softpipe_context(pipe); uint i; @@ -131,51 +160,51 @@ softpipe_set_sampler_textures(struct pipe_context *pipe, assert(num <= PIPE_MAX_SAMPLERS); /* Check for no-op */ - if (num == softpipe->num_textures && - !memcmp(softpipe->texture, texture, num * sizeof(struct pipe_texture *))) + if (num == softpipe->num_sampler_views && + !memcmp(softpipe->sampler_views, views, num * sizeof(struct pipe_sampler_view *))) return; draw_flush(softpipe->draw); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - struct pipe_texture *tex = i < num ? texture[i] : NULL; + struct pipe_sampler_view *view = i < num ? views[i] : NULL; - pipe_texture_reference(&softpipe->texture[i], tex); - sp_tex_tile_cache_set_texture(softpipe->tex_cache[i], tex); + pipe_sampler_view_reference(&softpipe->sampler_views[i], view); + sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[i], view); } - softpipe->num_textures = num; + softpipe->num_sampler_views = num; softpipe->dirty |= SP_NEW_TEXTURE; } void -softpipe_set_vertex_sampler_textures(struct pipe_context *pipe, - unsigned num_textures, - struct pipe_texture **textures) +softpipe_set_vertex_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct softpipe_context *softpipe = softpipe_context(pipe); uint i; - assert(num_textures <= PIPE_MAX_VERTEX_SAMPLERS); + assert(num <= PIPE_MAX_VERTEX_SAMPLERS); /* Check for no-op */ - if (num_textures == softpipe->num_vertex_textures && - !memcmp(softpipe->vertex_textures, textures, num_textures * sizeof(struct pipe_texture *))) { + if (num == softpipe->num_vertex_sampler_views && + !memcmp(softpipe->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) { return; } draw_flush(softpipe->draw); for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - struct pipe_texture *tex = i < num_textures ? textures[i] : NULL; + struct pipe_sampler_view *view = i < num ? views[i] : NULL; - pipe_texture_reference(&softpipe->vertex_textures[i], tex); - sp_tex_tile_cache_set_texture(softpipe->vertex_tex_cache[i], tex); + pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], view); + sp_tex_tile_cache_set_sampler_view(softpipe->vertex_tex_cache[i], view); } - softpipe->num_vertex_textures = num_textures; + softpipe->num_vertex_sampler_views = num; softpipe->dirty |= SP_NEW_TEXTURE; } @@ -245,29 +274,41 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) */ for (i = 0; i <= softpipe->vs->max_sampler; i++) { if (softpipe->vertex_samplers[i]) { + struct pipe_texture *texture = NULL; + + if (softpipe->vertex_sampler_views[i]) { + texture = softpipe->vertex_sampler_views[i]->texture; + } + softpipe->tgsi.vert_samplers_list[i] = get_sampler_varient( i, - sp_sampler(softpipe->vertex_samplers[i]), - softpipe->vertex_textures[i], + sp_sampler(softpipe->vertex_samplers[i]), + texture, TGSI_PROCESSOR_VERTEX ); sp_sampler_varient_bind_texture( softpipe->tgsi.vert_samplers_list[i], - softpipe->vertex_tex_cache[i], - softpipe->vertex_textures[i] ); + softpipe->vertex_tex_cache[i], + texture ); } } for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) { if (softpipe->sampler[i]) { + struct pipe_texture *texture = NULL; + + if (softpipe->sampler_views[i]) { + texture = softpipe->sampler_views[i]->texture; + } + softpipe->tgsi.frag_samplers_list[i] = get_sampler_varient( i, sp_sampler(softpipe->sampler[i]), - softpipe->texture[i], + texture, TGSI_PROCESSOR_FRAGMENT ); sp_sampler_varient_bind_texture( softpipe->tgsi.frag_samplers_list[i], softpipe->tex_cache[i], - softpipe->texture[i] ); + texture ); } } } diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index b491d92ed15..462f4d2655e 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -32,27 +32,45 @@ #include "sp_context.h" #include "sp_state.h" +#include "util/u_memory.h" #include "draw/draw_context.h" +void * +softpipe_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) +{ + struct sp_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct sp_velems_state *) MALLOC(sizeof(struct sp_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + void -softpipe_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *attribs) +softpipe_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) { struct softpipe_context *softpipe = softpipe_context(pipe); + struct sp_velems_state *sp_velems = (struct sp_velems_state *) velems; - assert(count <= PIPE_MAX_ATTRIBS); - - memcpy(softpipe->vertex_element, attribs, - count * sizeof(struct pipe_vertex_element)); - softpipe->num_vertex_elements = count; + softpipe->velems = sp_velems; softpipe->dirty |= SP_NEW_VERTEX; - draw_set_vertex_elements(softpipe->draw, count, attribs); + if (sp_velems) + draw_set_vertex_elements(softpipe->draw, sp_velems->count, sp_velems->velem); } +void +softpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} void softpipe_set_vertex_buffers(struct pipe_context *pipe, diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index ef7ccf41898..fa9e19b282b 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -1614,7 +1614,6 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); unsigned j; float ssss[4], tttt[4]; - unsigned face; /* major axis @@ -1628,7 +1627,8 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz */ - /* First choose the cube face. + /* Choose the cube face and compute new s/t coords for the 2D face. + * * Use the same cube face for all four pixels in the quad. * * This isn't ideal, but if we want to use a different cube face @@ -1647,85 +1647,37 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); if (arx >= ary && arx >= arz) { - if (rx >= 0.0F) { - face = PIPE_TEX_FACE_POS_X; - } - else { - face = PIPE_TEX_FACE_NEG_X; + float sign = (rx >= 0.0F) ? 1.0F : -1.0F; + uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X; + for (j = 0; j < QUAD_SIZE; j++) { + const float ima = -0.5F / fabsf(s[j]); + ssss[j] = sign * p[j] * ima + 0.5F; + tttt[j] = t[j] * ima + 0.5F; + samp->faces[j] = face; } } else if (ary >= arx && ary >= arz) { - if (ry >= 0.0F) { - face = PIPE_TEX_FACE_POS_Y; - } - else { - face = PIPE_TEX_FACE_NEG_Y; + float sign = (ry >= 0.0F) ? 1.0F : -1.0F; + uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y; + for (j = 0; j < QUAD_SIZE; j++) { + const float ima = -0.5F / fabsf(t[j]); + ssss[j] = -s[j] * ima + 0.5F; + tttt[j] = sign * -p[j] * ima + 0.5F; + samp->faces[j] = face; } } else { - if (rz > 0.0F) { - face = PIPE_TEX_FACE_POS_Z; - } - else { - face = PIPE_TEX_FACE_NEG_Z; + float sign = (rz >= 0.0F) ? 1.0F : -1.0F; + uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z; + for (j = 0; j < QUAD_SIZE; j++) { + const float ima = -0.5 / fabsf(p[j]); + ssss[j] = sign * -s[j] * ima + 0.5F; + tttt[j] = t[j] * ima + 0.5F; + samp->faces[j] = face; } } } - /* Now compute the 2D _face_ texture coords from the - * 3D _cube_ texture coords. - */ - for (j = 0; j < QUAD_SIZE; j++) { - const float rx = s[j], ry = t[j], rz = p[j]; - const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); - float sc, tc, ma; - - switch (face) { - case PIPE_TEX_FACE_POS_X: - sc = -rz; - tc = -ry; - ma = arx; - break; - case PIPE_TEX_FACE_NEG_X: - sc = rz; - tc = -ry; - ma = arx; - break; - case PIPE_TEX_FACE_POS_Y: - sc = rx; - tc = rz; - ma = ary; - break; - case PIPE_TEX_FACE_NEG_Y: - sc = rx; - tc = -rz; - ma = ary; - break; - case PIPE_TEX_FACE_POS_Z: - sc = rx; - tc = -ry; - ma = arz; - break; - case PIPE_TEX_FACE_NEG_Z: - sc = -rx; - tc = -ry; - ma = arz; - break; - default: - assert(0 && "bad cube face"); - sc = 0.0F; - tc = 0.0F; - ma = 0.0F; - } - - { - const float ima = 1.0 / ma; - ssss[j] = ( sc * ima + 1.0F ) * 0.5F; - tttt[j] = ( tc * ima + 1.0F ) * 0.5F; - samp->faces[j] = face; - } - } - /* In our little pipeline, the compare stage is next. If compare * is not active, this will point somewhere deeper into the * pipeline, eg. to mip_filter or even img_filter. diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index a0b95c88846..6594514c38f 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -43,14 +43,14 @@ struct softpipe_tex_tile_cache * -sp_create_tex_tile_cache( struct pipe_screen *screen ) +sp_create_tex_tile_cache( struct pipe_context *pipe ) { struct softpipe_tex_tile_cache *tc; uint pos; tc = CALLOC_STRUCT( softpipe_tex_tile_cache ); if (tc) { - tc->screen = screen; + tc->pipe = pipe; for (pos = 0; pos < NUM_ENTRIES; pos++) { tc->entries[pos].addr.bits.invalid = 1; } @@ -63,19 +63,16 @@ sp_create_tex_tile_cache( struct pipe_screen *screen ) void sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc) { - struct pipe_screen *screen; uint pos; for (pos = 0; pos < NUM_ENTRIES; pos++) { /*assert(tc->entries[pos].x < 0);*/ } if (tc->transfer) { - screen = tc->transfer->texture->screen; - screen->tex_transfer_destroy(tc->transfer); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->transfer); } if (tc->tex_trans) { - screen = tc->tex_trans->texture->screen; - screen->tex_transfer_destroy(tc->tex_trans); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->tex_trans); } FREE( tc ); @@ -88,7 +85,7 @@ void sp_tex_tile_cache_map_transfers(struct softpipe_tex_tile_cache *tc) { if (tc->tex_trans && !tc->tex_trans_map) - tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans); + tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans); } @@ -96,7 +93,7 @@ void sp_tex_tile_cache_unmap_transfers(struct softpipe_tex_tile_cache *tc) { if (tc->tex_trans_map) { - tc->screen->transfer_unmap(tc->screen, tc->tex_trans); + tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans); tc->tex_trans_map = NULL; } } @@ -119,12 +116,13 @@ sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc) } /** - * Specify the texture to cache. + * Specify the sampler view to cache. */ void -sp_tex_tile_cache_set_texture(struct softpipe_tex_tile_cache *tc, - struct pipe_texture *texture) +sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc, + struct pipe_sampler_view *view) { + struct pipe_texture *texture = view ? view->texture : NULL; uint i; assert(!tc->transfer); @@ -133,17 +131,23 @@ sp_tex_tile_cache_set_texture(struct softpipe_tex_tile_cache *tc, pipe_texture_reference(&tc->texture, texture); if (tc->tex_trans) { - struct pipe_screen *screen = tc->tex_trans->texture->screen; - if (tc->tex_trans_map) { - screen->transfer_unmap(screen, tc->tex_trans); + tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans); tc->tex_trans_map = NULL; } - screen->tex_transfer_destroy(tc->tex_trans); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->tex_trans); tc->tex_trans = NULL; } + if (view) { + tc->swizzle_r = view->swizzle_r; + tc->swizzle_g = view->swizzle_g; + tc->swizzle_b = view->swizzle_b; + tc->swizzle_a = view->swizzle_a; + tc->format = view->format; + } + /* mark as entries as invalid/empty */ /* XXX we should try to avoid this when the teximage hasn't changed */ for (i = 0; i < NUM_ENTRIES; i++) { @@ -204,7 +208,6 @@ const struct softpipe_tex_cached_tile * sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, union tex_tile_address addr ) { - struct pipe_screen *screen = tc->screen; struct softpipe_tex_cached_tile *tile; tile = tc->entries + tex_cache_pos( addr ); @@ -232,16 +235,16 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, if (tc->tex_trans) { if (tc->tex_trans_map) { - tc->screen->transfer_unmap(tc->screen, tc->tex_trans); + tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans); tc->tex_trans_map = NULL; } - screen->tex_transfer_destroy(tc->tex_trans); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->tex_trans); tc->tex_trans = NULL; } tc->tex_trans = - screen->get_tex_transfer(screen, tc->texture, + tc->pipe->get_tex_transfer(tc->pipe, tc->texture, addr.bits.face, addr.bits.level, addr.bits.z, @@ -249,7 +252,7 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, u_minify(tc->texture->width0, addr.bits.level), u_minify(tc->texture->height0, addr.bits.level)); - tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans); + tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans); tc->tex_face = addr.bits.face; tc->tex_level = addr.bits.level; @@ -257,11 +260,18 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, } /* get tile from the transfer (view into texture) */ - pipe_get_tile_rgba(tc->tex_trans, - addr.bits.x * TILE_SIZE, - addr.bits.y * TILE_SIZE, - TILE_SIZE, TILE_SIZE, - (float *) tile->data.color); + pipe_get_tile_swizzle(tc->pipe, + tc->tex_trans, + addr.bits.x * TILE_SIZE, + addr.bits.y * TILE_SIZE, + TILE_SIZE, + TILE_SIZE, + tc->swizzle_r, + tc->swizzle_g, + tc->swizzle_b, + tc->swizzle_a, + tc->format, + (float *) tile->data.color); tile->addr = addr; } diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h index ac6886a3df1..12ae7ba12d6 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h @@ -70,7 +70,7 @@ struct softpipe_tex_cached_tile struct softpipe_tex_tile_cache { - struct pipe_screen *screen; + struct pipe_context *pipe; struct pipe_transfer *transfer; void *transfer_map; @@ -83,12 +83,18 @@ struct softpipe_tex_tile_cache void *tex_trans_map; int tex_face, tex_level, tex_z; + unsigned swizzle_r; + unsigned swizzle_g; + unsigned swizzle_b; + unsigned swizzle_a; + unsigned format; + struct softpipe_tex_cached_tile *last_tile; /**< most recently retrieved tile */ }; extern struct softpipe_tex_tile_cache * -sp_create_tex_tile_cache( struct pipe_screen *screen ); +sp_create_tex_tile_cache( struct pipe_context *pipe ); extern void sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc); @@ -101,8 +107,8 @@ extern void sp_tex_tile_cache_unmap_transfers(struct softpipe_tex_tile_cache *tc); extern void -sp_tex_tile_cache_set_texture(struct softpipe_tex_tile_cache *tc, - struct pipe_texture *texture); +sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc, + struct pipe_sampler_view *view); void sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc); diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 32d261b5ffc..f4983b7c8e8 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -40,7 +40,8 @@ #include "sp_context.h" #include "sp_texture.h" #include "sp_screen.h" -#include "sp_winsys.h" + +#include "state_tracker/sw_winsys.h" /** @@ -72,11 +73,9 @@ softpipe_texture_layout(struct pipe_screen *screen, depth = u_minify(depth, 1); } - spt->buffer = screen->buffer_create(screen, 32, - PIPE_BUFFER_USAGE_PIXEL, - buffer_size); + spt->data = align_malloc(buffer_size, 16); - return spt->buffer != NULL; + return spt->data != NULL; } @@ -87,19 +86,19 @@ static boolean softpipe_displaytarget_layout(struct pipe_screen *screen, struct softpipe_texture * spt) { - unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE | - PIPE_BUFFER_USAGE_GPU_READ_WRITE); - unsigned tex_usage = spt->base.tex_usage; - - spt->buffer = screen->surface_buffer_create( screen, - spt->base.width0, - spt->base.height0, - spt->base.format, - usage, - tex_usage, - &spt->stride[0]); - - return spt->buffer != NULL; + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + + /* Round up the surface size to a multiple of the tile size? + */ + spt->dt = winsys->displaytarget_create(winsys, + spt->base.tex_usage, + spt->base.format, + spt->base.width0, + spt->base.height0, + 16, + &spt->stride[0] ); + + return spt->dt != NULL; } @@ -123,7 +122,8 @@ softpipe_texture_create(struct pipe_screen *screen, util_is_power_of_two(template->depth0)); if (spt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) { + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { if (!softpipe_displaytarget_layout(screen, spt)) goto fail; } @@ -140,47 +140,72 @@ softpipe_texture_create(struct pipe_screen *screen, } -/** - * Create a new pipe_texture which wraps an existing buffer. - */ -static struct pipe_texture * -softpipe_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) +static void +softpipe_texture_destroy(struct pipe_texture *pt) { - struct softpipe_texture *spt; - assert(screen); + struct softpipe_screen *screen = softpipe_screen(pt->screen); + struct softpipe_texture *spt = softpipe_texture(pt); - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = screen->winsys; + winsys->displaytarget_destroy(winsys, spt->dt); + } + else { + /* regular texture */ + align_free(spt->data); } - spt = CALLOC_STRUCT(softpipe_texture); + FREE(spt); +} + + +static struct pipe_texture * +softpipe_texture_from_handle(struct pipe_screen *screen, + const struct pipe_texture *template, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture); if (!spt) return NULL; - spt->base = *base; + spt->base = *template; pipe_reference_init(&spt->base.reference, 1); spt->base.screen = screen; - spt->stride[0] = stride[0]; - pipe_buffer_reference(&spt->buffer, buffer); + spt->pot = (util_is_power_of_two(template->width0) && + util_is_power_of_two(template->height0) && + util_is_power_of_two(template->depth0)); + + spt->dt = winsys->displaytarget_from_handle(winsys, + template, + whandle, + &spt->stride[0]); + if (!spt->dt) + goto fail; return &spt->base; + + fail: + FREE(spt); + return NULL; } -static void -softpipe_texture_destroy(struct pipe_texture *pt) +static boolean +softpipe_texture_get_handle(struct pipe_screen *screen, + struct pipe_texture *pt, + struct winsys_handle *whandle) { + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; struct softpipe_texture *spt = softpipe_texture(pt); - pipe_buffer_reference(&spt->buffer, NULL); - FREE(spt); + assert(spt->dt); + if (!spt->dt) + return FALSE; + + return winsys->displaytarget_get_handle(winsys, spt->dt, whandle); } @@ -278,7 +303,7 @@ softpipe_tex_surface_destroy(struct pipe_surface *surf) * \param height height of region to read/write */ static struct pipe_transfer * -softpipe_get_tex_transfer(struct pipe_screen *screen, +softpipe_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, @@ -332,7 +357,8 @@ softpipe_get_tex_transfer(struct pipe_screen *screen, * softpipe_get_tex_transfer(). */ static void -softpipe_tex_transfer_destroy(struct pipe_transfer *transfer) +softpipe_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) { /* Effectively do the texture_update work here - if texture images * needed post-processing to put them into hardware layout, this is @@ -348,7 +374,7 @@ softpipe_tex_transfer_destroy(struct pipe_transfer *transfer) * Create memory mapping for given pipe_transfer object. */ static void * -softpipe_transfer_map( struct pipe_screen *screen, +softpipe_transfer_map( struct pipe_context *pipe, struct pipe_transfer *transfer ) { ubyte *map, *xfer_map; @@ -359,9 +385,20 @@ softpipe_transfer_map( struct pipe_screen *screen, spt = softpipe_texture(transfer->texture); format = transfer->texture->format; - map = pipe_buffer_map(screen, spt->buffer, pipe_transfer_buffer_flags(transfer)); - if (map == NULL) - return NULL; + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; + + map = winsys->displaytarget_map(winsys, spt->dt, + pipe_transfer_buffer_flags(transfer)); + if (map == NULL) + return NULL; + } + else { + map = spt->data; + if (map == NULL) + return NULL; + } /* May want to different things here depending on read/write nature * of the map: @@ -370,7 +407,7 @@ softpipe_transfer_map( struct pipe_screen *screen, /* Do something to notify sharing contexts of a texture change. * In softpipe, that would mean flushing the texture cache. */ - softpipe_screen(screen)->timestamp++; + softpipe_screen(pipe->screen)->timestamp++; } xfer_map = map + softpipe_transfer(transfer)->offset + @@ -385,7 +422,7 @@ softpipe_transfer_map( struct pipe_screen *screen, * Unmap memory mapping for given pipe_transfer object. */ static void -softpipe_transfer_unmap(struct pipe_screen *screen, +softpipe_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct softpipe_texture *spt; @@ -393,7 +430,11 @@ softpipe_transfer_unmap(struct pipe_screen *screen, assert(transfer->texture); spt = softpipe_texture(transfer->texture); - pipe_buffer_unmap( screen, spt->buffer ); + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; + winsys->displaytarget_unmap(winsys, spt->dt); + } if (transfer->usage & PIPE_TRANSFER_WRITE) { /* Mark the texture as dirty to expire the tile caches. */ @@ -455,43 +496,28 @@ softpipe_video_surface_destroy(struct pipe_video_surface *vsfc) void +softpipe_init_texture_funcs(struct pipe_context *pipe) +{ + pipe->get_tex_transfer = softpipe_get_tex_transfer; + pipe->tex_transfer_destroy = softpipe_tex_transfer_destroy; + pipe->transfer_map = softpipe_transfer_map; + pipe->transfer_unmap = softpipe_transfer_unmap; +} + +void softpipe_init_screen_texture_funcs(struct pipe_screen *screen) { screen->texture_create = softpipe_texture_create; - screen->texture_blanket = softpipe_texture_blanket; screen->texture_destroy = softpipe_texture_destroy; + screen->texture_from_handle = softpipe_texture_from_handle; + screen->texture_get_handle = softpipe_texture_get_handle; screen->get_tex_surface = softpipe_get_tex_surface; screen->tex_surface_destroy = softpipe_tex_surface_destroy; - screen->get_tex_transfer = softpipe_get_tex_transfer; - screen->tex_transfer_destroy = softpipe_tex_transfer_destroy; - screen->transfer_map = softpipe_transfer_map; - screen->transfer_unmap = softpipe_transfer_unmap; - screen->video_surface_create = softpipe_video_surface_create; screen->video_surface_destroy = softpipe_video_surface_destroy; } -/** - * Return pipe_buffer handle and stride for given texture object. - * XXX used for??? - */ -boolean -softpipe_get_texture_buffer( struct pipe_texture *texture, - struct pipe_buffer **buf, - unsigned *stride ) -{ - struct softpipe_texture *tex = (struct softpipe_texture *) texture; - - if (!tex) - return FALSE; - pipe_buffer_reference(buf, tex->buffer); - - if (stride) - *stride = tex->stride[0]; - - return TRUE; -} diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 2ef64e1e7c3..c0e6ba8a869 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -33,6 +33,10 @@ #include "pipe/p_video_state.h" +#define SP_MAX_TEXTURE_2D_LEVELS 13 /* 4K x 4K */ +#define SP_MAX_TEXTURE_3D_LEVELS 9 /* 512 x 512 x 512 */ + + struct pipe_context; struct pipe_screen; struct softpipe_context; @@ -42,12 +46,19 @@ struct softpipe_texture { struct pipe_texture base; - unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS]; - unsigned stride[PIPE_MAX_TEXTURE_LEVELS]; + unsigned long level_offset[SP_MAX_TEXTURE_2D_LEVELS]; + unsigned stride[SP_MAX_TEXTURE_2D_LEVELS]; - /* The data is held here: + /** + * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET + * usage. */ - struct pipe_buffer *buffer; + struct sw_displaytarget *dt; + + /** + * Malloc'ed data for regular textures, or a mapping to dt above. + */ + void *data; /* True if texture images are power-of-two in all dimensions: */ @@ -96,5 +107,8 @@ softpipe_video_surface(struct pipe_video_surface *pvs) extern void softpipe_init_screen_texture_funcs(struct pipe_screen *screen); +void +softpipe_init_texture_funcs(struct pipe_context *pipe); + #endif /* SP_TEXTURE */ diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index aedfdf1b469..1c3c2667d73 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -79,20 +79,20 @@ clear_clear_flag(uint *bitvec, union tile_address addr) struct softpipe_tile_cache * -sp_create_tile_cache( struct pipe_screen *screen ) +sp_create_tile_cache( struct pipe_context *pipe ) { struct softpipe_tile_cache *tc; uint pos; int maxLevels, maxTexSize; /* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */ - maxLevels = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); + maxLevels = pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); maxTexSize = 1 << (maxLevels - 1); assert(MAX_WIDTH >= maxTexSize); tc = CALLOC_STRUCT( softpipe_tile_cache ); if (tc) { - tc->screen = screen; + tc->pipe = pipe; for (pos = 0; pos < NUM_ENTRIES; pos++) { tc->entries[pos].addr.bits.invalid = 1; } @@ -115,15 +115,13 @@ sp_create_tile_cache( struct pipe_screen *screen ) void sp_destroy_tile_cache(struct softpipe_tile_cache *tc) { - struct pipe_screen *screen; uint pos; for (pos = 0; pos < NUM_ENTRIES; pos++) { /*assert(tc->entries[pos].x < 0);*/ } if (tc->transfer) { - screen = tc->transfer->texture->screen; - screen->tex_transfer_destroy(tc->transfer); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->transfer); } FREE( tc ); @@ -137,27 +135,25 @@ void sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, struct pipe_surface *ps) { - if (tc->transfer) { - struct pipe_screen *screen = tc->transfer->texture->screen; + struct pipe_context *pipe = tc->pipe; + if (tc->transfer) { if (ps == tc->surface) return; if (tc->transfer_map) { - screen->transfer_unmap(screen, tc->transfer); + pipe->transfer_unmap(pipe, tc->transfer); tc->transfer_map = NULL; } - screen->tex_transfer_destroy(tc->transfer); + pipe->tex_transfer_destroy(pipe, tc->transfer); tc->transfer = NULL; } tc->surface = ps; if (ps) { - struct pipe_screen *screen = ps->texture->screen; - - tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face, + tc->transfer = pipe->get_tex_transfer(pipe, ps->texture, ps->face, ps->level, ps->zslice, PIPE_TRANSFER_READ_WRITE, 0, 0, ps->width, ps->height); @@ -187,7 +183,7 @@ void sp_tile_cache_map_transfers(struct softpipe_tile_cache *tc) { if (tc->transfer && !tc->transfer_map) - tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer); + tc->transfer_map = tc->pipe->transfer_map(tc->pipe, tc->transfer); } @@ -195,7 +191,7 @@ void sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc) { if (tc->transfer_map) { - tc->screen->transfer_unmap(tc->screen, tc->transfer); + tc->pipe->transfer_unmap(tc->pipe, tc->transfer); tc->transfer_map = NULL; } } @@ -295,7 +291,8 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) union tile_address addr = tile_address(x, y); if (is_clear_flag_set(tc->clear_flags, addr)) { - pipe_put_tile_raw(pt, + pipe_put_tile_raw(tc->pipe, + pt, x, y, TILE_SIZE, TILE_SIZE, tc->tile.data.color32, 0/*STRIDE*/); @@ -329,14 +326,14 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) struct softpipe_cached_tile *tile = tc->entries + pos; if (!tile->addr.bits.invalid) { if (tc->depth_stencil) { - pipe_put_tile_raw(pt, + pipe_put_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { - pipe_put_tile_rgba(pt, + pipe_put_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -379,14 +376,14 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, if (tile->addr.bits.invalid == 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { - pipe_put_tile_raw(pt, + pipe_put_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { - pipe_put_tile_rgba(pt, + pipe_put_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -409,14 +406,14 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, else { /* get new tile data from transfer */ if (tc->depth_stencil) { - pipe_get_tile_raw(pt, + pipe_get_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { - pipe_get_tile_rgba(pt, + pipe_get_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index a12092702a6..753d8c0daac 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -80,7 +80,7 @@ struct softpipe_cached_tile struct softpipe_tile_cache { - struct pipe_screen *screen; + struct pipe_context *pipe; struct pipe_surface *surface; /**< the surface we're caching */ struct pipe_transfer *transfer; void *transfer_map; @@ -98,7 +98,7 @@ struct softpipe_tile_cache extern struct softpipe_tile_cache * -sp_create_tile_cache( struct pipe_screen *screen ); +sp_create_tile_cache( struct pipe_context *pipe ); extern void sp_destroy_tile_cache(struct softpipe_tile_cache *tc); diff --git a/src/gallium/drivers/softpipe/sp_winsys.c b/src/gallium/drivers/softpipe/sp_winsys.c deleted file mode 100644 index 0a6245ed2cd..00000000000 --- a/src/gallium/drivers/softpipe/sp_winsys.c +++ /dev/null @@ -1,245 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/** - * @file - * Malloc softpipe winsys. Uses malloc for all memory allocations. - * - * @author Keith Whitwell - * @author Brian Paul - * @author Jose Fonseca - */ - - -#include "util/u_simple_screen.h"/* port to just p_screen */ -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "sp_winsys.h" - - -struct st_softpipe_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; -}; - - -/** Cast wrapper */ -static INLINE struct st_softpipe_buffer * -st_softpipe_buffer( struct pipe_buffer *buf ) -{ - return (struct st_softpipe_buffer *)buf; -} - - -static void * -st_softpipe_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = st_softpipe_buf->data; - return st_softpipe_buf->mapped; -} - - -static void -st_softpipe_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = NULL; -} - - -static void -st_softpipe_buffer_destroy(struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf); - - if (oldBuf->data) { - if (!oldBuf->userBuffer) - align_free(oldBuf->data); - - oldBuf->data = NULL; - } - - FREE(oldBuf); -} - - -static void -st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys, - struct pipe_surface *surf, - void *context_private) -{ -} - - - -static const char * -st_softpipe_get_name(struct pipe_winsys *winsys) -{ - return "softpipe"; -} - - -static struct pipe_buffer * -st_softpipe_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - buffer->data = align_malloc(size, alignment); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -st_softpipe_user_buffer_create(struct pipe_winsys *winsys, - void *ptr, - unsigned bytes) -{ - struct st_softpipe_buffer *buffer; - - buffer = CALLOC_STRUCT(st_softpipe_buffer); - if(!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -st_softpipe_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -st_softpipe_fence_reference(struct pipe_winsys *winsys, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -st_softpipe_fence_signalled(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -st_softpipe_fence_finish(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static void -st_softpipe_destroy(struct pipe_winsys *winsys) -{ - FREE(winsys); -} - - -struct pipe_screen * -softpipe_create_screen_malloc(void) -{ - static struct pipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(pipe_winsys); - if(!winsys) - return NULL; - - winsys->destroy = st_softpipe_destroy; - - winsys->buffer_create = st_softpipe_buffer_create; - winsys->user_buffer_create = st_softpipe_user_buffer_create; - winsys->buffer_map = st_softpipe_buffer_map; - winsys->buffer_unmap = st_softpipe_buffer_unmap; - winsys->buffer_destroy = st_softpipe_buffer_destroy; - - winsys->surface_buffer_create = st_softpipe_surface_buffer_create; - - winsys->fence_reference = st_softpipe_fence_reference; - winsys->fence_signalled = st_softpipe_fence_signalled; - winsys->fence_finish = st_softpipe_fence_finish; - - winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer; - winsys->get_name = st_softpipe_get_name; - - screen = softpipe_create_screen(winsys); - if(!screen) - st_softpipe_destroy(winsys); - - return screen; -} diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index d499ae6acc9..adb7840182b 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -164,6 +164,8 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen, svga_init_constbuffer_functions(svga); svga_init_query_functions(svga); + svga_init_texture_functions(&svga->pipe); + /* debug */ svga->debug.no_swtnl = debug_get_bool_option("SVGA_NO_SWTNL", FALSE); svga->debug.force_swtnl = debug_get_bool_option("SVGA_FORCE_SWTNL", FALSE); diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 03302e2a6ec..1f66437dfe1 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -169,6 +169,11 @@ struct svga_sampler_state { unsigned view_max_lod; }; +struct svga_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; + /* Use to calculate differences between state emitted to hardware and * current driver-calculated state. */ @@ -178,13 +183,13 @@ struct svga_state const struct svga_depth_stencil_state *depth; const struct svga_rasterizer_state *rast; const struct svga_sampler_state *sampler[PIPE_MAX_SAMPLERS]; + const struct svga_velems_state *velems; - struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; /* or texture ID's? */ + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; /* or texture ID's? */ struct svga_fragment_shader *fs; struct svga_vertex_shader *vs; struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS]; struct pipe_buffer *cb[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; @@ -203,8 +208,7 @@ struct svga_state struct pipe_viewport_state viewport; unsigned num_samplers; - unsigned num_textures; - unsigned num_vertex_elements; + unsigned num_sampler_views; unsigned num_vertex_buffers; unsigned reduced_prim; diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c index acba2b8f9da..82d525ca33f 100644 --- a/src/gallium/drivers/svga/svga_pipe_sampler.c +++ b/src/gallium/drivers/svga/svga_pipe_sampler.c @@ -155,7 +155,7 @@ static void svga_bind_sampler_states(struct pipe_context *pipe, /* Check for no-op */ if (num == svga->curr.num_samplers && !memcmp(svga->curr.sampler, sampler, num * sizeof(void *))) { - debug_printf("sampler noop\n"); + if (0) debug_printf("sampler noop\n"); return; } @@ -176,9 +176,36 @@ static void svga_delete_sampler_state(struct pipe_context *pipe, } -static void svga_set_sampler_textures(struct pipe_context *pipe, - unsigned num, - struct pipe_texture **texture) +static struct pipe_sampler_view * +svga_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +svga_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + +static void svga_set_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct svga_context *svga = svga_context(pipe); unsigned flag_1d = 0; @@ -188,31 +215,31 @@ static void svga_set_sampler_textures(struct pipe_context *pipe, assert(num <= PIPE_MAX_SAMPLERS); /* Check for no-op */ - if (num == svga->curr.num_textures && - !memcmp(svga->curr.texture, texture, num * sizeof(struct pipe_texture *))) { + if (num == svga->curr.num_sampler_views && + !memcmp(svga->curr.sampler_views, views, num * sizeof(struct pipe_sampler_view *))) { if (0) debug_printf("texture noop\n"); return; } for (i = 0; i < num; i++) { - pipe_texture_reference(&svga->curr.texture[i], - texture[i]); + pipe_sampler_view_reference(&svga->curr.sampler_views[i], + views[i]); - if (!texture[i]) + if (!views[i]) continue; - if (texture[i]->format == PIPE_FORMAT_B8G8R8A8_SRGB) + if (views[i]->texture->format == PIPE_FORMAT_B8G8R8A8_SRGB) flag_srgb |= 1 << i; - if (texture[i]->target == PIPE_TEXTURE_1D) + if (views[i]->texture->target == PIPE_TEXTURE_1D) flag_1d |= 1 << i; } - for (i = num; i < svga->curr.num_textures; i++) - pipe_texture_reference(&svga->curr.texture[i], - NULL); + for (i = num; i < svga->curr.num_sampler_views; i++) + pipe_sampler_view_reference(&svga->curr.sampler_views[i], + NULL); - svga->curr.num_textures = num; + svga->curr.num_sampler_views = num; svga->dirty |= SVGA_NEW_TEXTURE_BINDING; if (flag_srgb != svga->curr.tex_flags.flag_srgb || @@ -231,7 +258,9 @@ void svga_init_sampler_functions( struct svga_context *svga ) svga->pipe.create_sampler_state = svga_create_sampler_state; svga->pipe.bind_fragment_sampler_states = svga_bind_sampler_states; svga->pipe.delete_sampler_state = svga_delete_sampler_state; - svga->pipe.set_fragment_sampler_textures = svga_set_sampler_textures; + svga->pipe.set_fragment_sampler_views = svga_set_sampler_views; + svga->pipe.create_sampler_view = svga_create_sampler_view; + svga->pipe.sampler_view_destroy = svga_sampler_view_destroy; } diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 836b8441da2..1715a47fc62 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -26,6 +26,7 @@ #include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" +#include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "svga_screen.h" @@ -64,20 +65,37 @@ static void svga_set_vertex_buffers(struct pipe_context *pipe, svga->dirty |= SVGA_NEW_VBUFFER; } -static void svga_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements) + +static void * +svga_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) { - struct svga_context *svga = svga_context(pipe); - unsigned i; + struct svga_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct svga_velems_state *) MALLOC(sizeof(struct svga_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} - for (i = 0; i < count; i++) - svga->curr.ve[i] = elements[i]; +static void svga_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + struct svga_context *svga = svga_context(pipe); + struct svga_velems_state *svga_velems = (struct svga_velems_state *) velems; - svga->curr.num_vertex_elements = count; + svga->curr.velems = svga_velems; svga->dirty |= SVGA_NEW_VELEMENT; } +static void svga_delete_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + FREE(velems); +} void svga_cleanup_vertex_state( struct svga_context *svga ) { @@ -91,7 +109,9 @@ void svga_cleanup_vertex_state( struct svga_context *svga ) void svga_init_vertex_functions( struct svga_context *svga ) { svga->pipe.set_vertex_buffers = svga_set_vertex_buffers; - svga->pipe.set_vertex_elements = svga_set_vertex_elements; + svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state; + svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state; + svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state; } diff --git a/src/gallium/drivers/svga/svga_screen_texture.c b/src/gallium/drivers/svga/svga_screen_texture.c index e9792e063e0..4a058eda885 100644 --- a/src/gallium/drivers/svga/svga_screen_texture.c +++ b/src/gallium/drivers/svga/svga_screen_texture.c @@ -41,8 +41,6 @@ #include "svga_debug.h" #include "svga_screen_buffer.h" -#include <util/u_string.h> - /* XXX: This isn't a real hardware flag, but just a hack for kernel to * know about primary surfaces. Find a better way to accomplish this. @@ -315,7 +313,11 @@ svga_texture_create(struct pipe_screen *screen, tex->key.cachable = 0; } - if(templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) { + if(templat->tex_usage & PIPE_TEXTURE_USAGE_SHARED) { + tex->key.cachable = 0; + } + + if(templat->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) { tex->key.flags |= SVGA3D_SURFACE_HINT_SCANOUT; tex->key.cachable = 0; } @@ -355,80 +357,18 @@ error1: } -static struct pipe_texture * -svga_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) -{ - struct svga_texture *tex; - struct svga_buffer *sbuf = svga_buffer(buffer); - struct svga_winsys_screen *sws = svga_winsys_screen(screen); - assert(screen); - - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; - } - - /** - * We currently can't do texture blanket on - * SVGA3D_BUFFER. Need to blit to a temporary surface? - */ - - assert(sbuf->handle); - if (!sbuf->handle) - return NULL; - - if (svga_translate_format(base->format) != sbuf->key.format) { - unsigned f1 = svga_translate_format(base->format); - unsigned f2 = sbuf->key.format; - - /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up */ - if ( !( (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) || - (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_X8R8G8B8) || - (f1 == SVGA3D_Z_D24X8 && f2 == SVGA3D_Z_D24S8) ) ) { - debug_printf("%s wrong format %u != %u\n", __FUNCTION__, f1, f2); - return NULL; - } - } - - tex = CALLOC_STRUCT(svga_texture); - if (!tex) - return NULL; - - tex->base = *base; - - - if (sbuf->key.format == 1) - tex->base.format = PIPE_FORMAT_B8G8R8X8_UNORM; - else if (sbuf->key.format == 2) - tex->base.format = PIPE_FORMAT_B8G8R8A8_UNORM; - - pipe_reference_init(&tex->base.reference, 1); - tex->base.screen = screen; - - SVGA_DBG(DEBUG_DMA, "blanket sid %p\n", sbuf->handle); - /* We don't own this storage, so don't try to cache it. - */ - assert(sbuf->key.cachable == 0); - tex->key.cachable = 0; - sws->surface_reference(sws, &tex->handle, sbuf->handle); - return &tex->base; -} - -struct pipe_texture * -svga_screen_texture_wrap_surface(struct pipe_screen *screen, - struct pipe_texture *base, - enum SVGA3dSurfaceFormat format, - struct svga_winsys_surface *srf) +static struct pipe_texture * +svga_screen_texture_from_handle(struct pipe_screen *screen, + const struct pipe_texture *base, + struct winsys_handle *whandle) { + struct svga_winsys_screen *sws = svga_winsys_screen(screen); + struct svga_winsys_surface *srf; struct svga_texture *tex; + enum SVGA3dSurfaceFormat format = 0; assert(screen); /* Only supports one type */ @@ -438,6 +378,8 @@ svga_screen_texture_wrap_surface(struct pipe_screen *screen, return NULL; } + srf = sws->surface_from_handle(sws, whandle, &format); + if (!srf) return NULL; @@ -478,6 +420,22 @@ svga_screen_texture_wrap_surface(struct pipe_screen *screen, } +static boolean +svga_screen_texture_get_handle(struct pipe_screen *screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen); + unsigned stride; + + assert(svga_texture(texture)->key.cachable == 0); + svga_texture(texture)->key.cachable = 0; + stride = util_format_get_nblocksx(texture->format, texture->width0) * + util_format_get_blocksize(texture->format); + return sws->surface_get_handle(sws, svga_texture(texture)->handle, stride, whandle); +} + + static void svga_texture_destroy(struct pipe_texture *pt) { @@ -823,15 +781,17 @@ svga_surface_needs_propagation(struct pipe_surface *surf) return s->dirty && s->handle != tex->handle; } - +/* XXX: Still implementing this as if it was a screen function, but + * can now modify it to queue transfers on the context. + */ static struct pipe_transfer * -svga_get_tex_transfer(struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, unsigned x, unsigned y, - unsigned w, unsigned h) +svga_get_tex_transfer(struct pipe_context *pipe, + struct pipe_texture *texture, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, unsigned x, unsigned y, + unsigned w, unsigned h) { - struct svga_screen *ss = svga_screen(screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st; unsigned nblocksx = util_format_get_nblocksx(texture->format, w); @@ -899,11 +859,14 @@ no_hwbuf: } +/* XXX: Still implementing this as if it was a screen function, but + * can now modify it to queue transfers on the context. + */ static void * -svga_transfer_map( struct pipe_screen *screen, +svga_transfer_map( struct pipe_context *pipe, struct pipe_transfer *transfer ) { - struct svga_screen *ss = svga_screen(screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st = svga_transfer(transfer); @@ -917,11 +880,14 @@ svga_transfer_map( struct pipe_screen *screen, } +/* XXX: Still implementing this as if it was a screen function, but + * can now modify it to queue transfers on the context. + */ static void -svga_transfer_unmap(struct pipe_screen *screen, +svga_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct svga_screen *ss = svga_screen(screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st = svga_transfer(transfer); @@ -931,10 +897,11 @@ svga_transfer_unmap(struct pipe_screen *screen, static void -svga_tex_transfer_destroy(struct pipe_transfer *transfer) +svga_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) { struct svga_texture *tex = svga_texture(transfer->texture); - struct svga_screen *ss = svga_screen(transfer->texture->screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st = svga_transfer(transfer); @@ -951,18 +918,26 @@ svga_tex_transfer_destroy(struct pipe_transfer *transfer) FREE(st); } + +void +svga_init_texture_functions(struct pipe_context *pipe) +{ + pipe->get_tex_transfer = svga_get_tex_transfer; + pipe->transfer_map = svga_transfer_map; + pipe->transfer_unmap = svga_transfer_unmap; + pipe->tex_transfer_destroy = svga_tex_transfer_destroy; +} + + void svga_screen_init_texture_functions(struct pipe_screen *screen) { screen->texture_create = svga_texture_create; + screen->texture_from_handle = svga_screen_texture_from_handle; + screen->texture_get_handle = svga_screen_texture_get_handle; screen->texture_destroy = svga_texture_destroy; screen->get_tex_surface = svga_get_tex_surface; screen->tex_surface_destroy = svga_tex_surface_destroy; - screen->texture_blanket = svga_texture_blanket; - screen->get_tex_transfer = svga_get_tex_transfer; - screen->transfer_map = svga_transfer_map; - screen->transfer_unmap = svga_transfer_unmap; - screen->tex_transfer_destroy = svga_tex_transfer_destroy; } /*********************************************************************** @@ -1120,33 +1095,3 @@ svga_destroy_sampler_view_priv(struct svga_sampler_view *v) pipe_texture_reference(&v->texture, NULL); FREE(v); } - -boolean -svga_screen_buffer_from_texture(struct pipe_texture *texture, - struct pipe_buffer **buffer, - unsigned *stride) -{ - struct svga_texture *stex = svga_texture(texture); - - *buffer = svga_screen_buffer_wrap_surface - (texture->screen, - svga_translate_format(texture->format), - stex->handle); - - *stride = util_format_get_stride(texture->format, texture->width0); - - return *buffer != NULL; -} - - -struct svga_winsys_surface * -svga_screen_texture_get_winsys_surface(struct pipe_texture *texture) -{ - struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen); - struct svga_winsys_surface *vsurf = NULL; - - assert(svga_texture(texture)->key.cachable == 0); - svga_texture(texture)->key.cachable = 0; - sws->surface_reference(sws, &vsurf, svga_texture(texture)->handle); - return vsurf; -} diff --git a/src/gallium/drivers/svga/svga_screen_texture.h b/src/gallium/drivers/svga/svga_screen_texture.h index 24c1f78ca55..96d035b12d8 100644 --- a/src/gallium/drivers/svga/svga_screen_texture.h +++ b/src/gallium/drivers/svga/svga_screen_texture.h @@ -78,7 +78,7 @@ struct svga_texture { struct pipe_texture base; - boolean defined[6][PIPE_MAX_TEXTURE_LEVELS]; + boolean defined[6][SVGA_MAX_TEXTURE_LEVELS]; struct svga_sampler_view *cached_view; @@ -186,6 +186,9 @@ svga_surface_needs_propagation(struct pipe_surface *surf); extern void svga_screen_init_texture_functions(struct pipe_screen *screen); +void +svga_init_texture_functions(struct pipe_context *pipe); + enum SVGA3dSurfaceFormat svga_translate_format(enum pipe_format format); diff --git a/src/gallium/drivers/svga/svga_state_constants.c b/src/gallium/drivers/svga/svga_state_constants.c index bb92f818eae..493f78a9908 100644 --- a/src/gallium/drivers/svga/svga_state_constants.c +++ b/src/gallium/drivers/svga/svga_state_constants.c @@ -137,7 +137,7 @@ static int emit_fs_consts( struct svga_context *svga, for (i = 0; i < key->num_textures; i++) { if (key->tex[i].unnormalized) { - struct pipe_texture *tex = svga->curr.texture[i]; + struct pipe_texture *tex = svga->curr.sampler_views[i]->texture; float data[4]; data[0] = 1.0 / (float)tex->width0; diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index 2973444d0ab..1310fd9825f 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -158,10 +158,11 @@ static int make_fs_key( const struct svga_context *svga, * * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER */ - for (i = 0; i < svga->curr.num_textures; i++) { - if (svga->curr.texture[i]) { + for (i = 0; i < svga->curr.num_sampler_views; i++) { + if (svga->curr.sampler_views[i]) { assert(svga->curr.sampler[i]); - key->tex[i].texture_target = svga->curr.texture[i]->target; + assert(svga->curr.sampler_views[i]->texture); + key->tex[i].texture_target = svga->curr.sampler_views[i]->texture->target; if (!svga->curr.sampler[i]->normalized_coords) { key->tex[i].width_height_idx = idx++; key->tex[i].unnormalized = TRUE; @@ -169,7 +170,7 @@ static int make_fs_key( const struct svga_context *svga, } } } - key->num_textures = svga->curr.num_textures; + key->num_textures = svga->curr.num_sampler_views; idx = 0; for (i = 0; i < svga->curr.num_samplers; ++i) { diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c index d774e3e504d..dfaab53aef4 100644 --- a/src/gallium/drivers/svga/svga_state_need_swtnl.c +++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c @@ -76,8 +76,13 @@ static int update_need_swvfetch( struct svga_context *svga, unsigned i; boolean need_swvfetch = FALSE; - for (i = 0; i < svga->curr.num_vertex_elements; i++) { - svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.ve[i].src_format); + if (!svga->curr.velems) { + /* No vertex elements bound. */ + return 0; + } + + for (i = 0; i < svga->curr.velems->count; i++) { + svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.velems->velem[i].src_format); if (svga->state.sw.ve_format[i] == SVGA3D_DECLTYPE_MAX) { need_swvfetch = TRUE; break; diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c index 107cc403b4d..b7195d246bc 100644 --- a/src/gallium/drivers/svga/svga_state_rss.c +++ b/src/gallium/drivers/svga/svga_state_rss.c @@ -191,15 +191,24 @@ static int emit_rss( struct svga_context *svga, EMIT_RS( svga, svga->curr.stencil_ref.ref_value[0], STENCILREF, fail ); } - if (dirty & SVGA_NEW_RAST) + if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE)) { const struct svga_rasterizer_state *curr = svga->curr.rast; + unsigned cullmode = curr->cullmode; /* Shademode: still need to rearrange index list to move * flat-shading PV first vertex. */ EMIT_RS( svga, curr->shademode, SHADEMODE, fail ); - EMIT_RS( svga, curr->cullmode, CULLMODE, fail ); + + /* Don't do culling while the software pipeline is active. It + * does it for us, and additionally introduces potentially + * back-facing triangles. + */ + if (svga->state.sw.need_pipeline) + cullmode = SVGA3D_FACE_NONE; + + EMIT_RS( svga, cullmode, CULLMODE, fail ); EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail ); EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail ); EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail ); diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c index 17b47859781..c08ec7c2e8c 100644 --- a/src/gallium/drivers/svga/svga_state_tss.c +++ b/src/gallium/drivers/svga/svga_state_tss.c @@ -37,14 +37,14 @@ void svga_cleanup_tss_binding(struct svga_context *svga) { int i; - unsigned count = MAX2( svga->curr.num_textures, + unsigned count = MAX2( svga->curr.num_sampler_views, svga->state.hw_draw.num_views ); for (i = 0; i < count; i++) { struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; svga_sampler_view_reference(&view->v, NULL); - pipe_texture_reference( &svga->curr.texture[i], NULL ); + pipe_sampler_view_reference( &svga->curr.sampler_views[i], NULL ); pipe_texture_reference( &view->texture, NULL ); view->dirty = 1; @@ -57,7 +57,7 @@ update_tss_binding(struct svga_context *svga, unsigned dirty ) { unsigned i; - unsigned count = MAX2( svga->curr.num_textures, + unsigned count = MAX2( svga->curr.num_sampler_views, svga->state.hw_draw.num_views ); unsigned min_lod; unsigned max_lod; @@ -77,30 +77,32 @@ update_tss_binding(struct svga_context *svga, for (i = 0; i < count; i++) { const struct svga_sampler_state *s = svga->curr.sampler[i]; struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; + struct pipe_texture *texture = NULL; /* get min max lod */ - if (svga->curr.texture[i]) { + if (svga->curr.sampler_views[i]) { min_lod = MAX2(s->view_min_lod, 0); - max_lod = MIN2(s->view_max_lod, svga->curr.texture[i]->last_level); + max_lod = MIN2(s->view_max_lod, svga->curr.sampler_views[i]->texture->last_level); + texture = svga->curr.sampler_views[i]->texture; } else { min_lod = 0; max_lod = 0; } - if (view->texture != svga->curr.texture[i] || + if (view->texture != texture || view->min_lod != min_lod || view->max_lod != max_lod) { svga_sampler_view_reference(&view->v, NULL); - pipe_texture_reference( &view->texture, svga->curr.texture[i] ); + pipe_texture_reference( &view->texture, texture ); view->dirty = TRUE; view->min_lod = min_lod; view->max_lod = max_lod; - if (svga->curr.texture[i]) + if (texture) view->v = svga_get_tex_sampler_view(&svga->pipe, - svga->curr.texture[i], + texture, min_lod, max_lod); } @@ -115,7 +117,7 @@ update_tss_binding(struct svga_context *svga, } } - svga->state.hw_draw.num_views = svga->curr.num_textures; + svga->state.hw_draw.num_views = svga->curr.num_sampler_views; if (queue.bind_count) { SVGA3dTextureState *ts; diff --git a/src/gallium/drivers/svga/svga_state_vdecl.c b/src/gallium/drivers/svga/svga_state_vdecl.c index ded903170b5..f531e223048 100644 --- a/src/gallium/drivers/svga/svga_state_vdecl.c +++ b/src/gallium/drivers/svga/svga_state_vdecl.c @@ -95,17 +95,17 @@ upload_user_buffers( struct svga_context *svga ) static int emit_hw_vs_vdecl( struct svga_context *svga, unsigned dirty ) { - const struct pipe_vertex_element *ve = svga->curr.ve; + const struct pipe_vertex_element *ve = svga->curr.velems->velem; SVGA3dVertexDecl decl; unsigned i; - assert(svga->curr.num_vertex_elements >= + assert(svga->curr.velems->count >= svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]); svga_hwtnl_reset_vdecl( svga->hwtnl, - svga->curr.num_vertex_elements ); + svga->curr.velems->count ); - for (i = 0; i < svga->curr.num_vertex_elements; i++) { + for (i = 0; i < svga->curr.velems->count; i++) { const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index]; unsigned usage, index; diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c index d7999fe53d2..781f7bf5339 100644 --- a/src/gallium/drivers/svga/svga_state_vs.c +++ b/src/gallium/drivers/svga/svga_state_vs.c @@ -186,8 +186,8 @@ static int update_zero_stride( struct svga_context *svga, svga->curr.zero_stride_vertex_elements = 0; svga->curr.num_zero_stride_vertex_elements = 0; - for (i = 0; i < svga->curr.num_vertex_elements; i++) { - const struct pipe_vertex_element *vel = &svga->curr.ve[i]; + for (i = 0; i < svga->curr.velems->count; i++) { + const struct pipe_vertex_element *vel = &svga->curr.velems->velem[i]; const struct pipe_vertex_buffer *vbuffer = &svga->curr.vb[ vel->vertex_buffer_index]; if (vbuffer->stride == 0) { diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index 35f36a828fd..246d34e649e 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -99,8 +99,8 @@ static int update_swtnl_draw( struct svga_context *svga, if (dirty & SVGA_NEW_VELEMENT) draw_set_vertex_elements(svga->swtnl.draw, - svga->curr.num_vertex_elements, - svga->curr.ve ); + svga->curr.velems->count, + svga->curr.velems->velem ); if (dirty & SVGA_NEW_CLIP) draw_set_clip_state(svga->swtnl.draw, diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h index b4e3af0eafc..d4bb176f9a8 100644 --- a/src/gallium/drivers/svga/svga_winsys.h +++ b/src/gallium/drivers/svga/svga_winsys.h @@ -51,6 +51,7 @@ struct pipe_context; struct pipe_fence_handle; struct pipe_texture; struct svga_region; +struct winsys_handle; #define SVGA_BUFFER_USAGE_PINNED (PIPE_BUFFER_USAGE_CUSTOM << 0) @@ -187,6 +188,25 @@ struct svga_winsys_screen uint32 numMipLevels); /** + * Creates a surface from a winsys handle. + * Used to implement pipe_screen::texture_from_handle. + */ + struct svga_winsys_surface * + (*surface_from_handle)(struct svga_winsys_screen *sws, + struct winsys_handle *whandle, + SVGA3dSurfaceFormat *format); + + /** + * Get a winsys_handle from a surface. + * Used to implement pipe_screen::texture_get_handle. + */ + boolean + (*surface_get_handle)(struct svga_winsys_screen *sws, + struct svga_winsys_surface *surface, + unsigned stride, + struct winsys_handle *whandle); + + /** * Whether this surface is sitting in a validate list */ boolean @@ -284,19 +304,6 @@ svga_screen_buffer_wrap_surface(struct pipe_screen *screen, struct svga_winsys_surface *srf); struct svga_winsys_surface * -svga_screen_texture_get_winsys_surface(struct pipe_texture *texture); -struct svga_winsys_surface * svga_screen_buffer_get_winsys_surface(struct pipe_buffer *buffer); -boolean -svga_screen_buffer_from_texture(struct pipe_texture *texture, - struct pipe_buffer **buffer, - unsigned *stride); - -struct pipe_texture * -svga_screen_texture_wrap_surface(struct pipe_screen *screen, - struct pipe_texture *base, - enum SVGA3dSurfaceFormat format, - struct svga_winsys_surface *srf); - #endif /* SVGA_WINSYS_H_ */ diff --git a/src/gallium/drivers/svga/svgadump/svga_shader_dump.c b/src/gallium/drivers/svga/svgadump/svga_shader_dump.c index 705ca29e8f5..4ee1bf2c353 100644 --- a/src/gallium/drivers/svga/svgadump/svga_shader_dump.c +++ b/src/gallium/drivers/svga/svgadump/svga_shader_dump.c @@ -360,7 +360,9 @@ dump_dstreg(struct sh_dstreg dstreg, union { struct sh_reg reg; struct sh_dstreg dstreg; - } u = { { 0 } }; + } u; + + memset(&u, 0, sizeof(u)); assert( (dstreg.modifier & (SVGA3DDSTMOD_SATURATE | SVGA3DDSTMOD_PARTIALPRECISION)) == dstreg.modifier ); diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index df40fbade6c..5c24bd1f7df 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -25,9 +25,12 @@ * **************************************************************************/ +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_simple_list.h" +#include "util/u_format.h" +#include "pipe/p_format.h" #include "pipe/p_screen.h" #include "tr_dump.h" @@ -112,7 +115,7 @@ trace_context_draw_block(struct trace_context *tr_ctx, int flag) (void *) tr_ctx->draw_rule.fs, (void *) tr_ctx->curr.fs, (void *) tr_ctx->draw_rule.vs, (void *) tr_ctx->curr.vs, (void *) tr_ctx->draw_rule.surf, 0, - (void *) tr_ctx->draw_rule.tex, 0); + (void *) tr_ctx->draw_rule.sampler_view, 0); if (tr_ctx->draw_rule.fs && tr_ctx->draw_rule.fs == tr_ctx->curr.fs) block = TRUE; @@ -126,12 +129,12 @@ trace_context_draw_block(struct trace_context *tr_ctx, int flag) for (k = 0; k < tr_ctx->curr.nr_cbufs; k++) if (tr_ctx->draw_rule.surf == tr_ctx->curr.cbufs[k]) block = TRUE; - if (tr_ctx->draw_rule.tex) { - for (k = 0; k < tr_ctx->curr.num_texs; k++) - if (tr_ctx->draw_rule.tex == tr_ctx->curr.tex[k]) + if (tr_ctx->draw_rule.sampler_view) { + for (k = 0; k < tr_ctx->curr.num_sampler_views; k++) + if (tr_ctx->draw_rule.sampler_view == tr_ctx->curr.sampler_views[k]) block = TRUE; - for (k = 0; k < tr_ctx->curr.num_vert_texs; k++) { - if (tr_ctx->draw_rule.tex == tr_ctx->curr.vert_tex[k]) { + for (k = 0; k < tr_ctx->curr.num_vert_sampler_views; k++) { + if (tr_ctx->draw_rule.sampler_view == tr_ctx->curr.vert_sampler_views[k]) { block = TRUE; } } @@ -773,6 +776,70 @@ trace_context_delete_vs_state(struct pipe_context *_pipe, } +static INLINE void * +trace_context_create_vertex_elements_state(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_vertex_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, num_elements); + + trace_dump_arg_begin("elements"); + trace_dump_struct_array(vertex_element, elements, num_elements); + trace_dump_arg_end(); + + result = pipe->create_vertex_elements_state(pipe, num_elements, elements); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static INLINE void +trace_context_bind_vertex_elements_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "bind_vertex_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->bind_vertex_elements_state(pipe, state); + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_delete_vertex_elements_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_verte_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_vertex_elements_state(pipe, state); + + trace_dump_call_end(); +} + + static INLINE void trace_context_set_blend_color(struct pipe_context *_pipe, const struct pipe_blend_color *state) @@ -949,63 +1016,119 @@ trace_context_set_viewport_state(struct pipe_context *_pipe, } +static struct pipe_sampler_view * +trace_create_sampler_view(struct pipe_context *_pipe, + struct pipe_texture *_texture, + const struct pipe_sampler_view *templ) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_texture *tr_tex = trace_texture(_texture); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_texture *texture = tr_tex->texture; + struct trace_sampler_view *result = CALLOC_STRUCT(trace_sampler_view); + + trace_dump_call_begin("pipe_context", "create_sampler_view"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, texture); + trace_dump_arg(ptr, templ); + + result->sampler_view = pipe->create_sampler_view(pipe, texture, templ); + + result->base = *templ; + result->base.reference.count = 1; + result->base.texture = NULL; + pipe_texture_reference(&result->base.texture, _texture); + result->base.context = _pipe; + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return &result->base; +} + + +static void +trace_sampler_view_destroy(struct pipe_context *_pipe, + struct pipe_sampler_view *_view) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_sampler_view *tr_view = trace_sampler_view(_view); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_sampler_view *view = tr_view->sampler_view; + + trace_dump_call_begin("pipe_context", "sampler_view_destroy"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, view); + + pipe->sampler_view_destroy(pipe, view); + + trace_dump_call_end(); + + pipe_texture_reference(&_view->texture, NULL); + FREE(_view); +} + + static INLINE void -trace_context_set_fragment_sampler_textures(struct pipe_context *_pipe, - unsigned num_textures, - struct pipe_texture **textures) +trace_context_set_fragment_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **views) { struct trace_context *tr_ctx = trace_context(_pipe); - struct trace_texture *tr_tex; + struct trace_sampler_view *tr_view; struct pipe_context *pipe = tr_ctx->pipe; - struct pipe_texture *unwrapped_textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SAMPLERS]; unsigned i; - tr_ctx->curr.num_texs = num_textures; - for(i = 0; i < num_textures; ++i) { - tr_tex = trace_texture(textures[i]); - tr_ctx->curr.tex[i] = tr_tex; - unwrapped_textures[i] = tr_tex ? tr_tex->texture : NULL; + tr_ctx->curr.num_sampler_views = num; + for(i = 0; i < num; ++i) { + tr_view = trace_sampler_view(views[i]); + tr_ctx->curr.sampler_views[i] = tr_view; + unwrapped_views[i] = tr_view ? tr_view->sampler_view : NULL; } - textures = unwrapped_textures; + views = unwrapped_views; - trace_dump_call_begin("pipe_context", "set_fragment_sampler_textures"); + trace_dump_call_begin("pipe_context", "set_fragment_sampler_views"); trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, num_textures); - trace_dump_arg_array(ptr, textures, num_textures); + trace_dump_arg(uint, num); + trace_dump_arg_array(ptr, views, num); - pipe->set_fragment_sampler_textures(pipe, num_textures, textures); + pipe->set_fragment_sampler_views(pipe, num, views); trace_dump_call_end(); } static INLINE void -trace_context_set_vertex_sampler_textures(struct pipe_context *_pipe, - unsigned num_textures, - struct pipe_texture **textures) +trace_context_set_vertex_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **views) { struct trace_context *tr_ctx = trace_context(_pipe); - struct trace_texture *tr_tex; + struct trace_sampler_view *tr_view; struct pipe_context *pipe = tr_ctx->pipe; - struct pipe_texture *unwrapped_textures[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_VERTEX_SAMPLERS]; unsigned i; - tr_ctx->curr.num_vert_texs = num_textures; - for(i = 0; i < num_textures; ++i) { - tr_tex = trace_texture(textures[i]); - tr_ctx->curr.vert_tex[i] = tr_tex; - unwrapped_textures[i] = tr_tex ? tr_tex->texture : NULL; + tr_ctx->curr.num_vert_sampler_views = num; + for(i = 0; i < num; ++i) { + tr_view = trace_sampler_view(views[i]); + tr_ctx->curr.vert_sampler_views[i] = tr_view; + unwrapped_views[i] = tr_view ? tr_view->sampler_view : NULL; } - textures = unwrapped_textures; + views = unwrapped_views; - trace_dump_call_begin("pipe_context", "set_vertex_sampler_textures"); + trace_dump_call_begin("pipe_context", "set_vertex_sampler_views"); trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, num_textures); - trace_dump_arg_array(ptr, textures, num_textures); + trace_dump_arg(uint, num); + trace_dump_arg_array(ptr, views, num); - pipe->set_vertex_sampler_textures(pipe, num_textures, textures); + pipe->set_vertex_sampler_views(pipe, num, views); trace_dump_call_end(); } @@ -1048,29 +1171,6 @@ trace_context_set_vertex_buffers(struct pipe_context *_pipe, static INLINE void -trace_context_set_vertex_elements(struct pipe_context *_pipe, - unsigned num_elements, - const struct pipe_vertex_element *elements) -{ - struct trace_context *tr_ctx = trace_context(_pipe); - struct pipe_context *pipe = tr_ctx->pipe; - - trace_dump_call_begin("pipe_context", "set_vertex_elements"); - - trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, num_elements); - - trace_dump_arg_begin("elements"); - trace_dump_struct_array(vertex_element, elements, num_elements); - trace_dump_arg_end(); - - pipe->set_vertex_elements(pipe, num_elements, elements); - - trace_dump_call_end(); -} - - -static INLINE void trace_context_surface_copy(struct pipe_context *_pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, @@ -1242,6 +1342,136 @@ trace_is_buffer_referenced( struct pipe_context *_pipe, return referenced; } + +/******************************************************************** + * transfer + */ + + +static struct pipe_transfer * +trace_context_get_tex_transfer(struct pipe_context *_context, + struct pipe_texture *_texture, + unsigned face, unsigned level, + unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_texture *tr_tex = trace_texture(_texture); + struct pipe_context *context = tr_context->pipe; + struct pipe_texture *texture = tr_tex->texture; + struct pipe_transfer *result = NULL; + + assert(texture->screen == context->screen); + + trace_dump_call_begin("pipe_context", "get_tex_transfer"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, texture); + trace_dump_arg(uint, face); + trace_dump_arg(uint, level); + trace_dump_arg(uint, zslice); + trace_dump_arg(uint, usage); + + trace_dump_arg(uint, x); + trace_dump_arg(uint, y); + trace_dump_arg(uint, w); + trace_dump_arg(uint, h); + + result = context->get_tex_transfer(context, texture, face, level, zslice, usage, + x, y, w, h); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + if (result) + result = trace_transfer_create(tr_context, tr_tex, result); + + return result; +} + + +static void +trace_context_tex_transfer_destroy(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; + + trace_dump_call_begin("pipe_context", "tex_transfer_destroy"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, transfer); + + trace_dump_call_end(); + + trace_transfer_destroy(tr_context, tr_trans); +} + + +static void * +trace_context_transfer_map(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; + void *map; + + map = context->transfer_map(context, transfer); + if(map) { + if(transfer->usage & PIPE_TRANSFER_WRITE) { + assert(!tr_trans->map); + tr_trans->map = map; + } + } + + return map; +} + + +static void +trace_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct trace_context *tr_ctx = trace_context(_context); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_context *context = tr_ctx->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; + + if(tr_trans->map) { + size_t size = util_format_get_nblocksy(transfer->texture->format, transfer->height) * transfer->stride; + + trace_dump_call_begin("pipe_context", "transfer_write"); + + trace_dump_arg(ptr, context); + + trace_dump_arg(ptr, transfer); + + trace_dump_arg_begin("stride"); + trace_dump_uint(transfer->stride); + trace_dump_arg_end(); + + trace_dump_arg_begin("data"); + trace_dump_bytes(tr_trans->map, size); + trace_dump_arg_end(); + + trace_dump_arg_begin("size"); + trace_dump_uint(size); + trace_dump_arg_end(); + + trace_dump_call_end(); + + tr_trans->map = NULL; + } + + context->transfer_unmap(context, transfer); +} + static const struct debug_named_value rbug_blocker_flags[] = { {"before", 1}, {"after", 2}, @@ -1303,6 +1533,9 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.create_vs_state = trace_context_create_vs_state; tr_ctx->base.bind_vs_state = trace_context_bind_vs_state; tr_ctx->base.delete_vs_state = trace_context_delete_vs_state; + tr_ctx->base.create_vertex_elements_state = trace_context_create_vertex_elements_state; + tr_ctx->base.bind_vertex_elements_state = trace_context_bind_vertex_elements_state; + tr_ctx->base.delete_vertex_elements_state = trace_context_delete_vertex_elements_state; tr_ctx->base.set_blend_color = trace_context_set_blend_color; tr_ctx->base.set_stencil_ref = trace_context_set_stencil_ref; tr_ctx->base.set_clip_state = trace_context_set_clip_state; @@ -1311,10 +1544,11 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.set_polygon_stipple = trace_context_set_polygon_stipple; tr_ctx->base.set_scissor_state = trace_context_set_scissor_state; tr_ctx->base.set_viewport_state = trace_context_set_viewport_state; - tr_ctx->base.set_fragment_sampler_textures = trace_context_set_fragment_sampler_textures; - tr_ctx->base.set_vertex_sampler_textures = trace_context_set_vertex_sampler_textures; + tr_ctx->base.set_fragment_sampler_views = trace_context_set_fragment_sampler_views; + tr_ctx->base.set_vertex_sampler_views = trace_context_set_vertex_sampler_views; + tr_ctx->base.create_sampler_view = trace_create_sampler_view; + tr_ctx->base.sampler_view_destroy = trace_sampler_view_destroy; tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers; - tr_ctx->base.set_vertex_elements = trace_context_set_vertex_elements; if (pipe->surface_copy) tr_ctx->base.surface_copy = trace_context_surface_copy; if (pipe->surface_fill) @@ -1324,6 +1558,11 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.is_texture_referenced = trace_is_texture_referenced; tr_ctx->base.is_buffer_referenced = trace_is_buffer_referenced; + tr_ctx->base.get_tex_transfer = trace_context_get_tex_transfer; + tr_ctx->base.tex_transfer_destroy = trace_context_tex_transfer_destroy; + tr_ctx->base.transfer_map = trace_context_transfer_map; + tr_ctx->base.transfer_unmap = trace_context_transfer_unmap; + tr_ctx->pipe = pipe; trace_screen_add_to_list(tr_scr, contexts, tr_ctx); diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h index 14284232485..feec9b6bbf3 100644 --- a/src/gallium/drivers/trace/tr_context.h +++ b/src/gallium/drivers/trace/tr_context.h @@ -53,11 +53,11 @@ struct trace_context struct trace_shader *fs; struct trace_shader *vs; - struct trace_texture *tex[PIPE_MAX_SAMPLERS]; - unsigned num_texs; + struct trace_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; + unsigned num_sampler_views; - struct trace_texture *vert_tex[PIPE_MAX_VERTEX_SAMPLERS]; - unsigned num_vert_texs; + struct trace_sampler_view *vert_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; + unsigned num_vert_sampler_views; unsigned nr_cbufs; struct trace_texture *cbufs[PIPE_MAX_COLOR_BUFS]; @@ -68,7 +68,7 @@ struct trace_context struct trace_shader *fs; struct trace_shader *vs; - struct trace_texture *tex; + struct trace_sampler_view *sampler_view; struct trace_texture *surf; int blocker; diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c index 2b4915003e2..eaa47df4066 100644 --- a/src/gallium/drivers/trace/tr_drm.c +++ b/src/gallium/drivers/trace/tr_drm.c @@ -30,9 +30,7 @@ #include "util/u_memory.h" #include "tr_drm.h" #include "tr_screen.h" -#include "tr_context.h" -#include "tr_buffer.h" -#include "tr_texture.h" +#include "tr_public.h" struct trace_drm_api { @@ -62,69 +60,8 @@ trace_drm_create_screen(struct drm_api *_api, int fd, screen = api->create_screen(api, fd, arg); - return trace_screen_create(screen); -} - - -static struct pipe_texture * -trace_drm_texture_from_shared_handle(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *templ, - const char *name, - unsigned stride, - unsigned handle) -{ - struct trace_screen *tr_screen = trace_screen(_screen); - struct trace_drm_api *tr_api = trace_drm_api(_api); - struct pipe_screen *screen = tr_screen->screen; - struct drm_api *api = tr_api->api; - struct pipe_texture *result; - - /* TODO trace call */ - - result = api->texture_from_shared_handle(api, screen, templ, name, stride, handle); - - result = trace_texture_create(trace_screen(_screen), result); - - return result; -} - -static boolean -trace_drm_shared_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct trace_screen *tr_screen = trace_screen(_screen); - struct trace_texture *tr_texture = trace_texture(_texture); - struct trace_drm_api *tr_api = trace_drm_api(_api); - struct pipe_screen *screen = tr_screen->screen; - struct pipe_texture *texture = tr_texture->texture; - struct drm_api *api = tr_api->api; - - /* TODO trace call */ - - return api->shared_handle_from_texture(api, screen, texture, stride, handle); -} -static boolean -trace_drm_local_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct trace_screen *tr_screen = trace_screen(_screen); - struct trace_texture *tr_texture = trace_texture(_texture); - struct trace_drm_api *tr_api = trace_drm_api(_api); - struct pipe_screen *screen = tr_screen->screen; - struct pipe_texture *texture = tr_texture->texture; - struct drm_api *api = tr_api->api; - - /* TODO trace call */ - - return api->local_handle_from_texture(api, screen, texture, stride, handle); + return trace_screen_create(screen); } static void @@ -158,9 +95,6 @@ trace_drm_create(struct drm_api *api) tr_api->base.name = api->name; tr_api->base.driver_name = api->driver_name; tr_api->base.create_screen = trace_drm_create_screen; - tr_api->base.texture_from_shared_handle = trace_drm_texture_from_shared_handle; - tr_api->base.shared_handle_from_texture = trace_drm_shared_handle_from_texture; - tr_api->base.local_handle_from_texture = trace_drm_local_handle_from_texture; tr_api->base.destroy = trace_drm_destroy; tr_api->api = api; diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index f97d963dba6..f82dd01c697 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -479,7 +479,6 @@ void trace_dump_vertex_element(const struct pipe_vertex_element *state) trace_dump_member(uint, state, src_offset); trace_dump_member(uint, state, vertex_buffer_index); - trace_dump_member(uint, state, nr_components); trace_dump_member(format, state, src_format); diff --git a/src/gallium/drivers/trace/tr_public.h b/src/gallium/drivers/trace/tr_public.h new file mode 100644 index 00000000000..62e217097d0 --- /dev/null +++ b/src/gallium/drivers/trace/tr_public.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +#ifndef TR_PUBLIC_H +#define TR_PUBLIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_screen; +struct pipe_context; + +struct pipe_screen * +trace_screen_create(struct pipe_screen *screen); + +#ifdef __cplusplus +} +#endif + +#endif /* TR_PUBLIC_H */ diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c index a43adac6940..53ab8c686d8 100644 --- a/src/gallium/drivers/trace/tr_rbug.c +++ b/src/gallium/drivers/trace/tr_rbug.c @@ -219,7 +219,7 @@ trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, struct trace_texture *tr_tex = NULL; struct tr_list *ptr; - struct pipe_screen *screen = tr_scr->screen; + struct pipe_context *context = tr_scr->private_context; struct pipe_texture *tex; struct pipe_transfer *t; @@ -239,12 +239,12 @@ trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, } tex = tr_tex->texture; - t = screen->get_tex_transfer(tr_scr->screen, tex, - gptr->face, gptr->level, gptr->zslice, - PIPE_TRANSFER_READ, - gptr->x, gptr->y, gptr->w, gptr->h); + t = context->get_tex_transfer(context, tex, + gptr->face, gptr->level, gptr->zslice, + PIPE_TRANSFER_READ, + gptr->x, gptr->y, gptr->w, gptr->h); - map = screen->transfer_map(screen, t); + map = context->transfer_map(context, t); rbug_send_texture_read_reply(tr_rbug->con, serial, t->texture->format, @@ -256,8 +256,8 @@ trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, t->stride, NULL); - screen->transfer_unmap(screen, t); - screen->tex_transfer_destroy(t); + context->transfer_unmap(context, t); + context->tex_transfer_destroy(context, t); pipe_mutex_unlock(tr_scr->list_mutex); @@ -313,12 +313,12 @@ trace_rbug_context_info(struct trace_rbug *tr_rbug, struct rbug_header *header, for (i = 0; i < tr_ctx->curr.nr_cbufs; i++) cbufs[i] = VOID2U64(tr_ctx->curr.cbufs[i]); - for (i = 0; i < tr_ctx->curr.num_texs; i++) - texs[i] = VOID2U64(tr_ctx->curr.tex[i]); + for (i = 0; i < tr_ctx->curr.num_sampler_views; i++) + texs[i] = VOID2U64(tr_ctx->curr.sampler_views[i]); rbug_send_context_info_reply(tr_rbug->con, serial, VOID2U64(tr_ctx->curr.vs), VOID2U64(tr_ctx->curr.fs), - texs, tr_ctx->curr.num_texs, + texs, tr_ctx->curr.num_sampler_views, cbufs, tr_ctx->curr.nr_cbufs, VOID2U64(tr_ctx->curr.zsbuf), tr_ctx->draw_blocker, tr_ctx->draw_blocked, NULL); @@ -444,7 +444,7 @@ trace_rbug_context_draw_rule(struct trace_rbug *tr_rbug, struct rbug_header *hea pipe_mutex_lock(tr_ctx->draw_mutex); tr_ctx->draw_rule.vs = U642VOID(rule->vertex); tr_ctx->draw_rule.fs = U642VOID(rule->fragment); - tr_ctx->draw_rule.tex = U642VOID(rule->texture); + tr_ctx->draw_rule.sampler_view = U642VOID(rule->texture); tr_ctx->draw_rule.surf = U642VOID(rule->surface); tr_ctx->draw_rule.blocker = rule->block; tr_ctx->draw_blocker |= RBUG_BLOCK_RULE; diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index 388d83eb5c2..25990bdac7f 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -35,6 +35,7 @@ #include "tr_texture.h" #include "tr_context.h" #include "tr_screen.h" +#include "tr_public.h" #include "util/u_inlines.h" #include "pipe/p_format.h" @@ -236,39 +237,41 @@ trace_screen_texture_create(struct pipe_screen *_screen, return result; } - static struct pipe_texture * -trace_screen_texture_blanket(struct pipe_screen *_screen, - const struct pipe_texture *templat, - const unsigned *ppitch, - struct pipe_buffer *_buffer) +trace_screen_texture_from_handle(struct pipe_screen *_screen, + const struct pipe_texture *templ, + struct winsys_handle *handle) { - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_buffer *tr_buf = trace_buffer(_buffer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_buffer *buffer = tr_buf->buffer; - unsigned pitch = *ppitch; + struct trace_screen *tr_screen = trace_screen(_screen); + struct pipe_screen *screen = tr_screen->screen; struct pipe_texture *result; - trace_dump_call_begin("pipe_screen", "texture_blanket"); + /* TODO trace call */ - trace_dump_arg(ptr, screen); - trace_dump_arg(template, templat); - trace_dump_arg(uint, pitch); - trace_dump_arg(ptr, buffer); + result = screen->texture_from_handle(screen, templ, handle); - result = screen->texture_blanket(screen, templat, ppitch, buffer); + result = trace_texture_create(trace_screen(_screen), result); - trace_dump_ret(ptr, result); + return result; +} - trace_dump_call_end(); +static boolean +trace_screen_texture_get_handle(struct pipe_screen *_screen, + struct pipe_texture *_texture, + struct winsys_handle *handle) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_texture *tr_texture = trace_texture(_texture); + struct pipe_screen *screen = tr_screen->screen; + struct pipe_texture *texture = tr_texture->texture; - result = trace_texture_create(tr_scr, result); + /* TODO trace call */ - return result; + return screen->texture_get_handle(screen, texture, handle); } + static void trace_screen_texture_destroy(struct pipe_texture *_texture) { @@ -350,133 +353,7 @@ trace_screen_tex_surface_destroy(struct pipe_surface *_surface) } -/******************************************************************** - * transfer - */ - - -static struct pipe_transfer * -trace_screen_get_tex_transfer(struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned face, unsigned level, - unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_texture *tr_tex = trace_texture(_texture); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_texture *texture = tr_tex->texture; - struct pipe_transfer *result = NULL; - - assert(texture->screen == screen); - - trace_dump_call_begin("pipe_screen", "get_tex_transfer"); - trace_dump_arg(ptr, screen); - trace_dump_arg(ptr, texture); - trace_dump_arg(uint, face); - trace_dump_arg(uint, level); - trace_dump_arg(uint, zslice); - trace_dump_arg(uint, usage); - - trace_dump_arg(uint, x); - trace_dump_arg(uint, y); - trace_dump_arg(uint, w); - trace_dump_arg(uint, h); - - result = screen->get_tex_transfer(screen, texture, face, level, zslice, usage, - x, y, w, h); - - trace_dump_ret(ptr, result); - - trace_dump_call_end(); - - if (result) - result = trace_transfer_create(tr_tex, result); - - return result; -} - - -static void -trace_screen_tex_transfer_destroy(struct pipe_transfer *_transfer) -{ - struct trace_screen *tr_scr = trace_screen(_transfer->texture->screen); - struct trace_transfer *tr_trans = trace_transfer(_transfer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_transfer *transfer = tr_trans->transfer; - - trace_dump_call_begin("pipe_screen", "tex_transfer_destroy"); - - trace_dump_arg(ptr, screen); - trace_dump_arg(ptr, transfer); - - trace_dump_call_end(); - - trace_transfer_destroy(tr_trans); -} - - -static void * -trace_screen_transfer_map(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_transfer *tr_trans = trace_transfer(_transfer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_transfer *transfer = tr_trans->transfer; - void *map; - - map = screen->transfer_map(screen, transfer); - if(map) { - if(transfer->usage & PIPE_TRANSFER_WRITE) { - assert(!tr_trans->map); - tr_trans->map = map; - } - } - - return map; -} - - -static void -trace_screen_transfer_unmap(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_transfer *tr_trans = trace_transfer(_transfer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_transfer *transfer = tr_trans->transfer; - - if(tr_trans->map) { - size_t size = util_format_get_nblocksy(transfer->texture->format, transfer->height) * transfer->stride; - - trace_dump_call_begin("pipe_screen", "transfer_write"); - - trace_dump_arg(ptr, screen); - - trace_dump_arg(ptr, transfer); - - trace_dump_arg_begin("stride"); - trace_dump_uint(transfer->stride); - trace_dump_arg_end(); - - trace_dump_arg_begin("data"); - trace_dump_bytes(tr_trans->map, size); - trace_dump_arg_end(); - - trace_dump_arg_begin("size"); - trace_dump_uint(size); - trace_dump_arg_end(); - - trace_dump_call_end(); - - tr_trans->map = NULL; - } - - screen->transfer_unmap(screen, transfer); -} /******************************************************************** @@ -484,45 +361,7 @@ trace_screen_transfer_unmap(struct pipe_screen *_screen, */ -static struct pipe_buffer * -trace_screen_surface_buffer_create(struct pipe_screen *_screen, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *pstride) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct pipe_screen *screen = tr_scr->screen; - unsigned stride; - struct pipe_buffer *result; - - trace_dump_call_begin("pipe_screen", "surface_buffer_create"); - - trace_dump_arg(ptr, screen); - trace_dump_arg(uint, width); - trace_dump_arg(uint, height); - trace_dump_arg(format, format); - trace_dump_arg(uint, usage); - trace_dump_arg(uint, tex_usage); - - result = screen->surface_buffer_create(screen, - width, height, - format, - usage, - tex_usage, - pstride); - - stride = *pstride; - - trace_dump_arg(uint, stride); - - trace_dump_ret(ptr, result); - - trace_dump_call_end(); - return trace_buffer_create(tr_scr, result); -} static struct pipe_buffer * @@ -931,17 +770,13 @@ trace_screen_create(struct pipe_screen *screen) assert(screen->context_create); tr_scr->base.context_create = trace_screen_context_create; tr_scr->base.texture_create = trace_screen_texture_create; - tr_scr->base.texture_blanket = trace_screen_texture_blanket; + tr_scr->base.texture_from_handle = trace_screen_texture_from_handle; + tr_scr->base.texture_get_handle = trace_screen_texture_get_handle; tr_scr->base.texture_destroy = trace_screen_texture_destroy; tr_scr->base.get_tex_surface = trace_screen_get_tex_surface; tr_scr->base.tex_surface_destroy = trace_screen_tex_surface_destroy; - tr_scr->base.get_tex_transfer = trace_screen_get_tex_transfer; - tr_scr->base.tex_transfer_destroy = trace_screen_tex_transfer_destroy; - tr_scr->base.transfer_map = trace_screen_transfer_map; - tr_scr->base.transfer_unmap = trace_screen_transfer_unmap; tr_scr->base.buffer_create = trace_screen_buffer_create; tr_scr->base.user_buffer_create = trace_screen_user_buffer_create; - tr_scr->base.surface_buffer_create = trace_screen_surface_buffer_create; if (screen->buffer_map) tr_scr->base.buffer_map = trace_screen_buffer_map; if (screen->buffer_map_range) @@ -955,7 +790,11 @@ trace_screen_create(struct pipe_screen *screen) tr_scr->base.fence_signalled = trace_screen_fence_signalled; tr_scr->base.fence_finish = trace_screen_fence_finish; tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer; + tr_scr->screen = screen; + tr_scr->private_context = screen->context_create(screen, NULL); + if (tr_scr->private_context == NULL) + goto error3; trace_dump_ret(ptr, screen); trace_dump_call_end(); @@ -965,10 +804,8 @@ trace_screen_create(struct pipe_screen *screen) return &tr_scr->base; -#if 0 error3: FREE(tr_scr); -#endif error2: trace_dump_ret(ptr, screen); trace_dump_call_end(); diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h index fe5a0fa1909..9bfbe72e2c0 100644 --- a/src/gallium/drivers/trace/tr_screen.h +++ b/src/gallium/drivers/trace/tr_screen.h @@ -56,6 +56,7 @@ struct trace_screen struct pipe_screen base; struct pipe_screen *screen; + struct pipe_context *private_context; /* remote debugger */ struct trace_rbug *rbug; @@ -99,9 +100,6 @@ trace_enabled(void); struct trace_screen * trace_screen(struct pipe_screen *screen); -struct pipe_screen * -trace_screen_create(struct pipe_screen *screen); - void trace_screen_user_buffer_update(struct pipe_screen *screen, struct pipe_buffer *buffer); diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c index 5321d68ec0c..d818e21bb82 100644 --- a/src/gallium/drivers/trace/tr_texture.c +++ b/src/gallium/drivers/trace/tr_texture.c @@ -31,6 +31,7 @@ #include "util/u_simple_list.h" #include "tr_screen.h" +#include "tr_context.h" #include "tr_texture.h" @@ -124,8 +125,9 @@ trace_surface_destroy(struct trace_surface *tr_surf) struct pipe_transfer * -trace_transfer_create(struct trace_texture *tr_tex, - struct pipe_transfer *transfer) +trace_transfer_create(struct trace_context *tr_ctx, + struct trace_texture *tr_tex, + struct pipe_transfer *transfer) { struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen); struct trace_transfer *tr_trans; @@ -142,8 +144,9 @@ trace_transfer_create(struct trace_texture *tr_tex, memcpy(&tr_trans->base, transfer, sizeof(struct pipe_transfer)); tr_trans->base.texture = NULL; - pipe_texture_reference(&tr_trans->base.texture, &tr_tex->base); tr_trans->transfer = transfer; + + pipe_texture_reference(&tr_trans->base.texture, &tr_tex->base); assert(tr_trans->base.texture == &tr_tex->base); trace_screen_add_to_list(tr_scr, transfers, tr_trans); @@ -151,21 +154,23 @@ trace_transfer_create(struct trace_texture *tr_tex, return &tr_trans->base; error: - transfer->texture->screen->tex_transfer_destroy(transfer); + tr_ctx->pipe->tex_transfer_destroy(tr_ctx->pipe, transfer); return NULL; } void -trace_transfer_destroy(struct trace_transfer *tr_trans) +trace_transfer_destroy(struct trace_context *tr_context, + struct trace_transfer *tr_trans) { - struct trace_screen *tr_scr = trace_screen(tr_trans->base.texture->screen); - struct pipe_screen *screen = tr_trans->transfer->texture->screen; + struct trace_screen *tr_scr = trace_screen(tr_context->base.screen); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; trace_screen_remove_from_list(tr_scr, transfers, tr_trans); pipe_texture_reference(&tr_trans->base.texture, NULL); - screen->tex_transfer_destroy(tr_trans->transfer); + context->tex_transfer_destroy(context, transfer); FREE(tr_trans); } diff --git a/src/gallium/drivers/trace/tr_texture.h b/src/gallium/drivers/trace/tr_texture.h index 395e523e73a..66250465e44 100644 --- a/src/gallium/drivers/trace/tr_texture.h +++ b/src/gallium/drivers/trace/tr_texture.h @@ -34,6 +34,7 @@ #include "tr_screen.h" +struct trace_context; struct trace_texture { @@ -55,11 +56,20 @@ struct trace_surface }; +struct trace_sampler_view +{ + struct pipe_sampler_view base; + + struct pipe_sampler_view *sampler_view; +}; + + struct trace_transfer { struct pipe_transfer base; struct pipe_transfer *transfer; + struct pipe_context *pipe; struct tr_list list; @@ -87,6 +97,15 @@ trace_surface(struct pipe_surface *surface) } +static INLINE struct trace_sampler_view * +trace_sampler_view(struct pipe_sampler_view *sampler_view) +{ + if (!sampler_view) + return NULL; + return (struct trace_sampler_view *)sampler_view; +} + + static INLINE struct trace_transfer * trace_transfer(struct pipe_transfer *transfer) { @@ -112,11 +131,13 @@ void trace_surface_destroy(struct trace_surface *tr_surf); struct pipe_transfer * -trace_transfer_create(struct trace_texture *tr_tex, - struct pipe_transfer *transfer); +trace_transfer_create(struct trace_context *tr_ctx, + struct trace_texture *tr_tex, + struct pipe_transfer *transfer); void -trace_transfer_destroy(struct trace_transfer *tr_trans); +trace_transfer_destroy(struct trace_context *tr_ctx, + struct trace_transfer *tr_trans); #endif /* TR_TEXTURE_H_ */ diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h index b93b38310ac..e2766d15cd1 100644 --- a/src/gallium/include/pipe/p_compiler.h +++ b/src/gallium/include/pipe/p_compiler.h @@ -31,13 +31,8 @@ #include "p_config.h" -#ifndef XFree86Server #include <stdlib.h> #include <string.h> -#else -#include "xf86_ansic.h" -#include "xf86_libc.h" -#endif #include <stddef.h> #include <stdarg.h> diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index f82b77903e9..d1b734a9f9a 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -177,6 +177,12 @@ struct pipe_context { void (*bind_gs_state)(struct pipe_context *, void *); void (*delete_gs_state)(struct pipe_context *, void *); + void * (*create_vertex_elements_state)(struct pipe_context *, + unsigned num_elements, + const struct pipe_vertex_element *); + void (*bind_vertex_elements_state)(struct pipe_context *, void *); + void (*delete_vertex_elements_state)(struct pipe_context *, void *); + /*@}*/ /** @@ -208,21 +214,18 @@ struct pipe_context { void (*set_viewport_state)( struct pipe_context *, const struct pipe_viewport_state * ); - void (*set_fragment_sampler_textures)(struct pipe_context *, - unsigned num_textures, - struct pipe_texture **); + void (*set_fragment_sampler_views)(struct pipe_context *, + unsigned num_views, + struct pipe_sampler_view **); - void (*set_vertex_sampler_textures)(struct pipe_context *, - unsigned num_textures, - struct pipe_texture **); + void (*set_vertex_sampler_views)(struct pipe_context *, + unsigned num_views, + struct pipe_sampler_view **); void (*set_vertex_buffers)( struct pipe_context *, unsigned num_buffers, const struct pipe_vertex_buffer * ); - void (*set_vertex_elements)( struct pipe_context *, - unsigned num_elements, - const struct pipe_vertex_element * ); /*@}*/ @@ -303,6 +306,42 @@ struct pipe_context { */ unsigned int (*is_buffer_referenced)(struct pipe_context *pipe, struct pipe_buffer *buf); + + /** + * Create a view on a texture to be used by a shader stage. + */ + struct pipe_sampler_view * (*create_sampler_view)(struct pipe_context *ctx, + struct pipe_texture *texture, + const struct pipe_sampler_view *templat); + + void (*sampler_view_destroy)(struct pipe_context *ctx, + struct pipe_sampler_view *view); + + + /** + * Get a transfer object for transferring data to/from a texture. + * + * Transfers are (by default) context-private and allow uploads to be + * interleaved with + */ + struct pipe_transfer *(*get_tex_transfer)(struct pipe_context *, + struct pipe_texture *texture, + unsigned face, unsigned level, + unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, + unsigned w, unsigned h); + + void (*tex_transfer_destroy)(struct pipe_context *, + struct pipe_transfer *); + + void *(*transfer_map)( struct pipe_context *, + struct pipe_transfer *transfer ); + + void (*transfer_unmap)( struct pipe_context *, + struct pipe_transfer *transfer ); + + }; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 5cebd43ace2..c1e291b9da4 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -176,11 +176,12 @@ enum pipe_texture_target { #define PIPE_TEX_COMPARE_R_TO_TEXTURE 1 #define PIPE_TEXTURE_USAGE_RENDER_TARGET 0x1 -#define PIPE_TEXTURE_USAGE_DISPLAY_TARGET 0x2 /* ie a backbuffer */ -#define PIPE_TEXTURE_USAGE_PRIMARY 0x4 /* ie a frontbuffer */ +#define PIPE_TEXTURE_USAGE_DISPLAY_TARGET 0x2 /* windows presentable buffer, ie a backbuffer */ +#define PIPE_TEXTURE_USAGE_SCANOUT 0x4 /* ie a frontbuffer */ #define PIPE_TEXTURE_USAGE_DEPTH_STENCIL 0x8 #define PIPE_TEXTURE_USAGE_SAMPLER 0x10 #define PIPE_TEXTURE_USAGE_DYNAMIC 0x20 +#define PIPE_TEXTURE_USAGE_SHARED 0x40 /** Pipe driver custom usage flags should be greater or equal to this value */ #define PIPE_TEXTURE_USAGE_CUSTOM (1 << 16) @@ -369,6 +370,17 @@ enum pipe_transfer_usage { /** + * Texture swizzles + */ +#define PIPE_SWIZZLE_RED 0 +#define PIPE_SWIZZLE_GREEN 1 +#define PIPE_SWIZZLE_BLUE 2 +#define PIPE_SWIZZLE_ALPHA 3 +#define PIPE_SWIZZLE_ZERO 4 +#define PIPE_SWIZZLE_ONE 5 + + +/** * Implementation capabilities/limits which are queried through * pipe_screen::get_param() and pipe_screen::get_paramf(). */ diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h index e4a92228093..b7cb83abbe5 100644 --- a/src/gallium/include/pipe/p_screen.h +++ b/src/gallium/include/pipe/p_screen.h @@ -50,6 +50,8 @@ extern "C" { /** Opaque type */ +struct winsys_handle; +/** Opaque type */ struct pipe_fence_handle; struct pipe_winsys; struct pipe_buffer; @@ -108,16 +110,23 @@ struct pipe_screen { const struct pipe_texture *templat); /** - * Create a new texture object, using the given template info, but on top of - * existing memory. - * - * It is assumed that the buffer data is layed out according to the expected - * by the hardware. NULL will be returned if any inconsistency is found. + * Create a texture from a winsys_handle. The handle is often created in + * another process by first creating a pipe texture and then calling + * texture_get_handle. */ - struct pipe_texture * (*texture_blanket)(struct pipe_screen *, - const struct pipe_texture *templat, - const unsigned *stride, - struct pipe_buffer *buffer); + struct pipe_texture * (*texture_from_handle)(struct pipe_screen *, + const struct pipe_texture *templat, + struct winsys_handle *handle); + + /** + * Get a winsys_handle from a texture. Some platforms/winsys requires + * that the texture is created with a special usage flag like + * DISPLAYTARGET or PRIMARY. + */ + boolean (*texture_get_handle)(struct pipe_screen *, + struct pipe_texture *tex, + struct winsys_handle *handle); + void (*texture_destroy)(struct pipe_texture *pt); @@ -133,23 +142,6 @@ struct pipe_screen { void (*tex_surface_destroy)(struct pipe_surface *); - /** Get a transfer object for transferring data to/from a texture */ - struct pipe_transfer *(*get_tex_transfer)(struct pipe_screen *, - struct pipe_texture *texture, - unsigned face, unsigned level, - unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, - unsigned w, unsigned h); - - void (*tex_transfer_destroy)(struct pipe_transfer *); - - void *(*transfer_map)( struct pipe_screen *, - struct pipe_transfer *transfer ); - - void (*transfer_unmap)( struct pipe_screen *, - struct pipe_transfer *transfer ); - /** * Create a new buffer. @@ -187,23 +179,6 @@ struct pipe_screen { void *ptr, unsigned bytes); - /** - * Allocate storage for a display target surface. - * - * Often surfaces which are meant to be blitted to the front screen (i.e., - * display targets) must be allocated with special characteristics, memory - * pools, or obtained directly from the windowing system. - * - * This callback is invoked by the pipe_screenwhen creating a texture marked - * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying - * buffer storage. - */ - struct pipe_buffer *(*surface_buffer_create)(struct pipe_screen *screen, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride); /** @@ -273,6 +248,7 @@ struct pipe_screen { /** * Do any special operations to ensure buffer size is correct + * \param context_private the private data of the calling context */ void (*update_buffer)( struct pipe_screen *ws, void *context_private ); @@ -280,10 +256,12 @@ struct pipe_screen { /** * Do any special operations to ensure frontbuffer contents are * displayed, eg copy fake frontbuffer. + * \param winsys_drawable_handle an opaque handle that the calling context + * gets out-of-band */ void (*flush_frontbuffer)( struct pipe_screen *screen, struct pipe_surface *surf, - void *context_private ); + void *winsys_drawable_handle ); diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 02558520bfe..11072407d93 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -249,7 +249,7 @@ struct pipe_framebuffer_state { unsigned width, height; - /** multiple colorbuffers for multiple render targets */ + /** multiple color buffers for multiple render targets */ unsigned nr_cbufs; struct pipe_surface *cbufs[PIPE_MAX_COLOR_BUFS]; @@ -285,12 +285,12 @@ struct pipe_sampler_state struct pipe_surface { struct pipe_reference reference; - enum pipe_format format; /**< PIPE_FORMAT_x */ + enum pipe_format format; unsigned width; /**< logical width in pixels */ unsigned height; /**< logical height in pixels */ unsigned layout; /**< PIPE_SURFACE_LAYOUT_x */ unsigned offset; /**< offset from start of buffer, in bytes */ - unsigned usage; /**< PIPE_BUFFER_USAGE_* */ + unsigned usage; /**< bitmask of PIPE_BUFFER_USAGE_x */ unsigned zslice; struct pipe_texture *texture; /**< texture into which this is a view */ @@ -300,6 +300,24 @@ struct pipe_surface /** + * A view into a texture that can be bound to a shader stage. + */ +struct pipe_sampler_view +{ + struct pipe_reference reference; + enum pipe_format format; /**< typed PIPE_FORMAT_x */ + struct pipe_texture *texture; /**< texture into which this is a view */ + struct pipe_context *context; /**< context this view belongs to */ + unsigned first_level:8; /**< first mipmap level */ + unsigned last_level:8; /**< last mipmap level */ + unsigned swizzle_r:3; /**< PIPE_SWIZZLE_x for red component */ + unsigned swizzle_g:3; /**< PIPE_SWIZZLE_x for green component */ + unsigned swizzle_b:3; /**< PIPE_SWIZZLE_x for blue component */ + unsigned swizzle_a:3; /**< PIPE_SWIZZLE_x for alpha component */ +}; + + +/** * Transfer object. For data transfer to/from a texture. */ struct pipe_transfer @@ -336,7 +354,7 @@ struct pipe_texture unsigned nr_samples:8; /**< for multisampled surfaces, nr of samples */ - unsigned tex_usage; /* PIPE_TEXTURE_USAGE_* */ + unsigned tex_usage; /**< bitmask of PIPE_TEXTURE_USAGE_* */ struct pipe_screen *screen; /**< screen that this texture belongs to */ }; @@ -373,9 +391,8 @@ struct pipe_vertex_element * this attribute live in? */ unsigned vertex_buffer_index:8; - unsigned nr_components:8; - enum pipe_format src_format; /**< PIPE_FORMAT_* */ + enum pipe_format src_format; }; diff --git a/src/gallium/include/state_tracker/drm_api.h b/src/gallium/include/state_tracker/drm_api.h index e9fa9b4d2a3..fe7ef253ef0 100644 --- a/src/gallium/include/state_tracker/drm_api.h +++ b/src/gallium/include/state_tracker/drm_api.h @@ -17,6 +17,32 @@ enum drm_create_screen_mode { DRM_CREATE_MAX }; +#define DRM_API_HANDLE_TYPE_SHARED 0 +#define DRM_API_HANDLE_TYPE_KMS 1 + +/** + * For use with pipe_screen::{texture_from_handle|texture_get_handle}. + */ +struct winsys_handle +{ + /** + * Unused for texture_from_handle, always + * DRM_API_HANDLE_TYPE_SHARED. Input to texture_get_handle, + * use TEXTURE_USAGE to select handle for kms or ipc. + */ + unsigned type; + /** + * Input to texture_from_handle. + * Output for texture_get_handle. + */ + unsigned handle; + /** + * Input to texture_from_handle. + * Output for texture_get_handle. + */ + unsigned stride; +}; + /** * Modes other than DRM_CREATE_NORMAL derive from this struct. */ @@ -28,6 +54,8 @@ struct drm_create_screen_arg { struct drm_api { + void (*destroy)(struct drm_api *api); + const char *name; /** @@ -36,37 +64,10 @@ struct drm_api const char *driver_name; /** - * Special buffer functions + * Create a pipe srcreen. */ - /*@{*/ struct pipe_screen* (*create_screen)(struct drm_api *api, int drm_fd, struct drm_create_screen_arg *arg); - /*@}*/ - - /** - * Special buffer functions - */ - /*@{*/ - struct pipe_texture* - (*texture_from_shared_handle)(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *templ, - const char *name, - unsigned stride, - unsigned handle); - boolean (*shared_handle_from_texture)(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *stride, - unsigned *handle); - boolean (*local_handle_from_texture)(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *stride, - unsigned *handle); - /*@}*/ - - void (*destroy)(struct drm_api *api); }; extern struct drm_api * drm_api_create(void); diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h new file mode 100644 index 00000000000..70ad215bfce --- /dev/null +++ b/src/gallium/include/state_tracker/st_api.h @@ -0,0 +1,407 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 _ST_API_H_ +#define _ST_API_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +/** + * \file API for communication between state trackers and state tracker + * managers. + * + * While both are state tackers, we use the term state tracker for rendering + * APIs such as OpenGL or OpenVG, and state tracker manager for window system + * APIs such as EGL or GLX in this file. + * + * This file defines an API to be implemented by both state trackers and state + * tracker managers. + */ + +/** + * The entry points of the state trackers. + */ +#define ST_MODULE_OPENGL_SYMBOL "st_module_OpenGL" +#define ST_MODULE_OPENGL_ES1_SYMBOL "st_module_OpenGL_ES1" +#define ST_MODULE_OPENGL_ES2_SYMBOL "st_module_OpenGL_ES2" +#define ST_MODULE_OPENVG_SYMBOL "st_module_OpenVG" + +/** + * The supported rendering API of a state tracker. + */ +enum st_api_type { + ST_API_OPENGL, + ST_API_OPENGL_ES1, + ST_API_OPENGL_ES2, + ST_API_OPENVG, + + ST_API_COUNT +}; + +/** + * Used in st_context_iface->teximage. + */ +enum st_texture_type { + ST_TEXTURE_1D, + ST_TEXTURE_2D, + ST_TEXTURE_3D, + ST_TEXTURE_RECT, +}; + +/** + * Available attachments of framebuffer. + */ +enum st_attachment_type { + ST_ATTACHMENT_FRONT_LEFT, + ST_ATTACHMENT_BACK_LEFT, + ST_ATTACHMENT_FRONT_RIGHT, + ST_ATTACHMENT_BACK_RIGHT, + ST_ATTACHMENT_DEPTH_STENCIL, + ST_ATTACHMENT_ACCUM, + ST_ATTACHMENT_SAMPLE, + + ST_ATTACHMENT_COUNT, + ST_ATTACHMENT_INVALID = -1 +}; + +/* for buffer_mask in st_visual */ +#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT) +#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT) +#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT) +#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT) +#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL) +#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM) +#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE) + +/** + * Enumerations of state tracker context resources. + */ +enum st_context_resource_type { + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER, + ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE, +}; + +/** + * The return type of st_api->get_proc_address. + */ +typedef void (*st_proc_t)(void); + +struct pipe_context; +struct pipe_texture; +struct pipe_fence_handle; + +/** + * Used in st_context_iface->get_resource_for_egl_image. + */ +struct st_context_resource +{ + /* these fields are filled by the caller */ + enum st_context_resource_type type; + void *resource; + + /* this is owned by the caller */ + struct pipe_texture *texture; +}; + +/** + * Used in st_manager_iface->get_egl_image. + */ +struct st_egl_image +{ + /* these fields are filled by the caller */ + struct st_context_iface *stctxi; + void *egl_image; + + /* this is owned by the caller */ + struct pipe_texture *texture; + + unsigned face; + unsigned level; + unsigned zslice; +}; + +/** + * Represent the visual of a framebuffer. + */ +struct st_visual +{ + /** + * Available buffers. Tested with ST_FRAMEBUFFER_*_MASK. + */ + unsigned buffer_mask; + + /** + * Buffer formats. The formats are always set even when the buffer is + * not available. + */ + enum pipe_format color_format; + enum pipe_format depth_stencil_format; + enum pipe_format accum_format; + int samples; + + /** + * Desired render buffer. + */ + enum st_attachment_type render_buffer; +}; + +/** + * Represent a windowing system drawable. + * + * The framebuffer is implemented by the state tracker manager and + * used by the state trackers. + * + * Instead of the winsys pokeing into the API context to figure + * out what buffers that might be needed in the future by the API + * context, it calls into the framebuffer to get the textures. + * + * This structure along with the notify_invalid_framebuffer + * allows framebuffers to be shared between different threads + * but at the same make the API context free from thread + * syncronisation primitves, with the exception of a small + * atomic flag used for notification of framebuffer dirty status. + * + * The thread syncronisation is put inside the framebuffer + * and only called once the framebuffer has become dirty. + */ +struct st_framebuffer_iface +{ + /** + * Available for the state tracker manager to use. + */ + void *st_manager_private; + + /** + * The visual of a framebuffer. + */ + const struct st_visual *visual; + + /** + * Flush the front buffer. + * + * On some window systems, changes to the front buffers are not immediately + * visible. They need to be flushed. + * + * @att is one of the front buffer attachments. + */ + boolean (*flush_front)(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt); + + /** + * The state tracker asks for the textures it needs. + * + * It should try to only ask for attachments that it currently renders + * to, thus allowing the winsys to delay the allocation of textures not + * needed. For example front buffer attachments are not needed if you + * only do back buffer rendering. + * + * The implementor of this function needs to also ensure + * thread safty as this call might be done from multiple threads. + * + * The returned textures are owned by the caller. They should be + * unreferenced when no longer used. If this function is called multiple + * times with different sets of attachments, those buffers not included in + * the last call might be destroyed. This behavior might change in the + * future. + */ + boolean (*validate)(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_texture **out); +}; + +/** + * Represent a rendering context. + * + * This entity is created from st_api and used by the state tracker manager. + */ +struct st_context_iface +{ + /** + * Available for the state tracker and the manager to use. + */ + void *st_context_private; + void *st_manager_private; + + /** + * Destroy the context. + */ + void (*destroy)(struct st_context_iface *stctxi); + + /** + * Invalidate the current textures that was taken from a framebuffer. + * + * The state tracker manager calls this function to let the rendering + * context know that it should update the textures it got from + * st_framebuffer_iface::validate. It should do so at the latest time possible. + * Possible right before sending triangles to the pipe context. + * + * For certain platforms this function might be called from a thread other + * than the thread that the context is currently bound in, and must + * therefore be thread safe. But it is the state tracker manager's + * responsibility to make sure that the framebuffer is bound to the context + * and the API context is current for the duration of this call. + * + * Thus reducing the sync primitive needed to a single atomic flag. + */ + void (*notify_invalid_framebuffer)(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi); + + /** + * Flush all drawing from context to the pipe also flushes the pipe. + */ + void (*flush)(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence); + + /** + * Replace the texture image of a texture object at the specified level. + * + * This function is optional. + */ + boolean (*teximage)(struct st_context_iface *stctxi, enum st_texture_type target, + int level, enum pipe_format internal_format, + struct pipe_texture *tex, boolean mipmap); + + /** + * Used to implement glXCopyContext. + */ + void (*copy)(struct st_context_iface *stctxi, + struct st_context_iface *stsrci, unsigned mask); + + /** + * Look up and return the info of a resource for EGLImage. + * + * This function is optional. + */ + boolean (*get_resource_for_egl_image)(struct st_context_iface *stctxi, + struct st_context_resource *stres); +}; + + +/** + * Represent a state tracker manager. + * + * This interface is implemented by the state tracker manager. It corresponds + * to a "display" in the window system. + */ +struct st_manager +{ + struct pipe_screen *screen; + + /** + * Look up and return the info of an EGLImage. + * + * This function is optional. + */ + boolean (*get_egl_image)(struct st_manager *smapi, + struct st_egl_image *stimg); +}; + +/** + * Represent a rendering API such as OpenGL or OpenVG. + * + * Implemented by the state tracker and used by the state tracker manager. + */ +struct st_api +{ + /** + * Destroy the API. + */ + void (*destroy)(struct st_api *stapi); + + /** + * Return an API entry point. + * + * For GL this is the same as _glapi_get_proc_address. + */ + st_proc_t (*get_proc_address)(struct st_api *stapi, const char *procname); + + /** + * Return true if the visual is supported by the state tracker. + */ + boolean (*is_visual_supported)(struct st_api *stapi, + const struct st_visual *visual); + + /** + * Create a rendering context. + */ + struct st_context_iface *(*create_context)(struct st_api *stapi, + struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *stsharei); + + /** + * Bind the context to the calling thread with draw and read as drawables. + * + * The framebuffers might have different visuals than the context does. + */ + boolean (*make_current)(struct st_api *stapi, + struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi); + + /** + * Get the currently bound context in the calling thread. + */ + struct st_context_iface *(*get_current)(struct st_api *stapi); +}; + +/** + * Represent a state tracker. + * + * This is the entry point of a state tracker. + */ +struct st_module +{ + enum st_api_type api; + struct st_api *(*create_api)(void); +}; + +/** + * Return true if the visual has the specified buffers. + */ +static INLINE boolean +st_visual_have_buffers(const struct st_visual *visual, unsigned mask) +{ + return ((visual->buffer_mask & mask) == mask); +} + +/* these symbols may need to be dynamically lookup up */ +extern PUBLIC const struct st_module st_module_OpenGL; +extern PUBLIC const struct st_module st_module_OpenGL_ES1; +extern PUBLIC const struct st_module st_module_OpenGL_ES2; +extern PUBLIC const struct st_module st_module_OpenVG; + +#endif /* _ST_API_H_ */ diff --git a/src/gallium/drivers/llvmpipe/lp_winsys.h b/src/gallium/include/state_tracker/sw_winsys.h index ce11fa93041..a87650dc77d 100644 --- a/src/gallium/drivers/llvmpipe/lp_winsys.h +++ b/src/gallium/include/state_tracker/sw_winsys.h @@ -27,12 +27,12 @@ /** * @file - * llvmpipe public interface. + * Software rasterizer winsys. */ -#ifndef LP_WINSYS_H -#define LP_WINSYS_H +#ifndef SW_WINSYS_H +#define SW_WINSYS_H #include "pipe/p_compiler.h" /* for boolean */ @@ -44,30 +44,33 @@ extern "C" { #endif +struct winsys_handle; struct pipe_screen; struct pipe_context; +struct pipe_texture; /** * Opaque pointer. */ -struct llvmpipe_displaytarget; +struct sw_displaytarget; /** - * This is the interface that llvmpipe expects any window system + * This is the interface that sw expects any window system * hosting it to implement. * - * llvmpipe is for the most part a self sufficient driver. The only thing it + * sw is for the most part a self sufficient driver. The only thing it * does not know is how to display a surface. */ -struct llvmpipe_winsys +struct sw_winsys { void - (*destroy)( struct llvmpipe_winsys *ws ); + (*destroy)( struct sw_winsys *ws ); boolean - (*is_displaytarget_format_supported)( struct llvmpipe_winsys *ws, + (*is_displaytarget_format_supported)( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format ); /** @@ -81,21 +84,42 @@ struct llvmpipe_winsys * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying * storage. */ - struct llvmpipe_displaytarget * - (*displaytarget_create)( struct llvmpipe_winsys *ws, + struct sw_displaytarget * + (*displaytarget_create)( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, unsigned *stride ); + /** + * Used to implement texture_from_handle. + */ + struct sw_displaytarget * + (*displaytarget_from_handle)( struct sw_winsys *ws, + const struct pipe_texture *templat, + struct winsys_handle *whandle, + unsigned *stride ); + + /** + * Used to implement texture_get_handle. + */ + boolean + (*displaytarget_get_handle)( struct sw_winsys *ws, + struct sw_displaytarget *dt, + struct winsys_handle *whandle ); + + /** + * \param flags bitmask of PIPE_BUFFER_USAGE_x flags + */ void * - (*displaytarget_map)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, + (*displaytarget_map)( struct sw_winsys *ws, + struct sw_displaytarget *dt, unsigned flags ); void - (*displaytarget_unmap)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ); + (*displaytarget_unmap)( struct sw_winsys *ws, + struct sw_displaytarget *dt ); /** * @sa pipe_screen:flush_frontbuffer. @@ -103,23 +127,19 @@ struct llvmpipe_winsys * This call will likely become asynchronous eventually. */ void - (*displaytarget_display)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, + (*displaytarget_display)( struct sw_winsys *ws, + struct sw_displaytarget *dt, void *context_private ); void - (*displaytarget_destroy)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ); + (*displaytarget_destroy)( struct sw_winsys *ws, + struct sw_displaytarget *dt ); }; -struct pipe_screen * -llvmpipe_create_screen( struct llvmpipe_winsys * ); - - #ifdef __cplusplus } #endif -#endif /* LP_WINSYS_H */ +#endif /* SW_WINSYS_H */ diff --git a/src/gallium/include/state_tracker/xlib_sw_winsys.h b/src/gallium/include/state_tracker/xlib_sw_winsys.h new file mode 100644 index 00000000000..f22c22bb620 --- /dev/null +++ b/src/gallium/include/state_tracker/xlib_sw_winsys.h @@ -0,0 +1,29 @@ +#ifndef XLIB_SW_WINSYS_H +#define XLIB_SW_WINSYS_H + +#include "state_tracker/sw_winsys.h" +#include <X11/Xlib.h> + + +struct pipe_screen; +struct pipe_surface; + +/* This is what the xlib software winsys expects to find in the + * "private" field of flush_frontbuffers(). + * + * Xlib-based state trackers somehow need to know this. + */ +struct xlib_drawable { + Visual *visual; + int depth; + Drawable drawable; +}; + + +/* This is the public interface to the ws/xlib module. Why isn't it + * being defined in that directory? + */ +struct sw_winsys *xlib_create_sw_winsys( Display *display ); + + +#endif diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index 908cef454e9..f772ba5d16b 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -35,7 +35,6 @@ #include "state_tracker/drm_api.h" #include "state_tracker/dri1_api.h" #include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" #include "pipe/p_context.h" #include "dri_context.h" @@ -128,7 +127,7 @@ dri_unbind_context(__DRIcontext * cPriv) if (--ctx->bind_count == 0) { if (ctx->st && ctx->st == st_get_current()) { st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - st_make_current(NULL, NULL, NULL); + st_make_current(NULL, NULL, NULL, NULL); } } } @@ -161,7 +160,13 @@ dri_make_current(__DRIcontext * cPriv, ctx->r_stamp = driReadPriv->lastStamp - 1; } - st_make_current(ctx->st, draw->stfb, read->stfb); + /* DRI co-state tracker currently overrides flush_frontbuffer. + * When this is fixed, will need to pass the drawable in the + * fourth parameter here so that when Mesa calls + * flush_frontbuffer directly (in front-buffer rendering), it + * will have access to the drawable argument: + */ + st_make_current(ctx->st, draw->stfb, read->stfb, ctx); if (__dri1_api_hooks) { dri1_update_drawables(ctx, draw, read); @@ -170,7 +175,7 @@ dri_make_current(__DRIcontext * cPriv, ctx->pipe->priv); } } else { - st_make_current(NULL, NULL, NULL); + st_make_current(NULL, NULL, NULL, NULL); } return GL_TRUE; diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 173f4041c8c..c400725c7f2 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -39,8 +39,8 @@ #include "main/renderbuffer.h" #include "state_tracker/drm_api.h" #include "state_tracker/dri1_api.h" -#include "state_tracker/st_public.h" #include "state_tracker/st_context.h" +#include "state_tracker/st_public.h" #include "state_tracker/st_cb_fbo.h" #include "util/u_format.h" @@ -58,6 +58,7 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_surface *surface = NULL; struct pipe_texture *texture = NULL; struct pipe_texture templat; + struct winsys_handle whandle; memset(&templat, 0, sizeof(templat)); templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; @@ -68,8 +69,11 @@ dri_surface_from_handle(struct drm_api *api, templat.width0 = width; templat.height0 = height; - texture = api->texture_from_shared_handle(api, screen, &templat, - "dri2 buffer", pitch, handle); + memset(&whandle, 0, sizeof(whandle)); + whandle.handle = handle; + whandle.stride = pitch; + + texture = screen->texture_from_handle(screen, &templat, &whandle); if (!texture) { debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__); diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c index 1259813a412..800677a2d1e 100644 --- a/src/gallium/state_trackers/dri/dri_extensions.c +++ b/src/gallium/state_trackers/dri/dri_extensions.c @@ -33,110 +33,14 @@ #include "dri_context.h" #include "state_tracker/st_context.h" -#define need_GL_ARB_map_buffer_range -#define need_GL_ARB_multisample -#define need_GL_ARB_occlusion_query -#define need_GL_ARB_point_parameters -#define need_GL_ARB_provoking_vertex -#define need_GL_ARB_shader_objects -#define need_GL_ARB_texture_compression -#define need_GL_ARB_vertex_array_object -#define need_GL_ARB_vertex_buffer_object -#define need_GL_ARB_vertex_program -#define need_GL_ARB_vertex_shader -#define need_GL_ARB_window_pos -#define need_GL_EXT_blend_color -#define need_GL_EXT_blend_equation_separate -#define need_GL_EXT_blend_func_separate -#define need_GL_EXT_blend_minmax -#define need_GL_EXT_cull_vertex -#define need_GL_EXT_draw_buffers2 -#define need_GL_EXT_fog_coord -#define need_GL_EXT_framebuffer_object -#define need_GL_EXT_multi_draw_arrays -#define need_GL_EXT_provoking_vertex -#define need_GL_EXT_secondary_color -#define need_GL_EXT_stencil_two_side -#define need_GL_APPLE_vertex_array_object -#define need_GL_NV_vertex_program -#define need_GL_VERSION_2_0 -#define need_GL_VERSION_2_1 -#include "main/remap_helper.h" #include "utils.h" -/** - * Extension strings exported by the driver. - */ -static const struct dri_extension card_extensions[] = { - {"GL_ARB_fragment_shader", NULL}, - {"GL_ARB_map_buffer_range", GL_ARB_map_buffer_range_functions}, - {"GL_ARB_multisample", GL_ARB_multisample_functions}, - {"GL_ARB_multitexture", NULL}, - {"GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions}, - {"GL_ARB_pixel_buffer_object", NULL}, - {"GL_ARB_provoking_vertex", GL_ARB_provoking_vertex_functions}, - {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, - {"GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, - {"GL_ARB_shading_language_120", GL_VERSION_2_1_functions }, - {"GL_ARB_shader_objects", GL_ARB_shader_objects_functions}, - {"GL_ARB_texture_border_clamp", NULL}, - {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, - {"GL_ARB_texture_cube_map", NULL}, - {"GL_ARB_texture_env_add", NULL}, - {"GL_ARB_texture_env_combine", NULL}, - {"GL_ARB_texture_env_dot3", NULL}, - {"GL_ARB_texture_mirrored_repeat", NULL}, - {"GL_ARB_texture_non_power_of_two", NULL}, - {"GL_ARB_texture_rectangle", NULL}, - {"GL_ARB_vertex_array_object", GL_ARB_vertex_array_object_functions}, - {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, - {"GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions}, - {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, - {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, - {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, - {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, - {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, - {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, - {"GL_EXT_blend_subtract", NULL}, - {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, - {"GL_EXT_draw_buffers2", GL_EXT_draw_buffers2_functions}, - {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, - {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, - {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, - {"GL_EXT_packed_depth_stencil", NULL}, - {"GL_EXT_pixel_buffer_object", NULL}, - {"GL_EXT_provoking_vertex", GL_EXT_provoking_vertex_functions}, - {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, - {"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions}, - {"GL_EXT_stencil_wrap", NULL}, - {"GL_EXT_texture_edge_clamp", NULL}, - {"GL_EXT_texture_env_combine", NULL}, - {"GL_EXT_texture_env_dot3", NULL}, - {"GL_EXT_texture_filter_anisotropic", NULL}, - {"GL_EXT_texture_lod_bias", NULL}, - {"GL_3DFX_texture_compression_FXT1", NULL}, - {"GL_APPLE_client_storage", NULL}, - {"GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions}, - {"GL_MESA_pack_invert", NULL}, - {"GL_MESA_ycbcr_texture", NULL}, - {"GL_NV_blend_square", NULL}, - {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, - {"GL_NV_vertex_program1_1", NULL}, - {"GL_SGIS_generate_mipmap", NULL}, - {NULL, NULL} -}; - void dri_init_extensions(struct dri_context *ctx) { - /* The card_extensions list should be pruned according to the - * capabilities of the pipe_screen. This is actually something - * that can/should be done inside st_create_context(). - * XXX Not pruning is very bogus. Always all these extensions above - * will be advertized, regardless what st_init_extensions - * (which depends on the pipe cap bits) does. - */ - driInitExtensions(ctx->st->ctx, card_extensions, GL_TRUE); + /* New extensions should be added in mesa/state_tracker/st_extensions.c + * and not in this file. */ + driInitExtensions(ctx->st->ctx, NULL, GL_FALSE); } /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 50774b03f35..5eabe10558a 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -36,234 +36,27 @@ #include "native.h" #include "egl_g3d.h" +#include "egl_g3d_st.h" #include "egl_g3d_image.h" -#include "egl_st.h" - -/** - * Validate the draw/read surfaces of the context. - */ -static void -egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct pipe_screen *screen = gdpy->native->screen; - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { - ST_SURFACE_FRONT_LEFT, - ST_SURFACE_BACK_LEFT, - ST_SURFACE_FRONT_RIGHT, - ST_SURFACE_BACK_RIGHT, - }; - EGLint num_surfaces, s; - - /* validate draw and/or read buffers */ - num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; - for (s = 0; s < num_surfaces; s++) { - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - EGLint att; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - if (!gctx->force_validate) { - unsigned int seq_num; - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &seq_num, NULL, NULL, NULL); - /* skip validation */ - if (gsurf->sequence_number == seq_num) - continue; - } - - pipe_surface_reference(&gsurf->render_surface, NULL); - memset(textures, 0, sizeof(textures)); - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &gsurf->sequence_number, textures, - &gsurf->base.Width, &gsurf->base.Height); - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - struct pipe_texture *pt = textures[att]; - struct pipe_surface *ps; - - if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) { - ps = screen->get_tex_surface(screen, pt, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb, - st_att_map[att], ps); - - if (gsurf->render_att == att) - pipe_surface_reference(&gsurf->render_surface, ps); - - pipe_surface_reference(&ps, NULL); - pipe_texture_reference(&pt, NULL); - } - } - - gctx->stapi->st_resize_framebuffer(gbuf->st_fb, - gsurf->base.Width, gsurf->base.Height); - } - - gctx->force_validate = EGL_FALSE; - -} - -/** - * Create a st_framebuffer. - */ -static struct st_framebuffer * -create_framebuffer(_EGLContext *ctx, _EGLSurface *surf) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); - - return gctx->stapi->st_create_framebuffer(&gconf->native->mode, - gconf->native->color_format, gconf->native->depth_format, - gconf->native->stencil_format, - gsurf->base.Width, gsurf->base.Height, &gsurf->base); -} - -/** - * Update the attachments of draw/read surfaces. - */ -static void -egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - EGLint s; - - /* route draw and read buffers' attachments */ - for (s = 0; s < 2; s++) { - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - gbuf->attachment_mask = (1 << gsurf->render_att); - - /* FIXME OpenGL defaults to draw the front or back buffer when the - * context is single-buffered or double-buffered respectively. In EGL, - * however, the buffer to be drawn is determined by the surface, instead - * of the context. As a result, rendering to a pixmap surface with a - * double-buffered context does not work as expected. - * - * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt == - * NATIVE_ATTACHMENT_FRONT_LEFT); - */ - - /* - * FIXME If the back buffer is asked for here, and the front buffer is - * later needed by the client API (e.g. glDrawBuffer is called to draw - * the front buffer), it will create a new pipe texture and draw there. - * One fix is to ask for both buffers here, but it would be a waste if - * the front buffer is never used. A better fix is to add a callback to - * the pipe screen with context private (just like flush_frontbuffer). - */ - } -} - -/** - * Reallocate the context's framebuffers after draw/read surfaces change. - */ -static EGLBoolean -egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface); - struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface); - - /* unreference the old framebuffers */ - if (gctx->draw.st_fb) { - EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb); - void *priv; - - priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb); - if (!gdraw || priv != (void *) &gdraw->base) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - - if (is_equal) { - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - else { - priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb); - if (!gread || priv != (void *) &gread->base) { - gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb); - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - } - } - - if (!gdraw) - return EGL_TRUE; - - /* create the draw fb */ - if (!gctx->draw.st_fb) { - gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base); - if (!gctx->draw.st_fb) - return EGL_FALSE; - } - - /* create the read fb */ - if (!gctx->read.st_fb) { - if (gread != gdraw) { - gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base); - if (!gctx->read.st_fb) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - return EGL_FALSE; - } - } - else { - /* there is no st_reference_framebuffer... */ - gctx->read.st_fb = gctx->draw.st_fb; - } - } - - egl_g3d_route_context(dpy, &gctx->base); - gctx->force_validate = EGL_TRUE; - - return EGL_TRUE; -} /** * Return the state tracker for the given context. */ -static const struct egl_g3d_st * +static struct st_api * egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - const struct egl_g3d_st *stapi; + struct st_api *stapi; EGLint idx = -1; switch (ctx->ClientAPI) { case EGL_OPENGL_ES_API: switch (ctx->ClientVersion) { case 1: - idx = EGL_G3D_ST_OPENGL_ES; + idx = ST_API_OPENGL_ES1; break; case 2: - idx = EGL_G3D_ST_OPENGL_ES2; + idx = ST_API_OPENGL_ES2; break; default: _eglLog(_EGL_WARNING, "unknown client version %d", @@ -272,10 +65,10 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) } break; case EGL_OPENVG_API: - idx = EGL_G3D_ST_OPENVG; + idx = ST_API_OPENVG; break; case EGL_OPENGL_API: - idx = EGL_G3D_ST_OPENGL; + idx = ST_API_OPENGL; break; default: _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); @@ -299,10 +92,10 @@ egl_g3d_init_st(_EGLDriver *drv) if (gdrv->api_mask) return; - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - gdrv->stapis[i] = egl_g3d_get_st(i); + for (i = 0; i < ST_API_COUNT; i++) { + gdrv->stapis[i] = egl_g3d_create_st_api(i); if (gdrv->stapis[i]) - gdrv->api_mask |= gdrv->stapis[i]->api_bit; + gdrv->api_mask |= egl_g3d_st_api_bit(i); } if (gdrv->api_mask) @@ -351,35 +144,6 @@ egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy) } } -/** - * Return an API mask that consists of the state trackers that supports the - * given mode. - * - * FIXME add st_is_mode_supported()? - */ -static EGLint -get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask) -{ - EGLint check; - - /* OpenGL ES 1.x and 2.x are checked together */ - check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; - if (api_mask & check) { - /* this is required by EGL, not by OpenGL ES */ - if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode) - api_mask &= ~check; - } - - check = EGL_OPENVG_BIT; - if (api_mask & check) { - /* vega st needs the depth/stencil rb */ - if (!mode->depthBits && !mode->stencilBits) - api_mask &= ~check; - } - - return api_mask; -} - #ifdef EGL_MESA_screen_surface static void @@ -444,18 +208,88 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) #endif /* EGL_MESA_screen_surface */ /** + * Initialize an EGL config from the native config. + */ +static EGLBoolean +egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const struct native_config *nconf) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + const __GLcontextModes *mode = &nconf->mode; + EGLint buffer_mask, api_mask; + EGLBoolean valid; + EGLint i; + + buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (mode->doubleBufferMode) + buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (mode->stereoMode) { + buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (mode->doubleBufferMode) + buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + gconf->stvis.buffer_mask = buffer_mask; + gconf->stvis.color_format = nconf->color_format; + gconf->stvis.depth_stencil_format = nconf->depth_format; + gconf->stvis.accum_format = PIPE_FORMAT_NONE; + gconf->stvis.samples = 0; + + gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT) ? + ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; + + api_mask = 0; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; + if (stapi) { + if (stapi->is_visual_supported(stapi, &gconf->stvis)) + api_mask |= egl_g3d_st_api_bit(i); + } + } + /* this is required by EGL, not by OpenGL ES */ + if ((mode->drawableType & GLX_WINDOW_BIT) && !mode->doubleBufferMode) + api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); + + if (!api_mask) { + _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", + mode->visualID); + } + + valid = _eglConfigFromContextModesRec(&gconf->base, + mode, api_mask, api_mask); + if (valid) { +#ifdef EGL_MESA_screen_surface + /* check if scanout surface bit is set */ + if (nconf->scanout_bit) { + EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE); + val |= EGL_SCREEN_BIT_MESA; + SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val); + } +#endif + valid = _eglValidateConfig(&gconf->base, EGL_FALSE); + } + if (!valid) { + _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", mode->visualID); + return EGL_FALSE; + } + + gconf->native = nconf; + + return EGL_TRUE; +} + +/** * Add configs to display and return the next config ID. */ static EGLint egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) { - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct egl_g3d_display *gdpy = egl_g3d_display(dpy); const struct native_config **native_configs; int num_configs, i; - native_configs = gdpy->native->get_configs(gdpy->native, - &num_configs); + native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); if (!num_configs) { if (native_configs) free(native_configs); @@ -463,75 +297,25 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) } for (i = 0; i < num_configs; i++) { - EGLint api_mask; struct egl_g3d_config *gconf; - EGLBoolean valid; gconf = CALLOC_STRUCT(egl_g3d_config); - if (!gconf) - continue; - - _eglInitConfig(&gconf->base, dpy, id); - - api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask); - if (!api_mask) { - _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", - native_configs[i]->mode.visualID); - } - - valid = _eglConfigFromContextModesRec(&gconf->base, - &native_configs[i]->mode, api_mask, api_mask); - if (valid) { -#ifdef EGL_MESA_screen_surface - /* check if scanout surface bit is set */ - if (native_configs[i]->scanout_bit) { - EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE); - val |= EGL_SCREEN_BIT_MESA; - SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val); + if (gconf) { + _eglInitConfig(&gconf->base, dpy, id); + if (!egl_g3d_init_config(drv, dpy, &gconf->base, native_configs[i])) { + free(gconf); + continue; } -#endif - valid = _eglValidateConfig(&gconf->base, EGL_FALSE); - } - if (!valid) { - _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", - native_configs[i]->mode.visualID); - free(gconf); - continue; - } - gconf->native = native_configs[i]; - _eglAddConfig(dpy, &gconf->base); - id++; + _eglAddConfig(dpy, &gconf->base); + id++; + } } free(native_configs); return id; } -/** - * Flush the front buffer of the context's draw surface. - */ -static void -egl_g3d_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) -{ - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface); - - if (gsurf) - gsurf->native->flush_frontbuffer(gsurf->native); -} - -/** - * Re-validate the context. - */ -static void -egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) -{ - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); -} - static void egl_g3d_invalid_surface(struct native_display *ndpy, struct native_surface *nsurf, @@ -539,11 +323,15 @@ egl_g3d_invalid_surface(struct native_display *ndpy, { /* XXX not thread safe? */ struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); - struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext); - - /* set force_validate to skip an unnecessary check */ + struct egl_g3d_context *gctx; + + /* + * Some functions such as egl_g3d_copy_buffers create a temporary native + * surface. There is no gsurf associated with it. + */ + gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; if (gctx) - gctx->force_validate = TRUE; + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); } static struct native_event_handler egl_g3d_native_event_handler = { @@ -559,6 +347,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) _eglReleaseDisplayResources(drv, dpy); _eglCleanupDisplay(dpy); + if (gdpy->pipe) + gdpy->pipe->destroy(gdpy->pipe); + if (dpy->Screens) { for (i = 0; i < dpy->NumScreens; i++) { struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]); @@ -568,6 +359,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) free(dpy->Screens); } + if (gdpy->smapi) + egl_g3d_destroy_st_manager(gdpy->smapi); + if (gdpy->native) gdpy->native->destroy(gdpy->native); @@ -602,12 +396,17 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } gdpy->native->user_data = (void *) dpy; - gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer; - gdpy->native->screen->update_buffer = egl_g3d_update_buffer; egl_g3d_init_st(&gdrv->base); dpy->ClientAPIsMask = gdrv->api_mask; + gdpy->smapi = egl_g3d_create_st_manager(dpy); + if (!gdpy->smapi) { + _eglError(EGL_NOT_INITIALIZED, + "eglInitialize(failed to create st manager)"); + goto fail; + } + #ifdef EGL_MESA_screen_surface /* enable MESA_screen_surface before adding (and validating) configs */ if (gdpy->native->modeset) { @@ -644,7 +443,6 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, struct egl_g3d_context *gshare = egl_g3d_context(share); struct egl_g3d_config *gconf = egl_g3d_config(conf); struct egl_g3d_context *gctx; - const __GLcontextModes *mode; gctx = CALLOC_STRUCT(egl_g3d_context); if (!gctx) { @@ -663,24 +461,14 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, return NULL; } - mode = &gconf->native->mode; - - gctx->pipe = gdpy->native->screen->context_create( - gdpy->native->screen, - (void *) &gctx->base); - - if (!gctx->pipe) { + gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, + &gconf->stvis, (gshare) ? gshare->stctxi : NULL); + if (!gctx->stctxi) { free(gctx); return NULL; } - gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode, - (gshare) ? gshare->st_ctx : NULL); - if (!gctx->st_ctx) { - gctx->pipe->destroy(gctx->pipe); - free(gctx); - return NULL; - } + gctx->stctxi->st_manager_private = (void *) &gctx->base; return &gctx->base; } @@ -697,9 +485,7 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) if (!dpy->Initialized) _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); - egl_g3d_realloc_context(dpy, &gctx->base); - /* it will destroy the associated pipe context */ - gctx->stapi->st_destroy_context(gctx->st_ctx); + gctx->stctxi->destroy(gctx->stctxi); free(gctx); } @@ -801,14 +587,20 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, return NULL; } + gsurf->stvis = gconf->stvis; + if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) + gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT; + + gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); + if (!gsurf->stfbi) { + gsurf->native->destroy(gsurf->native); + free(gsurf); + return NULL; + } + nsurf->user_data = &gsurf->base; gsurf->native = nsurf; - gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; - if (!gconf->native->mode.doubleBufferMode) - gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; - return &gsurf->base; } @@ -864,7 +656,8 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) if (!dpy->Initialized) _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); - pipe_surface_reference(&gsurf->render_surface, NULL); + pipe_texture_reference(&gsurf->render_texture, NULL); + egl_g3d_destroy_st_framebuffer(gsurf->stfbi); gsurf->native->destroy(gsurf->native); free(gsurf); } @@ -883,6 +676,7 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, { struct egl_g3d_context *gctx = egl_g3d_context(ctx); struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); + struct egl_g3d_surface *gread = egl_g3d_surface(read); struct egl_g3d_context *old_gctx; EGLBoolean ok = EGL_TRUE; @@ -893,34 +687,29 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, if (old_gctx) { /* flush old context */ - old_gctx->stapi->st_flush(old_gctx->st_ctx, + old_gctx->stctxi->flush(old_gctx->stctxi, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - - /* - * The old context is no longer current, and egl_g3d_realloc_context() - * should be called to destroy the framebuffers. However, it is possible - * that it will be made current again with the same draw/read surfaces. - * It might be better to keep it around. - */ } if (gctx) { - ok = egl_g3d_realloc_context(dpy, &gctx->base); + ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi, + (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL); if (ok) { - ok = gctx->stapi->st_make_current(gctx->st_ctx, - gctx->draw.st_fb, gctx->read.st_fb); - if (ok) { - egl_g3d_validate_context(dpy, &gctx->base); - if (gdraw->base.Type == EGL_WINDOW_BIT) { - gctx->base.WindowRenderBuffer = - (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ? - EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; - } + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi); + if (gread != gdraw) { + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, + gread->stfbi); + } + + if (gdraw->base.Type == EGL_WINDOW_BIT) { + gctx->base.WindowRenderBuffer = + (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ? + EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; } } } else if (old_gctx) { - ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL); + ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL); old_gctx->base.WindowRenderBuffer = EGL_NONE; } @@ -947,15 +736,17 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) return EGL_TRUE; /* or when the surface is single-buffered */ - if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) + if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) return EGL_TRUE; if (ctx && ctx->DrawSurface == surf) gctx = egl_g3d_context(ctx); /* flush if the surface is current */ - if (gctx) - gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); + if (gctx) { + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } return gsurf->native->swap_buffers(gsurf->native); } @@ -995,7 +786,7 @@ get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, return NULL; psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], - 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE); + 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); pipe_texture_reference(&textures[natt], NULL); return psurf; @@ -1013,7 +804,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, struct pipe_screen *screen = gdpy->native->screen; struct pipe_surface *psurf; - if (!gsurf->render_surface) + if (!gsurf->render_texture) return EGL_TRUE; gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); @@ -1028,26 +819,33 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, /* flush if the surface is current */ if (ctx && ctx->DrawSurface == &gsurf->base) { struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_flush(gctx->st_ctx, + gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); } + /* create a pipe context to copy surfaces */ + if (!gdpy->pipe) { + gdpy->pipe = + gdpy->native->screen->context_create(gdpy->native->screen, NULL); + if (!gdpy->pipe) + return EGL_FALSE; + } + psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); if (psurf) { - struct pipe_context pipe; + struct pipe_surface *psrc; - /** - * XXX This is hacky. If we might allow the EGLDisplay to create a pipe - * context of its own and use the blitter context for this. - */ - memset(&pipe, 0, sizeof(pipe)); - pipe.screen = screen; + psrc = screen->get_tex_surface(screen, gsurf->render_texture, + 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + if (psrc) { + gdpy->pipe->surface_copy(gdpy->pipe, psurf, 0, 0, + psrc, 0, 0, psurf->width, psurf->height); + pipe_surface_reference(&psrc, NULL); - util_surface_copy(&pipe, FALSE, psurf, 0, 0, - gsurf->render_surface, 0, 0, psurf->width, psurf->height); + nsurf->flush_frontbuffer(nsurf); + } pipe_surface_reference(&psurf, NULL); - nsurf->flush_frontbuffer(nsurf); } nsurf->destroy(nsurf); @@ -1058,8 +856,16 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, static EGLBoolean egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_finish(gctx->st_ctx); + struct pipe_screen *screen = gdpy->native->screen; + struct pipe_fence_handle *fence = NULL; + + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + screen->fence_finish(screen, fence, 0); + screen->fence_reference(screen, &fence, NULL); + return EGL_TRUE; } @@ -1089,10 +895,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) /* in case this is called before a display is initialized */ egl_g3d_init_st(&gdrv->base); - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - const struct egl_g3d_st *stapi = gdrv->stapis[i]; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; if (stapi) { - proc = (_EGLProc) stapi->st_get_proc_address(procname); + proc = (_EGLProc) stapi->get_proc_address(stapi, procname); if (proc) return proc; } @@ -1108,8 +914,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); struct egl_g3d_context *gctx; - enum pipe_format target_format; - int target; + enum pipe_format internal_format; + enum st_texture_type target; if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); @@ -1120,10 +926,10 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, switch (gsurf->base.TextureFormat) { case EGL_TEXTURE_RGB: - target_format = PIPE_FORMAT_R8G8B8_UNORM; + internal_format = PIPE_FORMAT_R8G8B8_UNORM; break; case EGL_TEXTURE_RGBA: - target_format = PIPE_FORMAT_B8G8R8A8_UNORM; + internal_format = PIPE_FORMAT_B8G8R8A8_UNORM; break; default: return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); @@ -1139,21 +945,24 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, if (!es1) return EGL_TRUE; - if (!gsurf->render_surface) + if (!gsurf->render_texture) return EGL_FALSE; /* flush properly if the surface is bound */ if (gsurf->base.CurrentContext) { gctx = egl_g3d_context(gsurf->base.CurrentContext); - gctx->stapi->st_flush(gctx->st_ctx, + gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); } gctx = egl_g3d_context(es1); - gctx->stapi->st_bind_texture_surface(gsurf->render_surface, - target, gsurf->base.MipmapLevel, target_format); - - gsurf->base.BoundToTexture = EGL_TRUE; + if (gctx->stctxi->teximage) { + if (!gctx->stctxi->teximage(gctx->stctxi, target, + gsurf->base.MipmapLevel, internal_format, + gsurf->render_texture, gsurf->base.MipmapTexture)) + return EGL_FALSE; + gsurf->base.BoundToTexture = EGL_TRUE; + } return EGL_TRUE; } @@ -1170,14 +979,15 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, if (buffer != EGL_BACK_BUFFER) return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); - if (gsurf->render_surface) { + if (gsurf->render_texture) { _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); struct egl_g3d_context *gctx = egl_g3d_context(ctx); /* what if the context the surface binds to is no longer current? */ - if (gctx) - gctx->stapi->st_unbind_texture_surface(gsurf->render_surface, - ST_TEXTURE_2D, gsurf->base.MipmapLevel); + if (gctx) { + gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D, + gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE); + } } gsurf->base.BoundToTexture = EGL_FALSE; @@ -1289,6 +1099,12 @@ static void egl_g3d_unload(_EGLDriver *drv) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + EGLint i; + + for (i = 0; i < ST_API_COUNT; i++) { + if (gdrv->stapis[i]) + gdrv->stapis[i]->destroy(gdrv->stapis[i]); + } egl_g3d_destroy_probe(drv, NULL); free(gdrv); diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index e3e55e46d3b..2788f1bf4ac 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -39,11 +39,11 @@ #include "eglmode.h" #include "native.h" -#include "egl_st.h" +#include "egl_g3d_st.h" struct egl_g3d_driver { _EGLDriver base; - const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS]; + struct st_api *stapis[ST_API_COUNT]; EGLint api_mask; EGLint probe_key; @@ -51,35 +51,34 @@ struct egl_g3d_driver { struct egl_g3d_display { struct native_display *native; -}; -struct egl_g3d_buffer { - struct st_framebuffer *st_fb; - uint attachment_mask; + struct st_manager *smapi; + struct pipe_context *pipe; }; struct egl_g3d_context { _EGLContext base; - const struct egl_g3d_st *stapi; - struct pipe_context *pipe; + struct st_api *stapi; - struct st_context *st_ctx; - EGLBoolean force_validate; - struct egl_g3d_buffer draw, read; + struct st_context_iface *stctxi; }; struct egl_g3d_surface { _EGLSurface base; + + struct st_visual stvis; + struct st_framebuffer_iface *stfbi; + struct native_surface *native; - enum native_attachment render_att; - struct pipe_surface *render_surface; + struct pipe_texture *render_texture; unsigned int sequence_number; }; struct egl_g3d_config { _EGLConfig base; const struct native_config *native; + struct st_visual stvis; }; struct egl_g3d_image { diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c new file mode 100644 index 00000000000..36094096d36 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -0,0 +1,227 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_dl.h" +#include "eglimage.h" +#include "eglmutex.h" + +#include "egl_g3d.h" +#include "egl_g3d_st.h" + +struct egl_g3d_st_manager { + struct st_manager base; + _EGLDisplay *display; +}; + +static INLINE struct egl_g3d_st_manager * +egl_g3d_st_manager(struct st_manager *smapi) +{ + return (struct egl_g3d_st_manager *) smapi; +} + +struct st_api * +egl_g3d_create_st_api(enum st_api_type api) +{ + const char *stmod_name; + struct util_dl_library *lib; + const struct st_module *mod; + + switch (api) { + case ST_API_OPENGL: + stmod_name = ST_MODULE_OPENGL_SYMBOL; + break; + case ST_API_OPENGL_ES1: + stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL; + break; + case ST_API_OPENGL_ES2: + stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL; + break; + case ST_API_OPENVG: + stmod_name = ST_MODULE_OPENVG_SYMBOL; + break; + default: + stmod_name = NULL; + break; + } + if (!stmod_name) + return NULL; + + mod = NULL; + lib = util_dl_open(NULL); + if (lib) { + mod = (const struct st_module *) + util_dl_get_proc_address(lib, stmod_name); + util_dl_close(lib); + } + if (!mod || mod->api != api) + return NULL; + + return mod->create_api(); +} + +struct st_manager * +egl_g3d_create_st_manager(_EGLDisplay *dpy) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_st_manager *gsmapi; + + gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); + if (gsmapi) { + gsmapi->display = dpy; + + gsmapi->base.screen = gdpy->native->screen; + } + + return &gsmapi->base;; +} + +void +egl_g3d_destroy_st_manager(struct st_manager *smapi) +{ + struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); + free(gsmapi); +} + +static boolean +egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + return gsurf->native->flush_frontbuffer(gsurf->native); +} + +static boolean +egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_texture **out) +{ + _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + uint attachment_mask = 0; + unsigned i; + + for (i = 0; i < count; i++) { + int natt; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + natt = NATIVE_ATTACHMENT_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + natt = NATIVE_ATTACHMENT_BACK_RIGHT; + default: + natt = -1; + break; + } + + if (natt >= 0) + attachment_mask |= 1 << natt; + } + + if (!gsurf->native->validate(gsurf->native, attachment_mask, + &gsurf->sequence_number, textures, &gsurf->base.Width, + &gsurf->base.Height)) + return FALSE; + + for (i = 0; i < count; i++) { + struct pipe_texture *tex; + int natt; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + natt = NATIVE_ATTACHMENT_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + natt = NATIVE_ATTACHMENT_BACK_RIGHT; + break; + default: + natt = -1; + break; + } + + if (natt >= 0) { + tex = textures[natt]; + + if (statts[i] == stfbi->visual->render_buffer) + pipe_texture_reference(&gsurf->render_texture, tex); + + if (attachment_mask & (1 << natt)) { + /* transfer the ownership to the caller */ + out[i] = tex; + attachment_mask &= ~(1 << natt); + } + else { + /* the attachment is listed more than once */ + pipe_texture_reference(&out[i], tex); + } + } + } + + return TRUE; +} + +struct st_framebuffer_iface * +egl_g3d_create_st_framebuffer(_EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct st_framebuffer_iface *stfbi; + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + if (!stfbi) + return NULL; + + stfbi->visual = &gsurf->stvis; + stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; + stfbi->validate = egl_g3d_st_framebuffer_validate; + stfbi->st_manager_private = (void *) &gsurf->base; + + return stfbi; +} + +void +egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + free(stfbi); +} diff --git a/src/gallium/state_trackers/egl/common/egl_st.h b/src/gallium/state_trackers/egl/common/egl_g3d_st.h index 8fb464bd3d7..ea8b4068cd8 100644 --- a/src/gallium/state_trackers/egl/common/egl_st.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 7.8 + * Version: 7.9 * - * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> + * Copyright (C) 2010 LunarG Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,54 +20,60 @@ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> */ -#ifndef _EGL_ST_H_ -#define _EGL_ST_H_ - -#include "GL/gl.h" /* for GL types */ -#include "GL/internal/glcore.h" /* for __GLcontextModes */ +#ifndef _EGL_G3D_ST_H_ +#define _EGL_G3D_ST_H_ #include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" +#include "state_tracker/st_api.h" +#include "egltypedefs.h" -/* avoid calling st functions directly */ -#if 1 +struct st_api * +egl_g3d_create_st_api(enum st_api_type api); -#define ST_SURFACE_FRONT_LEFT 0 -#define ST_SURFACE_BACK_LEFT 1 -#define ST_SURFACE_FRONT_RIGHT 2 -#define ST_SURFACE_BACK_RIGHT 3 +struct st_manager * +egl_g3d_create_st_manager(_EGLDisplay *dpy); -#define ST_TEXTURE_2D 0x2 +void +egl_g3d_destroy_st_manager(struct st_manager *smapi); -struct st_context; -struct st_framebuffer; -typedef void (*st_proc)(); +struct st_framebuffer_iface * +egl_g3d_create_st_framebuffer(_EGLSurface *surf); -#else -#include "state_tracker/st_public.h" -#endif +void +egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); -/* remember to update egl_g3d_get_st() when update the enums */ -enum egl_g3d_st_api { - EGL_G3D_ST_OPENGL_ES = 0, - EGL_G3D_ST_OPENVG, - EGL_G3D_ST_OPENGL_ES2, - EGL_G3D_ST_OPENGL, - - NUM_EGL_G3D_STS -}; +/** + * Return the EGL_<api>_BIT of the st api. + */ +static INLINE int +egl_g3d_st_api_bit(enum st_api_type api) +{ + int bit; -struct egl_g3d_st { -#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__); -#include "st_public_tmp.h" - /* fields must be added here */ - EGLint api_bit; -}; + switch (api) { + case ST_API_OPENGL: + bit = EGL_OPENGL_BIT; + break; + case ST_API_OPENGL_ES1: + bit = EGL_OPENGL_ES_BIT; + break; + case ST_API_OPENGL_ES2: + bit = EGL_OPENGL_ES2_BIT; + break; + case ST_API_OPENVG: + bit = EGL_OPENVG_BIT; + break; + default: + bit = 0; + break; + } -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api); + return bit; +} -#endif /* _EGL_ST_H_ */ +#endif /* _EGL_G3D_ST_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_st.c b/src/gallium/state_trackers/egl/common/egl_st.c deleted file mode 100644 index a88ff911cd5..00000000000 --- a/src/gallium/state_trackers/egl/common/egl_st.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 7.8 - * - * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> - * - * 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 <dlfcn.h> -#include "pipe/p_compiler.h" -#include "util/u_memory.h" -#include "egllog.h" -#include "EGL/egl.h" /* for EGL_api_BIT */ - -#include "egl_st.h" - -#ifndef HAVE_DLADDR -#define HAVE_DLADDR 1 -#endif - -#if HAVE_DLADDR - -static const char * -egl_g3d_st_names[] = { -#define ST_PUBLIC(name, ...) #name, -#include "st_public_tmp.h" - NULL -}; - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ - st_proc *procs = (st_proc *) stapi; - void *handle; - Dl_info info; - const char **name; - - if (!dladdr(sym, &info)) - return FALSE; - handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); - if (!handle) - return FALSE; - - for (name = egl_g3d_st_names; *name; name++) { - st_proc proc = (st_proc) dlsym(handle, *name); - if (!proc) { - _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname); - memset(stapi, 0, sizeof(*stapi)); - dlclose(handle); - return FALSE; - } - *procs++ = proc; - } - - dlclose(handle); - return TRUE; -} - -#else /* HAVE_DLADDR */ - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ -#define ST_PUBLIC(name, ...) stapi->name = name; -#include "st_public_tmp.h" - return TRUE; -} - -#endif /* HAVE_DLADDR */ - -static boolean -egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api) -{ - void *handle, *sym; - boolean res = FALSE; - - /* already initialized */ - if (stapi->st_notify_swapbuffers != NULL) - return TRUE; - - handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); - if (!handle) - return FALSE; - - sym = dlsym(handle, api); - if (sym && egl_g3d_fill_st(stapi, sym)) - res = TRUE; - - dlclose(handle); - return res; -} - -static struct { - const char *symbol; - EGLint api_bit; -} egl_g3d_st_info[NUM_EGL_G3D_STS] = { - { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT }, - { "st_api_OpenVG", EGL_OPENVG_BIT }, - { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT }, - { "st_api_OpenGL", EGL_OPENGL_BIT }, -}; - -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api) -{ - static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS]; - - if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) { - all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit; - return &all_trackers[api]; - } - else { - return NULL; - } -} diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 9c22ff3e432..93c81b26e10 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -140,9 +140,6 @@ struct native_config { struct native_display { /** * The pipe screen of the native display. - * - * Note that the "flush_frontbuffer" and "update_buffer" callbacks will be - * overridden. */ struct pipe_screen *screen; diff --git a/src/gallium/state_trackers/egl/common/st_public_tmp.h b/src/gallium/state_trackers/egl/common/st_public_tmp.h deleted file mode 100644 index 507a0ec4027..00000000000 --- a/src/gallium/state_trackers/egl/common/st_public_tmp.h +++ /dev/null @@ -1,20 +0,0 @@ -ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share) -ST_PUBLIC(st_destroy_context, void, struct st_context *st) -ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask) -ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData) -ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height) -ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf) -ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height) -ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface) -ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture) -ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb) -ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read) -ST_PUBLIC(st_get_current, struct st_context *, void) -ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence) -ST_PUBLIC(st_finish, void, struct st_context *st) -ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format) -ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level) -ST_PUBLIC(st_get_proc_address, st_proc, const char *procname) -#undef ST_PUBLIC diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c index 94588bfa743..73222408565 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.c +++ b/src/gallium/state_trackers/egl/kms/native_kms.c @@ -55,7 +55,7 @@ kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, templ.format = ksurf->color_format; templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT) - templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + templ.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; } /* create textures */ @@ -100,7 +100,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) for (i = 0; i < num_framebuffers; i++) { struct kms_framebuffer *fb; enum native_attachment natt; - unsigned int handle, stride; + struct winsys_handle whandle; uint block_bits; if (i == 0) { @@ -128,13 +128,17 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) /* TODO detect the real value */ fb->is_passive = TRUE; - if (!kdpy->api->local_handle_from_texture(kdpy->api, - kdpy->base.screen, fb->texture, &stride, &handle)) + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + if (!kdpy->base.screen->texture_get_handle(kdpy->base.screen, + fb->texture, &whandle)) return FALSE; block_bits = util_format_get_blocksizebits(ksurf->color_format); err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height, - block_bits, block_bits, stride, handle, &fb->buffer_id); + block_bits, block_bits, whandle.stride, whandle.handle, + &fb->buffer_id); if (err) { fb->buffer_id = 0; return FALSE; diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 8d2a8b1dffe..98399792311 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -114,6 +114,7 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; struct pipe_texture templ; + struct winsys_handle whandle; uint valid_mask; int i; @@ -171,9 +172,11 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, continue; } - dri2surf->textures[natt] = - dri2dpy->api->texture_from_shared_handle(dri2dpy->api, - dri2dpy->base.screen, &templ, desc, xbuf->pitch, xbuf->name); + memset(&whandle, 0, sizeof(whandle)); + whandle.stride = xbuf->pitch; + whandle.handle = xbuf->name; + dri2surf->textures[natt] = dri2dpy->base.screen->texture_from_handle( + dri2dpy->base.screen, &templ, &whandle); if (dri2surf->textures[natt]) valid_mask |= 1 << natt; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 7b4fe63fa07..c6eb17ab1ac 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -142,16 +142,9 @@ native_create_display(EGLNativeDisplayType dpy, if (!ndpy) { EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING; - boolean use_shm; - - /* - * XXX st/mesa calls pipe_screen::update_buffer in st_validate_state. - * When SHM is used, there is a good chance that the shared memory - * segment is detached before the softpipe tile cache is flushed. - */ - use_shm = FALSE; - _eglLog(level, "use software%s fallback", (use_shm) ? " (SHM)" : ""); - ndpy = x11_create_ximage_display(dpy, event_handler, use_shm); + + _eglLog(level, "use software fallback"); + ndpy = x11_create_ximage_display(dpy, event_handler); } return ndpy; diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 8c6a7d93497..1566524926a 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h @@ -30,8 +30,7 @@ struct native_display * x11_create_ximage_display(EGLNativeDisplayType dpy, - struct native_event_handler *event_handler, - boolean use_xshm); + struct native_event_handler *event_handler); struct native_display * x11_create_dri2_display(EGLNativeDisplayType dpy, diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 3421c1951aa..c6b16354f9b 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -28,17 +28,19 @@ #include <sys/shm.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#include <X11/extensions/XShm.h> #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_format.h" #include "pipe/p_compiler.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" -#include "softpipe/sp_winsys.h" +#include "state_tracker/xlib_sw_winsys.h" +#include "target-helpers/wrap_screen.h" +#include "util/u_debug.h" +#include "softpipe/sp_public.h" +#include "llvmpipe/lp_public.h" +#include "cell/ppu/cell_public.h" #include "egllog.h" -#include "sw_winsys.h" #include "native_x11.h" #include "x11_screen.h" @@ -53,24 +55,18 @@ struct ximage_display { Display *dpy; boolean own_dpy; - struct x11_screen *xscr; - int xscr_number; - struct native_event_handler *event_handler; - boolean use_xshm; + struct x11_screen *xscr; + int xscr_number; - struct pipe_winsys *winsys; struct ximage_config *configs; int num_configs; }; struct ximage_buffer { - XImage *ximage; - struct pipe_texture *texture; - XShmSegmentInfo *shm_info; - boolean xshm_attached; + struct xlib_drawable xdraw; }; struct ximage_surface { @@ -81,13 +77,13 @@ struct ximage_surface { XVisualInfo visual; struct ximage_display *xdpy; - GC gc; - unsigned int server_stamp; unsigned int client_stamp; int width, height; struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; + + struct pipe_surface *draw_surface; }; struct ximage_config { @@ -121,18 +117,6 @@ ximage_surface_free_buffer(struct native_surface *nsurf, struct ximage_buffer *xbuf = &xsurf->buffers[which]; pipe_texture_reference(&xbuf->texture, NULL); - - if (xbuf->shm_info) { - if (xbuf->xshm_attached) - XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info); - if (xbuf->shm_info->shmaddr != (void *) -1) - shmdt(xbuf->shm_info->shmaddr); - if (xbuf->shm_info->shmid != -1) - shmctl(xbuf->shm_info->shmid, IPC_RMID, 0); - - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->shmid = -1; - } } static boolean @@ -156,40 +140,25 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, templ.depth0 = 1; templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - if (xbuf->shm_info) { - struct pipe_buffer *pbuf; - unsigned stride, size; - void *addr = NULL; - - stride = util_format_get_stride(xsurf->color_format, xsurf->width); - /* alignment should depend on visual? */ - stride = align(stride, 4); - size = stride * xsurf->height; - - /* create and attach shm object */ - xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755); - if (xbuf->shm_info->shmid != -1) { - xbuf->shm_info->shmaddr = - shmat(xbuf->shm_info->shmid, NULL, 0); - if (xbuf->shm_info->shmaddr != (void *) -1) { - if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) { - addr = xbuf->shm_info->shmaddr; - xbuf->xshm_attached = TRUE; - } - } - } - - if (addr) { - pbuf = screen->user_buffer_create(screen, addr, size); - if (pbuf) { - xbuf->texture = - screen->texture_blanket(screen, &templ, &stride, pbuf); - pipe_buffer_reference(&pbuf, NULL); - } + if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { + switch (which) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + case NATIVE_ATTACHMENT_FRONT_RIGHT: + templ.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + case NATIVE_ATTACHMENT_BACK_RIGHT: + templ.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + break; + default: + break; } } - else { - xbuf->texture = screen->texture_create(screen, &templ); + xbuf->texture = screen->texture_create(screen, &templ); + if (xbuf->texture) { + xbuf->xdraw.visual = xsurf->visual.visual; + xbuf->xdraw.depth = xsurf->visual.depth; + xbuf->xdraw.drawable = xsurf->drawable; } /* clean up the buffer if allocation failed */ @@ -269,18 +238,10 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) new_valid = 0x0; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(buffer_mask, att)) { - struct ximage_buffer *xbuf = &xsurf->buffers[att]; - /* reallocate the texture */ if (!ximage_surface_alloc_buffer(&xsurf->base, att)) break; - /* update ximage */ - if (xbuf->ximage) { - xbuf->ximage->width = xsurf->width; - xbuf->ximage->height = xsurf->height; - } - new_valid |= (1 << att); if (buffer_mask == new_valid) break; @@ -300,43 +261,26 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; - struct pipe_transfer *transfer; + struct pipe_surface *psurf; if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) return TRUE; - assert(xsurf->drawable && xbuf->ximage && xbuf->texture); + assert(xsurf->drawable && xbuf->texture); - transfer = screen->get_tex_transfer(screen, xbuf->texture, - 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); - if (!transfer) - return FALSE; + psurf = xsurf->draw_surface; + if (!psurf || psurf->texture != xbuf->texture) { + pipe_surface_reference(&xsurf->draw_surface, NULL); - xbuf->ximage->bytes_per_line = transfer->stride; - xbuf->ximage->data = screen->transfer_map(screen, transfer); - if (!xbuf->ximage->data) { - screen->tex_transfer_destroy(transfer); - return FALSE; - } - - - if (xbuf->shm_info) - XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False); - else - XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height); - - xbuf->ximage->data = NULL; - screen->transfer_unmap(screen, transfer); + psurf = screen->get_tex_surface(screen, + xbuf->texture, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ); + if (!psurf) + return FALSE; - /* - * softpipe allows the pipe transfer to be re-used, but we don't want to - * rely on that behavior. - */ - screen->tex_transfer_destroy(transfer); + xsurf->draw_surface = psurf; + } - XSync(xsurf->xdpy->dpy, FALSE); + screen->flush_frontbuffer(screen, psurf, &xbuf->xdraw); return TRUE; } @@ -364,7 +308,8 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) boolean ret; /* display the back buffer first */ - ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + ret = ximage_surface_draw_buffer(&xsurf->base, + NATIVE_ATTACHMENT_BACK_LEFT); /* force buffers to be updated in next validation call */ xsurf->server_stamp++; ximage_surface_notify_invalid(&xsurf->base); @@ -372,13 +317,12 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; - /* skip swapping so that the front buffer is allocated only when needed */ - if (!xfront->texture) - return ret; - - xtmp = *xfront; - *xfront = *xback; - *xback = xtmp; + /* skip swapping unless there is a front buffer */ + if (xfront->texture) { + xtmp = *xfront; + *xfront = *xback; + *xback = xtmp; + } return ret; } @@ -433,18 +377,11 @@ ximage_surface_destroy(struct native_surface *nsurf) struct ximage_surface *xsurf = ximage_surface(nsurf); int i; - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; + pipe_surface_reference(&xsurf->draw_surface, NULL); + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) ximage_surface_free_buffer(&xsurf->base, i); - /* xbuf->shm_info is owned by xbuf->ximage? */ - if (xbuf->ximage) { - XDestroyImage(xbuf->ximage); - xbuf->ximage = NULL; - } - } - if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) - XFreeGC(xsurf->xdpy->dpy, xsurf->gc); free(xsurf); } @@ -457,7 +394,6 @@ ximage_display_create_surface(struct native_display *ndpy, struct ximage_display *xdpy = ximage_display(ndpy); struct ximage_config *xconf = ximage_config(nconf); struct ximage_surface *xsurf; - int i; xsurf = CALLOC_STRUCT(ximage_surface); if (!xsurf) @@ -471,52 +407,8 @@ ximage_display_create_surface(struct native_display *ndpy, if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { xsurf->drawable = drawable; xsurf->visual = *xconf->visual; - - xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL); - if (!xsurf->gc) { - free(xsurf); - return NULL; - } - /* initialize the geometry */ ximage_surface_update_buffers(&xsurf->base, 0x0); - - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; - - if (xdpy->use_xshm) { - xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info)); - if (xbuf->shm_info) { - /* initialize shm info */ - xbuf->shm_info->shmid = -1; - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->readOnly = TRUE; - - xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, NULL, - xbuf->shm_info, - 0, 0); - } - } - else { - xbuf->ximage = XCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 8, /* bitmap_pad */ - 0); /* bytes_per_line */ - } - - if (!xbuf->ximage) { - XFreeGC(xdpy->dpy, xsurf->gc); - free(xsurf); - return NULL; - } - } } xsurf->base.destroy = ximage_surface_destroy; @@ -727,7 +619,6 @@ ximage_display_destroy(struct native_display *ndpy) free(xdpy->configs); xdpy->base.screen->destroy(xdpy->base.screen); - free(xdpy->winsys); x11_screen_destroy(xdpy->xscr); if (xdpy->own_dpy) @@ -735,10 +626,63 @@ ximage_display_destroy(struct native_display *ndpy) free(xdpy); } + +/* Helper function to build a subset of a driver stack consisting of + * one of the software rasterizers (cell, llvmpipe, softpipe) and the + * xlib winsys. + * + * This function could be shared, but currently causes headaches for + * the build systems, particularly scons if we try. + * + * Long term, want to avoid having global #defines for things like + * GALLIUM_LLVMPIPE, GALLIUM_CELL, etc. Scons already eliminates + * those #defines, so things that are painful for it now are likely to + * be painful for other build systems in the future. + */ +static struct pipe_screen * +swrast_xlib_create_screen( Display *display ) +{ + struct sw_winsys *winsys; + struct pipe_screen *screen = NULL; + + /* Create the underlying winsys, which performs presents to Xlib + * drawables: + */ + winsys = xlib_create_sw_winsys( display ); + if (winsys == NULL) + return NULL; + + /* Create a software rasterizer on top of that winsys. Use + * llvmpipe if it is available. + */ +#if defined(GALLIUM_LLVMPIPE) + if (screen == NULL && + !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE)) + screen = llvmpipe_create_screen( winsys ); +#endif + + if (screen == NULL) + screen = softpipe_create_screen( winsys ); + + if (screen == NULL) + goto fail; + + /* Inject any wrapping layers we want to here: + */ + return gallium_wrap_screen( screen ); + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; +} + + + struct native_display * x11_create_ximage_display(EGLNativeDisplayType dpy, - struct native_event_handler *event_handler, - boolean use_xshm) + struct native_event_handler *event_handler) { struct ximage_display *xdpy; @@ -756,6 +700,8 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, xdpy->own_dpy = TRUE; } + xdpy->event_handler = event_handler; + xdpy->xscr_number = DefaultScreen(xdpy->dpy); xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); if (!xdpy->xscr) { @@ -763,13 +709,7 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, return NULL; } - xdpy->event_handler = event_handler; - - xdpy->use_xshm = - (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM)); - - xdpy->winsys = create_sw_winsys(); - xdpy->base.screen = softpipe_create_screen(xdpy->winsys); + xdpy->base.screen = swrast_xlib_create_screen(xdpy->dpy); xdpy->base.destroy = ximage_display_destroy; xdpy->base.get_param = ximage_display_get_param; diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.c b/src/gallium/state_trackers/egl/x11/sw_winsys.c deleted file mode 100644 index 33328aadf26..00000000000 --- a/src/gallium/state_trackers/egl/x11/sw_winsys.c +++ /dev/null @@ -1,231 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * Totally software-based winsys layer. - * Note that the one winsys function that we can't implement here - * is flush_frontbuffer(). - * Whoever uses this code will have to provide that. - * - * Authors: Brian Paul - */ - - -#include "util/u_simple_screen.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "sw_winsys.h" - - - -/** Subclass of pipe_winsys */ -struct sw_pipe_winsys -{ - struct pipe_winsys Base; - /* no extra fields for now */ -}; - - -/** subclass of pipe_buffer */ -struct sw_pipe_buffer -{ - struct pipe_buffer Base; - boolean UserBuffer; /** Is this a user-space buffer? */ - void *Data; - void *Mapped; -}; - - -/** cast wrapper */ -static INLINE struct sw_pipe_buffer * -sw_pipe_buffer(struct pipe_buffer *b) -{ - return (struct sw_pipe_buffer *) b; -} - - -static const char * -get_name(struct pipe_winsys *pws) -{ - return "software"; -} - - -/** Create new pipe_buffer and allocate storage of given size */ -static struct pipe_buffer * -buffer_create(struct pipe_winsys *pws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.alignment = alignment; - buffer->Base.usage = usage; - buffer->Base.size = size; - - /* align to 16-byte multiple for Cell */ - buffer->Data = align_malloc(size, MAX2(alignment, 16)); - - return &buffer->Base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.size = bytes; - buffer->UserBuffer = TRUE; - buffer->Data = ptr; - - return &buffer->Base; -} - - -static void * -buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = buffer->Data; - return buffer->Mapped; -} - - -static void -buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = NULL; -} - - -static void -buffer_destroy(struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - - if (buffer->Data && !buffer->UserBuffer) { - align_free(buffer->Data); - buffer->Data = NULL; - } - - free(buffer); -} - - -static struct pipe_buffer * -surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ - /* no-op */ -} - - -static int -fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -static int -fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -/** - * Create/return a new pipe_winsys object. - */ -struct pipe_winsys * -create_sw_winsys(void) -{ - struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys); - if (!ws) - return NULL; - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - */ - ws->Base.buffer_create = buffer_create; - ws->Base.user_buffer_create = user_buffer_create; - ws->Base.buffer_map = buffer_map; - ws->Base.buffer_unmap = buffer_unmap; - ws->Base.buffer_destroy = buffer_destroy; - - ws->Base.surface_buffer_create = surface_buffer_create; - - ws->Base.fence_reference = fence_reference; - ws->Base.fence_signalled = fence_signalled; - ws->Base.fence_finish = fence_finish; - - ws->Base.flush_frontbuffer = NULL; /* not implemented here! */ - - ws->Base.get_name = get_name; - - return &ws->Base; -} diff --git a/src/gallium/state_trackers/es/Makefile b/src/gallium/state_trackers/es/Makefile index b0365512719..e33685d2471 100644 --- a/src/gallium/state_trackers/es/Makefile +++ b/src/gallium/state_trackers/es/Makefile @@ -38,6 +38,7 @@ SYS_LIBS = -lm -pthread INCLUDE_DIRS = \ + -I$(TOP)/src/mesa \ -I$(TOP)/src/gallium/include .c.o: diff --git a/src/gallium/state_trackers/es/st_es1.c b/src/gallium/state_trackers/es/st_es1.c index 25bc53b21eb..4e89e06b34c 100644 --- a/src/gallium/state_trackers/es/st_es1.c +++ b/src/gallium/state_trackers/es/st_es1.c @@ -1,3 +1,8 @@ -#include "pipe/p_compiler.h" +#include "state_tracker/st_manager.h" PUBLIC const int st_api_OpenGL_ES1 = 1; + +PUBLIC const struct st_module st_module_OpenGL_ES1 = { + .api = ST_API_OPENGL_ES1, + .create_api = st_manager_create_api +}; diff --git a/src/gallium/state_trackers/es/st_es2.c b/src/gallium/state_trackers/es/st_es2.c index 171ea62b97f..82e88b176ac 100644 --- a/src/gallium/state_trackers/es/st_es2.c +++ b/src/gallium/state_trackers/es/st_es2.c @@ -1,3 +1,8 @@ -#include "pipe/p_compiler.h" +#include "state_tracker/st_manager.h" PUBLIC const int st_api_OpenGL_ES2 = 1; + +PUBLIC const struct st_module st_module_OpenGL_ES2 = { + .api = ST_API_OPENGL_ES2, + .create_api = st_manager_create_api +}; diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile index 7b2adc62c34..582e72bb463 100644 --- a/src/gallium/state_trackers/glx/xlib/Makefile +++ b/src/gallium/state_trackers/glx/xlib/Makefile @@ -5,12 +5,14 @@ LIBNAME = xlib LIBRARY_INCLUDES = \ -I$(TOP)/include \ - -I$(TOP)/src/mesa + -I$(TOP)/src/mesa \ + $(X_CFLAGS) C_SOURCES = \ glx_api.c \ glx_getproc.c \ glx_usefont.c \ - xm_api.c + xm_api.c \ + xm_st.c include ../../../Makefile.template diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript index fa96df357d5..d6c16ad2f52 100644 --- a/src/gallium/state_trackers/glx/xlib/SConscript +++ b/src/gallium/state_trackers/glx/xlib/SConscript @@ -13,8 +13,6 @@ if env['platform'] == 'linux' \ '#/src/mesa/main', ]) - env.Append(CPPDEFINES = ['USE_XSHM']) - st_xlib = env.ConvenienceLibrary( target = 'st_xlib', source = [ @@ -22,6 +20,7 @@ if env['platform'] == 'linux' \ 'glx_getproc.c', 'glx_usefont.c', 'xm_api.c', + 'xm_st.c', ] ) Export('st_xlib') diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 08bf624b5c1..4930cd6cd50 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_api.c +++ b/src/gallium/state_trackers/glx/xlib/glx_api.c @@ -35,12 +35,9 @@ #include "xm_api.h" #include "main/context.h" -#include "main/config.h" #include "main/macros.h" #include "main/imports.h" #include "main/version.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" /* This indicates the client-side GLX API and GLX encoder version. */ @@ -689,7 +686,7 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) int desiredVisualID = -1; int numAux = 0; - xmesa_init(); + xmesa_init( dpy ); parselist = list; @@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, if (MakeCurrent_PrevContext == src) { _mesa_Flush(); } - st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask ); + XMesaCopyContext(xm_src, xm_dst, mask); } diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index 217bdeff75e..62a2bfcfa07 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -35,10 +35,6 @@ * corner of the window. Therefore, most drawing functions in this * file have to flip Y coordinates. * - * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile - * in support for the MIT Shared Memory extension. If enabled, when you - * use an Ximage for the back buffer in double buffered mode, the "swap" - * operation will be faster. You must also link with -lXext. * * Byte swapping: If the Mesa host and the X display use a different * byte order then there's some trickiness to be aware of when using @@ -58,20 +54,14 @@ #endif #include "xm_api.h" -#include "main/context.h" -#include "main/framebuffer.h" +#include "xm_st.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" +#include "main/context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" -#include "trace/tr_screen.h" -#include "trace/tr_context.h" -#include "trace/tr_texture.h" - -#include "xm_winsys.h" +#include "xm_public.h" #include <GL/glx.h> @@ -80,20 +70,56 @@ * global. */ static struct xm_driver driver; +static struct st_api *stapi; void xmesa_set_driver( const struct xm_driver *templ ) { driver = *templ; + stapi = driver.create_st_api(); } -/** - * Global X driver lock - */ -pipe_mutex _xmesa_lock; +static XMesaDisplay +xmesa_init_display( Display *display ) +{ + pipe_static_mutex(init_mutex); + static struct xmesa_display xm_display; + XMesaDisplay xmdpy; + + pipe_mutex_lock(init_mutex); + + /* TODO support for multiple displays */ + xmdpy = &xm_display; + + if (!xmdpy->display && display) { + xmdpy->display = display; + xmdpy->screen = driver.create_pipe_screen(display); + xmdpy->smapi = CALLOC_STRUCT(st_manager); + if (xmdpy->smapi) + xmdpy->smapi->screen = xmdpy->screen; + + if (xmdpy->screen && xmdpy->smapi) { + pipe_mutex_init(xmdpy->mutex); + } + else { + if (xmdpy->screen) { + xmdpy->screen->destroy(xmdpy->screen); + xmdpy->screen = NULL; + } + if (xmdpy->smapi) { + FREE(xmdpy->smapi); + xmdpy->smapi = NULL; + } + + xmdpy->display = NULL; + } + } + if (!xmdpy->display || xmdpy->display != display) + xmdpy = NULL; -static struct pipe_screen *_screen = NULL; -static struct pipe_screen *screen = NULL; + pipe_mutex_unlock(init_mutex); + return xmdpy; +} /**********************************************************************/ /***** X Utility Functions *****/ @@ -111,41 +137,6 @@ static int host_byte_order( void ) } -/** - * Check if the X Shared Memory extension is available. - * Return: 0 = not available - * 1 = shared XImage support available - * 2 = shared Pixmap support available also - */ -int xmesa_check_for_xshm( Display *display ) -{ -#if defined(USE_XSHM) - int major, minor, ignore; - Bool pixmaps; - - if (getenv("SP_NO_RAST")) - return 0; - - if (getenv("MESA_NOSHM")) { - return 0; - } - - if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { - if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { - return (pixmaps==True) ? 2 : 1; - } - else { - return 0; - } - } - else { - return 0; - } -#else - /* No XSHM support */ - return 0; -#endif -} /** @@ -238,12 +229,13 @@ void xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height) { + XMesaDisplay xmdpy = xmesa_init_display(dpy); Status stat; - pipe_mutex_lock(_xmesa_lock); + pipe_mutex_lock(xmdpy->mutex); XSync(b->xm_visual->display, 0); /* added for Chromium */ - stat = get_drawable_size(dpy, b->drawable, width, height); - pipe_mutex_unlock(_xmesa_lock); + stat = get_drawable_size(dpy, b->ws.drawable, width, height); + pipe_mutex_unlock(xmdpy->mutex); if (!stat) { /* probably querying a window that's recently been destroyed */ @@ -317,49 +309,43 @@ choose_pixel_format(XMesaVisual v) return 0; } - - /** - * Query the default gallium screen for a Z/Stencil format that - * at least matches the given depthBits and stencilBits. + * Choose a depth/stencil format that is "better" than the given depth and + * stencil sizes. */ -static void -xmesa_choose_z_stencil_format(int depthBits, int stencilBits, - enum pipe_format *depthFormat, - enum pipe_format *stencilFormat) +static enum pipe_format +choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil) { const enum pipe_texture_target target = PIPE_TEXTURE_2D; const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE | PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO); - static enum pipe_format formats[] = { - PIPE_FORMAT_S8Z24_UNORM, - PIPE_FORMAT_Z24S8_UNORM, - PIPE_FORMAT_Z16_UNORM, - PIPE_FORMAT_Z32_UNORM - }; - int i; + enum pipe_format formats[8], fmt; + int count, i; - assert(screen); + count = 0; + if (depth <= 24 && stencil <= 8) { + formats[count++] = PIPE_FORMAT_S8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24S8_UNORM; + } - *depthFormat = *stencilFormat = PIPE_FORMAT_NONE; + if (!stencil) { + if (depth <= 16) + formats[count++] = PIPE_FORMAT_Z16_UNORM; + if (depth <= 32) + formats[count++] = PIPE_FORMAT_Z32_UNORM; + } - /* search for supported format */ - for (i = 0; i < Elements(formats); i++) { - if (screen->is_format_supported(screen, formats[i], + fmt = PIPE_FORMAT_NONE; + for (i = 0; i < count; i++) { + if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], target, tex_usage, geom_flags)) { - *depthFormat = formats[i]; + fmt = formats[i]; break; } } - if (stencilBits) { - *stencilFormat = *depthFormat; - } - - /* XXX we should check that he chosen format has at least as many bits - * as what was requested. - */ + return fmt; } @@ -368,7 +354,7 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits, /***** Linked list of XMesaBuffers *****/ /**********************************************************************/ -XMesaBuffer XMesaBufferList = NULL; +static XMesaBuffer XMesaBufferList = NULL; /** @@ -386,53 +372,33 @@ static XMesaBuffer create_xmesa_buffer(Drawable d, BufferType type, XMesaVisual vis, Colormap cmap) { + XMesaDisplay xmdpy = xmesa_init_display(vis->display); XMesaBuffer b; - GLframebuffer *fb; - enum pipe_format colorFormat, depthFormat, stencilFormat; uint width, height; ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); + if (!xmdpy) + return NULL; + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); if (!b) return NULL; - b->drawable = d; + b->ws.drawable = d; + b->ws.visual = vis->visinfo->visual; + b->ws.depth = vis->visinfo->depth; b->xm_visual = vis; b->type = type; b->cmap = cmap; - /* determine PIPE_FORMATs for buffers */ - colorFormat = choose_pixel_format(vis); - - xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits, - vis->mesa_visual.stencilBits, - &depthFormat, &stencilFormat); - - get_drawable_size(vis->display, d, &width, &height); /* * Create framebuffer, but we'll plug in our own renderbuffers below. */ - b->stfb = st_create_framebuffer(&vis->mesa_visual, - colorFormat, depthFormat, stencilFormat, - width, height, - (void *) b); - fb = &b->stfb->Base; - - /* - * Create scratch XImage for xmesa_display_surface() - */ - b->tempImage = XCreateImage(vis->display, - vis->visinfo->visual, - vis->visinfo->depth, - ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 32, /* bitmap_pad */ - 0); /* bytes_per_line */ + b->stfb = xmesa_create_st_framebuffer(xmdpy, b); /* GLX_EXT_texture_from_pixmap */ b->TextureTarget = 0; @@ -476,29 +442,21 @@ xmesa_free_buffer(XMesaBuffer buffer) for (b = XMesaBufferList; b; b = b->Next) { if (b == buffer) { - struct gl_framebuffer *fb = &buffer->stfb->Base; - /* unlink buffer from list */ if (prev) prev->Next = buffer->Next; else XMesaBufferList = buffer->Next; - /* mark as delete pending */ - fb->DeletePending = GL_TRUE; - /* Since the X window for the XMesaBuffer is going away, we don't * want to dereference this pointer in the future. */ - b->drawable = 0; - - buffer->tempImage->data = NULL; - XDestroyImage(buffer->tempImage); - - /* Unreference. If count = zero we'll really delete the buffer */ - _mesa_reference_framebuffer(&fb, NULL); + b->ws.drawable = 0; - XFreeGC(b->xm_visual->display, b->gc); + /* XXX we should move the buffer to a delete-pending list and destroy + * the buffer until it is no longer current. + */ + xmesa_destroy_st_framebuffer(buffer->stfb); free(buffer); @@ -576,21 +534,6 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); } - if (b && window) { - /* these should have been set in create_xmesa_buffer */ - ASSERT(b->drawable == window); - - /* Setup for single/double buffering */ - if (v->mesa_visual.doubleBufferMode) { - /* Double buffered */ - b->shm = xmesa_check_for_xshm( v->display ); - } - - /* X11 graphics context */ - b->gc = XCreateGC( v->display, window, 0, NULL ); - XSetFunction( v->display, b->gc, GXcopy ); - } - return GL_TRUE; } @@ -670,10 +613,12 @@ XMesaVisual XMesaCreateVisual( Display *display, GLint level, GLint visualCaveat ) { + XMesaDisplay xmdpy = xmesa_init_display(display); XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; - xmesa_init(); + if (!xmdpy) + return NULL; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { @@ -755,6 +700,26 @@ XMesaVisual XMesaCreateVisual( Display *display, accum_blue_size, accum_alpha_size, 0 ); + v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (stereo_flag) { + v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + v->stvis.color_format = choose_pixel_format(v); + v->stvis.depth_stencil_format = + choose_depth_stencil_format(xmdpy, depth_size, stencil_size); + + v->stvis.accum_format = (accum_red_size + + accum_green_size + accum_blue_size + accum_alpha_size) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + v->stvis.samples = num_samples; + v->stvis.render_buffer = ST_ATTACHMENT_INVALID; + /* XXX minor hack */ v->mesa_visual.level = level; return v; @@ -770,18 +735,12 @@ void XMesaDestroyVisual( XMesaVisual v ) /** - * Do one-time initializations. + * Do per-display initializations. */ void -xmesa_init(void) +xmesa_init( Display *display ) { - static GLboolean firstTime = GL_TRUE; - if (firstTime) { - pipe_mutex_init(_xmesa_lock); - _screen = driver.create_pipe_screen(); - screen = trace_screen_create( _screen ); - firstTime = GL_FALSE; - } + xmesa_init_display(display); } @@ -795,51 +754,33 @@ xmesa_init(void) PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { - struct pipe_context *pipe = NULL; + XMesaDisplay xmdpy = xmesa_init_display(v->display); XMesaContext c; - GLcontext *mesaCtx; - uint pf; - xmesa_init(); + if (!xmdpy) + return NULL; /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ c = (XMesaContext) CALLOC_STRUCT(xmesa_context); if (!c) return NULL; - pf = choose_pixel_format(v); - assert(pf); - c->xm_visual = v; c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ c->xm_read_buffer = NULL; - if (screen == NULL) - goto fail; - - /* Trace screen knows how to properly wrap context creation in the - * wrapped screen, so nothing special to do here: - */ - pipe = screen->context_create(screen, (void *) c); - if (pipe == NULL) - goto fail; - - c->st = st_create_context(pipe, - &v->mesa_visual, - share_list ? share_list->st : NULL); + c->st = stapi->create_context(stapi, xmdpy->smapi, + &v->stvis, (share_list) ? share_list->st : NULL); if (c->st == NULL) goto fail; - mesaCtx = c->st->ctx; - c->st->ctx->DriverCtx = c; + c->st->st_manager_private = (void *) c; return c; fail: if (c->st) - st_destroy_context(c->st); - else if (pipe) - pipe->destroy(pipe); + c->st->destroy(c->st); free(c); return NULL; @@ -850,7 +791,7 @@ fail: PUBLIC void XMesaDestroyContext( XMesaContext c ) { - st_destroy_context(c->st); + c->st->destroy(c->st); /* FIXME: We should destroy the screen here, but if we do so, surfaces may * outlive it, causing segfaults @@ -956,7 +897,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, { GET_CURRENT_CONTEXT(ctx); XMesaBuffer b; - GLuint width, height; assert(v); @@ -964,19 +904,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, if (!b) return NULL; - /* get pixmap size, update framebuffer/renderbuffer dims */ - xmesa_get_window_size(v->display, b, &width, &height); - _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height); + /* get pixmap size */ + xmesa_get_window_size(v->display, b, &b->width, &b->height); if (target == 0) { /* examine dims */ if (ctx->Extensions.ARB_texture_non_power_of_two) { target = GLX_TEXTURE_2D_EXT; } - else if ( _mesa_bitcount(width) == 1 - && _mesa_bitcount(height) == 1) { + else if ( _mesa_bitcount(b->width) == 1 + && _mesa_bitcount(b->height) == 1) { /* power of two size */ - if (height == 1) { + if (b->height == 1) { target = GLX_TEXTURE_1D_EXT; } else { @@ -1049,23 +988,20 @@ XMesaDestroyBuffer(XMesaBuffer b) /** - * Query the current window size and update the corresponding GLframebuffer - * and all attached renderbuffers. - * Called when: - * 1. the first time a buffer is bound to a context. - * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too... - * Note: it's possible (and legal) for xmctx to be NULL. That can happen - * when resizing a buffer when no rendering context is bound. + * Query the current drawable size and notify the binding context. */ void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) +xmesa_check_buffer_size(XMesaBuffer b) { - GLuint width, height; - xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height); - st_resize_framebuffer(drawBuffer->stfb, width, height); -} + XMesaContext xmctx = XMesaGetCurrentContext(); + if (b->type == PBUFFER) + return; + xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); + if (xmctx && xmctx->xm_buffer == b) + xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb); +} /* @@ -1092,21 +1028,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, c->xm_read_buffer == readBuffer) return GL_TRUE; + xmesa_check_buffer_size(drawBuffer); + if (readBuffer != drawBuffer) + xmesa_check_buffer_size(readBuffer); + c->xm_buffer = drawBuffer; c->xm_read_buffer = readBuffer; - st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb); - - xmesa_check_and_update_buffer_size(c, drawBuffer); - if (readBuffer != drawBuffer) - xmesa_check_and_update_buffer_size(c, readBuffer); + stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb); /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ drawBuffer->wasCurrent = GL_TRUE; } else { /* Detach */ - st_make_current( NULL, NULL, NULL ); + stapi->make_current(stapi, NULL, NULL, NULL); } return GL_TRUE; @@ -1125,14 +1061,8 @@ GLboolean XMesaUnbindContext( XMesaContext c ) XMesaContext XMesaGetCurrentContext( void ) { - GET_CURRENT_CONTEXT(ctx); - if (ctx) { - XMesaContext xmesa = xmesa_context(ctx); - return xmesa; - } - else { - return 0; - } + struct st_context_iface *st = stapi->get_current(stapi); + return (XMesaContext) (st) ? st->st_manager_private : NULL; } @@ -1144,21 +1074,17 @@ XMesaContext XMesaGetCurrentContext( void ) PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { - struct pipe_surface *frontLeftSurf; - - st_swapbuffers(b->stfb, &frontLeftSurf, NULL); - - if (frontLeftSurf) { - if (_screen != screen) { - struct trace_surface *tr_surf = trace_surface( frontLeftSurf ); - struct pipe_surface *surf = tr_surf->surface; - frontLeftSurf = surf; - } - - driver.display_surface(b, frontLeftSurf); + XMesaContext xmctx = XMesaGetCurrentContext(); + + if (xmctx && xmctx->xm_buffer == b) { + xmctx->st->flush( xmctx->st, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL); } - xmesa_check_and_update_buffer_size(NULL, b); + xmesa_swap_st_framebuffer(b->stfb); } @@ -1168,21 +1094,9 @@ void XMesaSwapBuffers( XMesaBuffer b ) */ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) { - struct pipe_surface *surf_front; - struct pipe_surface *surf_back; - struct pipe_context *pipe = NULL; /* XXX fix */ - - st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front); - st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back); - - if (!surf_front || !surf_back) - return; - - assert(pipe); - pipe->surface_copy(pipe, - surf_front, x, y, /* dest */ - surf_back, x, y, /* src */ - width, height); + xmesa_copy_st_framebuffer(b->stfb, + ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT, + x, y, width, height); } @@ -1190,7 +1104,14 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) void XMesaFlush( XMesaContext c ) { if (c && c->xm_visual->display) { - st_finish(c->st); + XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display); + struct pipe_fence_handle *fence = NULL; + + c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + if (fence) { + xmdpy->screen->fence_finish(xmdpy->screen, fence, 0); + xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); + } XSync( c->xm_visual->display, False ); } } @@ -1203,7 +1124,7 @@ XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d ) { XMesaBuffer b; for (b = XMesaBufferList; b; b = b->Next) { - if (b->drawable == d && b->xm_visual->display == dpy) { + if (b->ws.drawable == d && b->xm_visual->display == dpy) { return b; } } @@ -1237,10 +1158,10 @@ void XMesaGarbageCollect( void ) next = b->Next; if (b->xm_visual && b->xm_visual->display && - b->drawable && + b->ws.drawable && b->type == WINDOW) { XSync(b->xm_visual->display, False); - if (!window_exists( b->xm_visual->display, b->drawable )) { + if (!window_exists( b->xm_visual->display, b->ws.drawable )) { /* found a dead window, free the ancillary info */ XMesaDestroyBuffer( b ); } @@ -1264,3 +1185,10 @@ XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) { } + +void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask) +{ + if (dst->st->copy) + dst->st->copy(dst->st, src->st, mask); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index 004cb260dcd..4f2c8a6e6a9 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -58,25 +58,31 @@ and create a window, you must do the following to use the X/Mesa interface: #include "main/mtypes.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" +#include "state_tracker/st_api.h" #include "os/os_thread.h" +#include "state_tracker/xlib_sw_winsys.h" # include <X11/Xlib.h> # include <X11/Xlibint.h> # include <X11/Xutil.h> -# ifdef USE_XSHM /* was SHM */ -# include <sys/ipc.h> -# include <sys/shm.h> -# include <X11/extensions/XShm.h> -# endif +typedef struct xmesa_display *XMesaDisplay; typedef struct xmesa_buffer *XMesaBuffer; typedef struct xmesa_context *XMesaContext; typedef struct xmesa_visual *XMesaVisual; +struct xmesa_display { + pipe_mutex mutex; + + Display *display; + struct pipe_screen *screen; + struct st_manager *smapi; + + struct pipe_context *pipe; +}; + /* * Create a new X/Mesa visual. @@ -262,16 +268,13 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, int format, int target, int mipmap); +extern void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask); /*********************************************************************** */ -extern pipe_mutex _xmesa_lock; - -extern struct xmesa_buffer *XMesaBufferList; - - /** * Visual inforation, derived from GLvisual. * Basically corresponds to an XVisualInfo. @@ -284,6 +287,8 @@ struct xmesa_visual { GLint BitsPerPixel; /* True bits per pixel for XImages */ GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ + + struct st_visual stvis; }; @@ -292,7 +297,7 @@ struct xmesa_visual { * Basically corresponds to a GLXContext. */ struct xmesa_context { - struct st_context *st; + struct st_context_iface *st; XMesaVisual xm_visual; /** pixel format info */ XMesaBuffer xm_buffer; /** current drawbuffer */ XMesaBuffer xm_read_buffer; /** current readbuffer */ @@ -315,7 +320,8 @@ typedef enum { * Basically corresponds to a GLXDrawable. */ struct xmesa_buffer { - struct st_framebuffer *stfb; + struct st_framebuffer_iface *stfb; + struct xlib_drawable ws; GLboolean wasCurrent; /* was ever the current buffer? */ XMesaVisual xm_visual; /* the X/Mesa visual */ @@ -329,13 +335,6 @@ struct xmesa_buffer { XImage *tempImage; unsigned long selectedEvents;/* for pbuffers only */ - GLuint shm; /* X Shared Memory extension status: */ - /* 0 = not available */ - /* 1 = XImage support available */ - /* 2 = Pixmap support available too */ -#if defined(USE_XSHM) - XShmSegmentInfo shminfo; -#endif GC gc; /* scratch GC for span, line, tri drawing */ @@ -345,32 +344,14 @@ struct xmesa_buffer { GLint TextureMipmap; /** 0 or 1 */ struct xmesa_buffer *Next; /* Linked list pointer: */ -}; + unsigned width, height; +}; -/** cast wrapper */ -static INLINE XMesaContext -xmesa_context(GLcontext *ctx) -{ - return (XMesaContext) ctx->DriverCtx; -} - - -/** cast wrapper */ -static INLINE XMesaBuffer -xmesa_buffer(GLframebuffer *fb) -{ - struct st_framebuffer *stfb = (struct st_framebuffer *) fb; - return (XMesaBuffer) st_framebuffer_private(stfb); -} - - -extern void -xmesa_init(void); extern void -xmesa_delete_framebuffer(struct gl_framebuffer *fb); +xmesa_init(Display *dpy); extern XMesaBuffer xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis); @@ -380,7 +361,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height); extern void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer); +xmesa_check_buffer_size(XMesaBuffer b); extern void xmesa_destroy_buffers_on_display(Display *dpy); @@ -388,17 +369,15 @@ xmesa_destroy_buffers_on_display(Display *dpy); static INLINE GLuint xmesa_buffer_width(XMesaBuffer b) { - return b->stfb->Base.Width; + return b->width; } static INLINE GLuint xmesa_buffer_height(XMesaBuffer b) { - return b->stfb->Base.Height; + return b->height; } -extern int -xmesa_check_for_xshm(Display *display); #endif diff --git a/src/gallium/state_trackers/glx/xlib/xm_winsys.h b/src/gallium/state_trackers/glx/xlib/xm_public.h index 4bd5b5c8d3b..950eb21521f 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_winsys.h +++ b/src/gallium/state_trackers/glx/xlib/xm_public.h @@ -26,27 +26,23 @@ * **************************************************************************/ -#ifndef XM_WINSYS_H -#define XM_WINSYS_H +#ifndef XM_PUBLIC_H +#define XM_PUBLIC_H -struct pipe_context; -struct pipe_screen; -struct pipe_surface; -struct xmesa_buffer; +#include <X11/Xlib.h> +struct pipe_screen; +struct st_api; +/* This is the driver interface required by the glx/xlib state tracker. + */ struct xm_driver { - - struct pipe_screen *(*create_pipe_screen)( void ); - - void (*display_surface)( struct xmesa_buffer *, - struct pipe_surface * ); - + struct pipe_screen *(*create_pipe_screen)( Display *display ); + struct st_api *(*create_st_api)( void ); }; - extern void xmesa_set_driver( const struct xm_driver *driver ); -#endif +#endif /* XM_PUBLIC_H */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c new file mode 100644 index 00000000000..b6ed7e8e1e8 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -0,0 +1,332 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "xm_api.h" +#include "xm_st.h" + +struct xmesa_st_framebuffer { + XMesaDisplay display; + XMesaBuffer buffer; + struct pipe_screen *screen; + + struct st_visual stvis; + + unsigned texture_width, texture_height, texture_mask; + struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; + + struct pipe_surface *display_surface; +}; + +static INLINE struct xmesa_st_framebuffer * +xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; +} + +/** + * Display an attachment to the xlib_drawable of the framebuffer. + */ +static boolean +xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_texture *ptex = xstfb->textures[statt]; + struct pipe_surface *psurf; + + if (!ptex) + return TRUE; + + psurf = xstfb->display_surface; + /* (re)allocate the surface for the texture to be displayed */ + if (!psurf || psurf->texture != ptex) { + pipe_surface_reference(&xstfb->display_surface, NULL); + + psurf = xstfb->screen->get_tex_surface(xstfb->screen, + ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ); + if (!psurf) + return FALSE; + + xstfb->display_surface = psurf; + } + + xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws); + + return TRUE; +} + +/** + * Copy the contents between the attachments. + */ +static void +xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src_statt, + enum st_attachment_type dst_statt, + unsigned x, unsigned y, + unsigned width, unsigned height) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_texture *src_ptex = xstfb->textures[src_statt]; + struct pipe_texture *dst_ptex = xstfb->textures[dst_statt]; + struct pipe_surface *src, *dst; + struct pipe_context *pipe; + + if (!src_ptex || !dst_ptex) + return; + + pipe = xstfb->display->pipe; + if (!pipe) { + pipe = xstfb->screen->context_create(xstfb->screen, NULL); + if (!pipe) + return; + xstfb->display->pipe = pipe; + } + + src = xstfb->screen->get_tex_surface(xstfb->screen, + src_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + dst = xstfb->screen->get_tex_surface(xstfb->screen, + dst_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); + + if (src && dst) + pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +/** + * Remove outdated textures and create the requested ones. + */ +static void +xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + unsigned width, unsigned height, + unsigned mask) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_texture templ; + unsigned i; + + /* remove outdated textures */ + if (xstfb->texture_width != width || xstfb->texture_height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_texture_reference(&xstfb->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned tex_usage; + + /* the texture already exists or not requested */ + if (xstfb->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (xstfb->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = xstfb->stvis.color_format; + tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = xstfb->stvis.depth_stencil_format; + tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.tex_usage = tex_usage; + + xstfb->textures[i] = + xstfb->screen->texture_create(xstfb->screen, &templ); + } + } + + xstfb->texture_width = width; + xstfb->texture_height = height; + xstfb->texture_mask = mask; +} + +static boolean +xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_texture **out) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + unsigned statt_mask, new_mask, i; + boolean resized; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; + /* record newly allocated textures */ + new_mask = statt_mask & ~xstfb->texture_mask; + + resized = (xstfb->buffer->width != xstfb->texture_width || + xstfb->buffer->height != xstfb->texture_height); + + /* revalidate textures */ + if (resized || new_mask) { + xmesa_st_framebuffer_validate_textures(stfbi, + xstfb->buffer->width, xstfb->buffer->height, statt_mask); + + if (!resized) { + enum st_attachment_type back, front; + + back = ST_ATTACHMENT_BACK_LEFT; + front = ST_ATTACHMENT_FRONT_LEFT; + /* copy the contents if front is newly allocated and back is not */ + if ((statt_mask & (1 << back)) && + (new_mask & (1 << front)) && + !(new_mask & (1 << back))) { + xmesa_st_framebuffer_copy_textures(stfbi, back, front, + 0, 0, xstfb->texture_width, xstfb->texture_height); + } + } + } + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_texture_reference(&out[i], xstfb->textures[statts[i]]); + } + + return TRUE; +} + +static boolean +xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, statt); + if (ret) + xmesa_check_buffer_size(xstfb->buffer); + + return ret; +} + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b) +{ + struct st_framebuffer_iface *stfbi; + struct xmesa_st_framebuffer *xstfb; + + assert(xmdpy->display == b->xm_visual->display); + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); + if (!stfbi || !xstfb) { + if (stfbi) + FREE(stfbi); + if (xstfb) + FREE(xstfb); + return NULL; + } + + xstfb->display = xmdpy; + xstfb->buffer = b; + xstfb->screen = xmdpy->screen; + xstfb->stvis = b->xm_visual->stvis; + + stfbi->visual = &xstfb->stvis; + stfbi->flush_front = xmesa_st_framebuffer_flush_front; + stfbi->validate = xmesa_st_framebuffer_validate; + stfbi->st_manager_private = (void *) xstfb; + + return stfbi; +} + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + int i; + + pipe_surface_reference(&xstfb->display_surface, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_texture_reference(&xstfb->textures[i], NULL); + + FREE(xstfb); + FREE(stfbi); +} + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); + if (ret) { + struct pipe_texture **front, **back, *tmp; + + front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; + back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; + /* swap textures only if the front texture has been allocated */ + if (*front) { + tmp = *front; + *front = *back; + *back = tmp; + } + + xmesa_check_buffer_size(xstfb->buffer); + } +} + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h) +{ + xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h); + if (dst == ST_ATTACHMENT_FRONT_LEFT) + xmesa_st_framebuffer_display(stfbi, dst); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h new file mode 100644 index 00000000000..396495c1893 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.h @@ -0,0 +1,51 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef _XM_ST_H_ +#define _XM_ST_H_ + +#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" + +#include "xm_api.h" + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h); + +#endif /* _XM_ST_H_ */ diff --git a/src/gallium/state_trackers/python/SConscript b/src/gallium/state_trackers/python/SConscript index 527e065cd91..d0d141fd249 100644 --- a/src/gallium/state_trackers/python/SConscript +++ b/src/gallium/state_trackers/python/SConscript @@ -3,7 +3,8 @@ import os.path Import('*') -if 'python' in env['statetrackers']: +if 'python' in env['statetrackers'] and 0: + # FIXME: Disable python state tracker until transfers are done by contexts env = env.Clone() @@ -24,6 +25,7 @@ if 'python' in env['statetrackers']: 'ws2_32', ]) else: + env.Append(CPPDEFINES = ['GCC_HASCLASSVISIBILITY']) env.Append(LIBS = [ 'GL', 'X11', @@ -33,31 +35,27 @@ if 'python' in env['statetrackers']: 'gallium.i', 'st_device.c', 'st_sample.c', + 'st_hardpipe_winsys.c', + 'st_softpipe_winsys.c', ] - drivers = [ - trace - ] + env.Prepend(LIBS = [ + ws_null, + trace, + gallium, + ]) if 'llvmpipe' in env['drivers']: + env.Append(CPPDEFINES = ['HAVE_LLVMPIPE']) env.Tool('llvm') - sources += ['st_llvmpipe_winsys.c'] - drivers += [llvmpipe] - else: - sources += ['st_softpipe_winsys.c'] - drivers += [softpipe] - - pyst = env.ConvenienceLibrary( - target = 'pyst', - source = sources, - ) + env.Prepend(LIBS = [llvmpipe]) + if 'softpipe' in env['drivers']: + env.Append(CPPDEFINES = ['HAVE_SOFTPIPE']) + env.Prepend(LIBS = [softpipe]) env['no_import_lib'] = 1 env.SharedLibrary( target = '_gallium', - source = [ - 'st_hardpipe_winsys.c', - ], - LIBS = [pyst] + drivers + gallium + env['LIBS'], + source = sources, ) diff --git a/src/gallium/state_trackers/python/gallium.i b/src/gallium/state_trackers/python/gallium.i index ffb084e358b..632d71ccbee 100644 --- a/src/gallium/state_trackers/python/gallium.i +++ b/src/gallium/state_trackers/python/gallium.i @@ -49,6 +49,7 @@ #include "util/u_format.h" #include "util/u_dump.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" #include "tgsi/tgsi_text.h" #include "tgsi/tgsi_dump.h" diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i index 3f36ccb6217..df700bc663c 100644 --- a/src/gallium/state_trackers/python/p_context.i +++ b/src/gallium/state_trackers/python/p_context.i @@ -51,7 +51,7 @@ struct st_context { void set_blend( const struct pipe_blend_state *state ) { cso_set_blend($self->cso, state); } - + void set_fragment_sampler( unsigned index, const struct pipe_sampler_state *state ) { cso_single_sampler($self->cso, index, state); cso_single_sampler_done($self->cso); @@ -169,22 +169,39 @@ struct st_context { void set_fragment_sampler_texture(unsigned index, struct pipe_texture *texture) { + struct pipe_sampler_view templ; + if(!texture) texture = $self->default_texture; - pipe_texture_reference(&$self->fragment_sampler_textures[index], texture); - $self->pipe->set_fragment_sampler_textures($self->pipe, - PIPE_MAX_SAMPLERS, - $self->fragment_sampler_textures); + pipe_sampler_view_reference(&$self->fragment_sampler_views[index], NULL); + u_sampler_view_default_template(&templ, + texture, + texture->format); + $self->fragment_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe, + texture, + &templ); + $self->pipe->set_fragment_sampler_views($self->pipe, + PIPE_MAX_SAMPLERS, + $self->fragment_sampler_views); } void set_vertex_sampler_texture(unsigned index, struct pipe_texture *texture) { + struct pipe_sampler_view templ; + if(!texture) texture = $self->default_texture; - pipe_texture_reference(&$self->vertex_sampler_textures[index], texture); - $self->pipe->set_vertex_sampler_textures($self->pipe, - PIPE_MAX_VERTEX_SAMPLERS, - $self->vertex_sampler_textures); + pipe_sampler_view_reference(&$self->vertex_sampler_views[index], NULL); + u_sampler_view_default_template(&templ, + texture, + texture->format); + $self->vertex_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe, + texture, + &templ); + + $self->pipe->set_vertex_sampler_views($self->pipe, + PIPE_MAX_VERTEX_SAMPLERS, + $self->vertex_sampler_views); } void set_vertex_buffer(unsigned index, @@ -222,9 +239,9 @@ struct st_context { void set_vertex_elements(unsigned num) { $self->num_vertex_elements = num; - $self->pipe->set_vertex_elements($self->pipe, - $self->num_vertex_elements, - $self->vertex_elements); + cso_set_vertex_elements($self->cso, + $self->num_vertex_elements, + $self->vertex_elements); } /* diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c index 45e78417500..0d87c705e75 100644 --- a/src/gallium/state_trackers/python/st_device.c +++ b/src/gallium/state_trackers/python/st_device.c @@ -33,9 +33,9 @@ #include "cso_cache/cso_context.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "util/u_simple_shaders.h" -#include "trace/tr_screen.h" -#include "trace/tr_context.h" +#include "trace/tr_public.h" #include "st_device.h" #include "st_winsys.h" @@ -75,43 +75,34 @@ st_device_destroy(struct st_device *st_dev) } -static struct st_device * -st_device_create_from_st_winsys(const struct st_winsys *st_ws) +struct st_device * +st_device_create(boolean hardware) { + struct pipe_screen *screen; struct st_device *st_dev; - - if(!st_ws->screen_create) - return NULL; - + + if (hardware) + screen = st_hardware_screen_create(); + else + screen = st_software_screen_create(); + + screen = trace_screen_create(screen); + if (!screen) + goto no_screen; + st_dev = CALLOC_STRUCT(st_device); - if(!st_dev) - return NULL; + if (!st_dev) + goto no_device; pipe_reference_init(&st_dev->reference, 1); - st_dev->st_ws = st_ws; - - st_dev->real_screen = st_ws->screen_create(); - if(!st_dev->real_screen) { - st_device_destroy(st_dev); - return NULL; - } - - st_dev->screen = trace_screen_create(st_dev->real_screen); - if(!st_dev->screen) { - st_device_destroy(st_dev); - return NULL; - } + st_dev->screen = screen; return st_dev; -} - -struct st_device * -st_device_create(boolean hardware) { - if(hardware) - return st_device_create_from_st_winsys(&st_hardpipe_winsys); - else - return st_device_create_from_st_winsys(&st_softpipe_winsys); +no_device: + screen->destroy(screen); +no_screen: + return NULL; } @@ -134,9 +125,9 @@ st_context_destroy(struct st_context *st_ctx) st_ctx->pipe->destroy(st_ctx->pipe); for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) - pipe_texture_reference(&st_ctx->fragment_sampler_textures[i], NULL); + pipe_sampler_view_reference(&st_ctx->fragment_sampler_views[i], NULL); for(i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) - pipe_texture_reference(&st_ctx->vertex_sampler_textures[i], NULL); + pipe_sampler_view_reference(&st_ctx->vertex_sampler_views[i], NULL); pipe_texture_reference(&st_ctx->default_texture, NULL); FREE(st_ctx); @@ -240,6 +231,8 @@ st_context_create(struct st_device *st_dev) struct pipe_screen *screen = st_dev->screen; struct pipe_texture templat; struct pipe_transfer *transfer; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; unsigned i; memset( &templat, 0, sizeof( templat ) ); @@ -269,14 +262,27 @@ st_context_create(struct st_device *st_dev) screen->tex_transfer_destroy(transfer); } } - + + u_sampler_view_default_template(&view_templ, + st_ctx->default_texture, + st_ctx->default_texture->format); + view = st_ctx->pipe->create_sampler_view(st_ctx->pipe, + st_ctx->default_texture, + &view_templ); + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) - pipe_texture_reference(&st_ctx->fragment_sampler_textures[i], st_ctx->default_texture); + pipe_sampler_view_reference(&st_ctx->fragment_sampler_views[i], view); for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) - pipe_texture_reference(&st_ctx->vertex_sampler_textures[i], st_ctx->default_texture); - - cso_set_sampler_textures(st_ctx->cso, PIPE_MAX_SAMPLERS, st_ctx->fragment_sampler_textures); - cso_set_vertex_sampler_textures(st_ctx->cso, PIPE_MAX_VERTEX_SAMPLERS, st_ctx->vertex_sampler_textures); + pipe_sampler_view_reference(&st_ctx->vertex_sampler_views[i], view); + + st_ctx->pipe->set_fragment_sampler_views(st_ctx->pipe, + PIPE_MAX_SAMPLERS, + st_ctx->fragment_sampler_views); + st_ctx->pipe->set_vertex_sampler_views(st_ctx->pipe, + PIPE_MAX_VERTEX_SAMPLERS, + st_ctx->vertex_sampler_views); + + pipe_sampler_view_reference(&view, NULL); } /* vertex shader */ diff --git a/src/gallium/state_trackers/python/st_device.h b/src/gallium/state_trackers/python/st_device.h index de9e0215d8e..dcd0dc6e273 100644 --- a/src/gallium/state_trackers/python/st_device.h +++ b/src/gallium/state_trackers/python/st_device.h @@ -47,7 +47,8 @@ struct st_surface }; -struct st_context { +struct st_context +{ struct st_device *st_dev; struct pipe_context *pipe; @@ -59,8 +60,8 @@ struct st_context { void *gs; struct pipe_texture *default_texture; - struct pipe_texture *fragment_sampler_textures[PIPE_MAX_SAMPLERS]; - struct pipe_texture *vertex_sampler_textures[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; unsigned num_vertex_buffers; struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; @@ -72,13 +73,11 @@ struct st_context { }; -struct st_device { +struct st_device +{ /* FIXME: we also need to refcount for textures and surfaces... */ struct pipe_reference reference; - const struct st_winsys *st_ws; - - struct pipe_screen *real_screen; struct pipe_screen *screen; }; diff --git a/src/gallium/state_trackers/python/st_hardpipe_winsys.c b/src/gallium/state_trackers/python/st_hardpipe_winsys.c index a3110a19d5d..b141177b793 100644 --- a/src/gallium/state_trackers/python/st_hardpipe_winsys.c +++ b/src/gallium/state_trackers/python/st_hardpipe_winsys.c @@ -54,11 +54,6 @@ static PFNGETGALLIUMSCREENMESAPROC pfnGetGalliumScreenMESA = NULL; static PFNCREATEGALLIUMCONTEXTMESAPROC pfnCreateGalliumContextMESA = NULL; -/* XXX: Force init_gallium symbol to be linked */ -extern void init_gallium(void); -void (*force_init_gallium_linkage)(void) = &init_gallium; - - #ifdef PIPE_OS_WINDOWS static INLINE boolean @@ -207,16 +202,11 @@ st_hardpipe_load(void) #endif -static struct pipe_screen * -st_hardpipe_screen_create(void) +struct pipe_screen * +st_hardware_screen_create(void) { if(st_hardpipe_load()) return pfnGetGalliumScreenMESA(); else - return st_softpipe_winsys.screen_create(); + return st_software_screen_create(); } - - -const struct st_winsys st_hardpipe_winsys = { - &st_hardpipe_screen_create -}; diff --git a/src/gallium/state_trackers/python/st_llvmpipe_winsys.c b/src/gallium/state_trackers/python/st_llvmpipe_winsys.c deleted file mode 100644 index 5d83b5a9e15..00000000000 --- a/src/gallium/state_trackers/python/st_llvmpipe_winsys.c +++ /dev/null @@ -1,141 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/** - * @file - * Llvmpipe support. - * - * @author Jose Fonseca - */ - - -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "llvmpipe/lp_winsys.h" -#include "st_winsys.h" - - -static boolean -llvmpipe_ws_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, - enum pipe_format format ) -{ - return FALSE; -} - - -static void * -llvmpipe_ws_displaytarget_map(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, - unsigned flags ) -{ - assert(0); - return NULL; -} - - -static void -llvmpipe_ws_displaytarget_unmap(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ) -{ - assert(0); -} - - -static void -llvmpipe_ws_displaytarget_destroy(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt) -{ - assert(0); -} - - -static struct llvmpipe_displaytarget * -llvmpipe_ws_displaytarget_create(struct llvmpipe_winsys *winsys, - enum pipe_format format, - unsigned width, unsigned height, - unsigned alignment, - unsigned *stride) -{ - return NULL; -} - - -static void -llvmpipe_ws_displaytarget_display(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt, - void *context_private) -{ - assert(0); -} - - -static void -llvmpipe_ws_destroy(struct llvmpipe_winsys *winsys) -{ - FREE(winsys); -} - - -static struct pipe_screen * -st_llvmpipe_screen_create(void) -{ - static struct llvmpipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(llvmpipe_winsys); - if (!winsys) - goto no_winsys; - - winsys->destroy = llvmpipe_ws_destroy; - winsys->is_displaytarget_format_supported = llvmpipe_ws_is_displaytarget_format_supported; - winsys->displaytarget_create = llvmpipe_ws_displaytarget_create; - winsys->displaytarget_map = llvmpipe_ws_displaytarget_map; - winsys->displaytarget_unmap = llvmpipe_ws_displaytarget_unmap; - winsys->displaytarget_display = llvmpipe_ws_displaytarget_display; - winsys->displaytarget_destroy = llvmpipe_ws_displaytarget_destroy; - - screen = llvmpipe_create_screen(winsys); - if (!screen) - goto no_screen; - - return screen; - -no_screen: - FREE(winsys); -no_winsys: - return NULL; -} - - - -const struct st_winsys st_softpipe_winsys = { - &st_llvmpipe_screen_create -}; diff --git a/src/gallium/state_trackers/python/st_softpipe_winsys.c b/src/gallium/state_trackers/python/st_softpipe_winsys.c index 81676bc3a4f..985374190c3 100644 --- a/src/gallium/state_trackers/python/st_softpipe_winsys.c +++ b/src/gallium/state_trackers/python/st_softpipe_winsys.c @@ -26,18 +26,47 @@ * **************************************************************************/ -/** - * @file - * Softpipe support. - * - * @author Keith Whitwell - * @author Brian Paul - * @author Jose Fonseca - */ - -#include "softpipe/sp_winsys.h" +#include "util/u_debug.h" +#include "softpipe/sp_public.h" +#include "llvmpipe/lp_public.h" +#include "state_tracker/sw_winsys.h" +#include "null/null_sw_winsys.h" #include "st_winsys.h" -const struct st_winsys st_softpipe_winsys = { - &softpipe_create_screen_malloc -}; + +struct pipe_screen * +st_software_screen_create(void) +{ + struct sw_winsys *ws; + const char *default_driver; + const char *driver; + struct pipe_screen *screen = NULL; + +#if defined(HAVE_LLVMPIPE) + default_driver = "llvmpipe"; +#elif defined(HAVE_SOFTPIPE) + default_driver = "softpipe"; +#else + default_driver = ""; +#endif + + ws = null_sw_create(); + if(!ws) + return NULL; + + driver = debug_get_option("GALLIUM_DRIVER", default_driver); + +#ifdef HAVE_LLVMPIPE + if (strcmp(driver, "llvmpipe") == 0) { + screen = llvmpipe_create_screen(ws); + } +#endif + +#ifdef HAVE_SOFTPIPE + if (strcmp(driver, "softpipe") == 0) { + screen = softpipe_create_screen(ws); + } +#endif + + return screen; +} diff --git a/src/gallium/state_trackers/python/st_winsys.h b/src/gallium/state_trackers/python/st_winsys.h index 0c7b6a200e1..e1a99383a41 100644 --- a/src/gallium/state_trackers/python/st_winsys.h +++ b/src/gallium/state_trackers/python/st_winsys.h @@ -31,19 +31,13 @@ struct pipe_screen; -struct pipe_context; -struct st_winsys -{ - struct pipe_screen * - (*screen_create)(void); -}; +struct pipe_screen * +st_hardware_screen_create(void); - -extern const struct st_winsys st_softpipe_winsys; - -extern const struct st_winsys st_hardpipe_winsys; +struct pipe_screen * +st_software_screen_create(void); #endif /* ST_WINSYS_H_ */ diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile index 037d8dc911a..7c315de8271 100644 --- a/src/gallium/state_trackers/vega/Makefile +++ b/src/gallium/state_trackers/vega/Makefile @@ -25,6 +25,7 @@ VG_SOURCES = \ api_transform.c \ vgu.c \ vg_context.c \ + vg_manager.c \ vg_state.c \ vg_tracker.c \ vg_translate.c \ @@ -53,7 +54,7 @@ INCLUDE_DIRS = \ .c.o: - $(CC) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) $< -o $@ + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ default: depend $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) diff --git a/src/gallium/state_trackers/vega/api_context.c b/src/gallium/state_trackers/vega/api_context.c index 47db102dd2d..eb2fbe26e7f 100644 --- a/src/gallium/state_trackers/vega/api_context.c +++ b/src/gallium/state_trackers/vega/api_context.c @@ -26,6 +26,7 @@ #include "VG/openvg.h" +#include "vg_manager.h" #include "vg_context.h" #include "pipe/p_context.h" @@ -55,6 +56,8 @@ void vgFlush(void) pipe = ctx->pipe; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + + vg_manager_flush_frontbuffer(ctx); } void vgFinish(void) diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c index 02248ad4337..18e2cc1f250 100644 --- a/src/gallium/state_trackers/vega/api_filters.c +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -78,14 +78,14 @@ static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx, { /* upload color_data */ struct pipe_transfer *transfer = - screen->get_tex_transfer(screen, tex, - 0, 0, 0, - PIPE_TRANSFER_READ_WRITE , - 0, 0, tex->width0, tex->height0); - void *map = screen->transfer_map(screen, transfer); + pipe->get_tex_transfer(pipe, tex, + 0, 0, 0, + PIPE_TRANSFER_READ_WRITE , + 0, 0, tex->width0, tex->height0); + void *map = pipe->transfer_map(pipe, transfer); memcpy(map, color_data, sizeof(VGint)*color_data_len); - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->tex_transfer_destroy(pipe, transfer); } return tex; diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c index 015241498ed..fec473d9d23 100644 --- a/src/gallium/state_trackers/vega/api_images.c +++ b/src/gallium/state_trackers/vega/api_images.c @@ -397,7 +397,6 @@ void vgReadPixels(void * data, VGint dataStride, { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; @@ -442,7 +441,7 @@ void vgReadPixels(void * data, VGint dataStride, { struct pipe_transfer *transfer; - transfer = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, + transfer = pipe->get_tex_transfer(pipe, strb->texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, width, height); @@ -451,14 +450,14 @@ void vgReadPixels(void * data, VGint dataStride, #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif - pipe_get_tile_rgba(transfer, sx, y, width, 1, df); + pipe_get_tile_rgba(pipe, transfer, sx, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst + yoffset + xoffset); dst += dataStride; } - screen->tex_transfer_destroy(transfer); + pipe->tex_transfer_destroy(pipe, transfer); } } diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c index 9c123a4cf95..2f2d925252d 100644 --- a/src/gallium/state_trackers/vega/api_masks.c +++ b/src/gallium/state_trackers/vega/api_masks.c @@ -86,6 +86,8 @@ draw_clear_quad(struct vg_context *st, /* draw */ if (buf) { + cso_set_vertex_elements(st->cso_context, 2, st->velems); + util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -115,10 +117,6 @@ clear_with_quad(struct vg_context *st, float x0, float y0, x1, y1); */ - if (st->pipe->screen && st->pipe->screen->update_buffer) - st->pipe->screen->update_buffer( st->pipe->screen, - st->pipe->priv ); - cso_save_blend(st->cso_context); cso_save_rasterizer(st->cso_context); cso_save_fragment_shader(st->cso_context); diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c index 41c979bfecf..a71579cd264 100644 --- a/src/gallium/state_trackers/vega/image.c +++ b/src/gallium/state_trackers/vega/image.c @@ -378,7 +378,7 @@ void image_sub_data(struct vg_image *image, VGfloat *df = (VGfloat*)temp; VGint i; struct vg_context *ctx = vg_current_context(); - struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_context *pipe = ctx->pipe; struct pipe_texture *texture = image_texture(image); VGint xoffset = 0, yoffset = 0; @@ -412,17 +412,17 @@ void image_sub_data(struct vg_image *image, } { /* upload color_data */ - struct pipe_transfer *transfer = screen->get_tex_transfer( - screen, texture, 0, 0, 0, + struct pipe_transfer *transfer = pipe->get_tex_transfer( + pipe, texture, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, texture->width0, texture->height0); src += (dataStride * yoffset); for (i = 0; i < height; i++) { _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp); - pipe_put_tile_rgba(transfer, x+image->x, y+image->y, width, 1, df); + pipe_put_tile_rgba(pipe, transfer, x+image->x, y+image->y, width, 1, df); y += yStep; src += dataStride; } - screen->tex_transfer_destroy(transfer); + pipe->tex_transfer_destroy(pipe, transfer); } } @@ -435,7 +435,6 @@ void image_get_sub_data(struct vg_image * image, { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; VGfloat *df = (VGfloat*)temp; VGint y = 0, yStep = 1; @@ -444,7 +443,7 @@ void image_get_sub_data(struct vg_image * image, { struct pipe_transfer *transfer = - screen->get_tex_transfer(screen, + pipe->get_tex_transfer(pipe, image->texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, @@ -455,13 +454,13 @@ void image_get_sub_data(struct vg_image * image, #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif - pipe_get_tile_rgba(transfer, sx+image->x, y, width, 1, df); + pipe_get_tile_rgba(pipe, transfer, sx+image->x, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst); dst += dataStride; } - screen->tex_transfer_destroy(transfer); + pipe->tex_transfer_destroy(pipe, transfer); } } diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c index cdb87d3bf68..dc56b8c5f3b 100644 --- a/src/gallium/state_trackers/vega/paint.c +++ b/src/gallium/state_trackers/vega/paint.c @@ -164,10 +164,10 @@ static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p) struct pipe_transfer *transfer = st_no_flush_get_tex_transfer(p->base.ctx, tex, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, 1024, 1); - void *map = screen->transfer_map(screen, transfer); + void *map = pipe->transfer_map(pipe, transfer); memcpy(map, p->gradient.color_data, sizeof(VGint)*1024); - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->tex_transfer_destroy(pipe, transfer); } return tex; diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c index c06dbf52069..eef2c1eb876 100644 --- a/src/gallium/state_trackers/vega/polygon.c +++ b/src/gallium/state_trackers/vega/polygon.c @@ -292,12 +292,12 @@ static void draw_polygon(struct vg_context *ctx, pipe->set_vertex_buffers(pipe, 1, &vbuffer); /* tell pipe about the vertex attributes */ + memset(&velement, 0, sizeof(velement)); velement.src_offset = 0; velement.instance_divisor = 0; velement.vertex_buffer_index = 0; velement.src_format = PIPE_FORMAT_R32G32_FLOAT; - velement.nr_components = COMPONENTS; - pipe->set_vertex_elements(pipe, 1, &velement); + cso_set_vertex_elements(ctx->cso_context, 1, &velement); /* draw */ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 05620efa9c0..47e8b470a11 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -210,6 +210,7 @@ void renderer_draw_quad(struct renderer *r, buf = setup_vertex_data(r, x1, y1, x2, y2, depth); if (buf) { + cso_set_vertex_elements(r->cso, 2, r->owner->velems); util_draw_vertex_buffer(r->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -248,6 +249,7 @@ void renderer_draw_texture(struct renderer *r, s0, t0, s1, t1, 0.0f); if (buf) { + cso_set_vertex_elements(r->cso, 2, r->owner->velems); util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -370,6 +372,7 @@ void renderer_copy_texture(struct renderer *ctx, 0.0f); if (buf) { + cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems); util_draw_vertex_buffer(ctx->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -535,6 +538,7 @@ void renderer_copy_surface(struct renderer *ctx, (float) dstX1, (float) dstY1, z); if (buf) { + cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems); util_draw_vertex_buffer(ctx->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -587,6 +591,7 @@ void renderer_texture_quad(struct renderer *r, s0, t0, s1, t1, 0.0f); if (buf) { + cso_set_vertex_elements(r->cso, 2, r->owner->velems); util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ diff --git a/src/gallium/state_trackers/vega/st_inlines.h b/src/gallium/state_trackers/vega/st_inlines.h index 419151c3aee..4d12a4efdd6 100644 --- a/src/gallium/state_trackers/vega/st_inlines.h +++ b/src/gallium/state_trackers/vega/st_inlines.h @@ -51,7 +51,6 @@ st_cond_flush_get_tex_transfer(struct vg_context *st, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { - struct pipe_screen *screen = st->pipe->screen; struct pipe_context *pipe = st->pipe; unsigned referenced = pipe->is_texture_referenced(pipe, pt, face, level); @@ -60,7 +59,7 @@ st_cond_flush_get_tex_transfer(struct vg_context *st, (usage & PIPE_TRANSFER_WRITE))) vgFlush(); - return screen->get_tex_transfer(screen, pt, face, level, zslice, usage, + return pipe->get_tex_transfer(pipe, pt, face, level, zslice, usage, x, y, w, h); } @@ -74,10 +73,10 @@ st_no_flush_get_tex_transfer(struct vg_context *st, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *pipe = st->pipe; - return screen->get_tex_transfer(screen, pt, face, level, - zslice, usage, x, y, w, h); + return pipe->get_tex_transfer(pipe, pt, face, level, + zslice, usage, x, y, w, h); } static INLINE void * diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index 426bf9bc62b..7769112a31e 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -32,6 +32,7 @@ #include "shader.h" #include "asm_util.h" #include "st_inlines.h" +#include "vg_manager.h" #include "pipe/p_context.h" #include "util/u_inlines.h" @@ -72,6 +73,7 @@ struct vg_context * vg_create_context(struct pipe_context *pipe, struct vg_context *share) { struct vg_context *ctx; + unsigned i; ctx = CALLOC_STRUCT(vg_context); @@ -103,6 +105,13 @@ struct vg_context * vg_create_context(struct pipe_context *pipe, ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; ctx->blend_sampler.normalized_coords = 0; + for (i = 0; i < 2; i++) { + ctx->velems[i].src_offset = i * 4 * sizeof(float); + ctx->velems[i].instance_divisor = 0; + ctx->velems[i].vertex_buffer_index = 0; + ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + vg_set_error(ctx, VG_NO_ERROR); ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create(); @@ -297,6 +306,8 @@ static void update_clip_state(struct vg_context *ctx) void vg_validate_state(struct vg_context *ctx) { + vg_manager_validate_framebuffer(ctx); + if ((ctx->state.dirty & BLEND_DIRTY)) { struct pipe_blend_state *blend = &ctx->state.g3d.blend; memset(blend, 0, sizeof(struct pipe_blend_state)); diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h index bc88c8d139d..17c7d2ad1c5 100644 --- a/src/gallium/state_trackers/vega/vg_context.h +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -33,6 +33,7 @@ #include "pipe/p_state.h" #include "util/u_pointer.h" #include "util/u_math.h" +#include "state_tracker/st_api.h" #include "cso_cache/cso_hash.h" #include "cso_cache/cso_context.h" @@ -58,6 +59,9 @@ struct st_framebuffer { struct pipe_texture *blend_texture; + struct st_framebuffer_iface *iface; + enum st_attachment_type strb_att; + void *privateData; }; @@ -84,6 +88,8 @@ enum dirty_state { struct vg_context { + struct st_context_iface iface; + struct pipe_context *pipe; struct { @@ -101,6 +107,7 @@ struct vg_context VGErrorCode _error; struct st_framebuffer *draw_buffer; + int32_t draw_buffer_invalid; struct cso_hash *owned_objects[VG_OBJECT_LAST]; @@ -146,6 +153,7 @@ struct vg_context struct vg_shader *clear_vs; struct vg_shader *texture_vs; struct pipe_buffer *vs_const_buffer; + struct pipe_vertex_element velems[2]; }; struct vg_object { diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c new file mode 100644 index 00000000000..25c2e853f2a --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_manager.c @@ -0,0 +1,373 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "state_tracker/st_api.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "vg_manager.h" +#include "vg_context.h" +#include "vg_tracker.h" /* for st_resize_framebuffer */ +#include "image.h" + +/** + * Flush the front buffer if the current context renders to the front buffer. + */ +void +vg_manager_flush_frontbuffer(struct vg_context *ctx) +{ + struct st_framebuffer *stfb = ctx->draw_buffer; + + if (!stfb) + return; + + /* st_public.h is used */ + if (!stfb->iface) { + struct pipe_screen *screen = ctx->pipe->screen; + if (screen->flush_frontbuffer) { + screen->flush_frontbuffer(screen, + stfb->strb->surface, ctx->pipe->priv); + } + return; + } + + switch (stfb->strb_att) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + stfb->iface->flush_front(stfb->iface, stfb->strb_att); + break; + default: + break; + } +} + +/** + * Re-validate the framebuffer. + */ +void +vg_manager_validate_framebuffer(struct vg_context *ctx) +{ + struct pipe_screen *screen = ctx->pipe->screen; + struct st_framebuffer *stfb = ctx->draw_buffer; + struct st_renderbuffer *rb; + struct pipe_texture *pt; + + /* no binding surface */ + if (!stfb) + return; + + /* st_public.h is used */ + if (!stfb->iface) { + struct pipe_screen *screen = ctx->pipe->screen; + if (screen->update_buffer) + screen->update_buffer(screen, ctx->pipe->priv); + return; + } + + if (!p_atomic_read(&ctx->draw_buffer_invalid)) + return; + + /* validate the fb */ + if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt) + return; + + rb = stfb->strb; + if (rb->texture == pt) { + pipe_texture_reference(&pt, NULL); + return; + } + + /* unreference existing ones */ + pipe_surface_reference(&rb->surface, NULL); + pipe_texture_reference(&rb->texture, NULL); + + rb->texture = pt; + rb->surface = screen->get_tex_surface(screen, rb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); + + rb->width = rb->surface->width; + rb->height = rb->surface->height; + + st_resize_framebuffer(stfb, rb->width, rb->height); + + p_atomic_set(&ctx->draw_buffer_invalid, FALSE); +} + + +static void +vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + p_atomic_set(&ctx->draw_buffer_invalid, TRUE); +} + +static void +vg_context_flush(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + ctx->pipe->flush(ctx->pipe, flags, fence); + if (flags & PIPE_FLUSH_RENDER_CACHE) + vg_manager_flush_frontbuffer(ctx); +} + +static void +vg_context_destroy(struct st_context_iface *stctxi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + vg_destroy_context(ctx); +} + +static struct st_context_iface * +vg_api_create_context(struct st_api *stapi, struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *shared_stctxi) +{ + struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi; + struct vg_context *ctx; + struct pipe_context *pipe; + + pipe = smapi->screen->context_create(smapi->screen, NULL); + if (!pipe) + return NULL; + ctx = vg_create_context(pipe, NULL, shared_ctx); + if (!ctx) { + pipe->destroy(pipe); + return NULL; + } + + ctx->iface.destroy = vg_context_destroy; + + ctx->iface.notify_invalid_framebuffer = + vg_context_notify_invalid_framebuffer; + ctx->iface.flush = vg_context_flush; + + ctx->iface.teximage = NULL; + ctx->iface.copy = NULL; + + ctx->iface.st_context_private = (void *) smapi; + + return &ctx->iface; +} + +static struct st_renderbuffer * +create_renderbuffer(enum pipe_format format) +{ + struct st_renderbuffer *strb; + + strb = CALLOC_STRUCT(st_renderbuffer); + if (strb) + strb->format = format; + + return strb; +} + +static void +destroy_renderbuffer(struct st_renderbuffer *strb) +{ + pipe_surface_reference(&strb->surface, NULL); + pipe_texture_reference(&strb->texture, NULL); + free(strb); +} + +/** + * Decide the buffer to render to. + */ +static enum st_attachment_type +choose_attachment(struct st_framebuffer_iface *stfbi) +{ + enum st_attachment_type statt; + + statt = stfbi->visual->render_buffer; + if (statt != ST_ATTACHMENT_INVALID) { + /* use the buffer given by the visual, unless it is unavailable */ + if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) { + switch (statt) { + case ST_ATTACHMENT_BACK_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + statt = ST_ATTACHMENT_FRONT_RIGHT; + break; + default: + break; + } + + if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) + statt = ST_ATTACHMENT_INVALID; + } + } + + return statt; +} + +/** + * Bind the context to the given framebuffers. + */ +static boolean +vg_context_bind_framebuffers(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + struct st_framebuffer *stfb; + enum st_attachment_type strb_att; + + /* the draw and read framebuffers must be the same */ + if (stdrawi != streadi) + return FALSE; + + p_atomic_set(&ctx->draw_buffer_invalid, TRUE); + + strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID; + + if (ctx->draw_buffer) { + stfb = ctx->draw_buffer; + + /* free the existing fb */ + if (!stdrawi || + stfb->strb_att != strb_att || + stfb->strb->format != stdrawi->visual->color_format || + stfb->dsrb->format != stdrawi->visual->depth_stencil_format) { + destroy_renderbuffer(stfb->strb); + destroy_renderbuffer(stfb->dsrb); + free(stfb); + + ctx->draw_buffer = NULL; + } + } + + if (!stdrawi) + return TRUE; + + if (strb_att == ST_ATTACHMENT_INVALID) + return FALSE; + + /* create a new fb */ + if (!ctx->draw_buffer) { + stfb = CALLOC_STRUCT(st_framebuffer); + if (!stfb) + return FALSE; + + stfb->strb = create_renderbuffer(stdrawi->visual->color_format); + if (!stfb->strb) { + free(stfb); + return FALSE; + } + + stfb->dsrb = create_renderbuffer(stdrawi->visual->depth_stencil_format); + if (!stfb->dsrb) { + free(stfb->strb); + free(stfb); + return FALSE; + } + + stfb->width = 0; + stfb->height = 0; + stfb->strb_att = strb_att; + + ctx->draw_buffer = stfb; + } + + ctx->draw_buffer->iface = stdrawi; + + return TRUE; +} + +static boolean +vg_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + + if (stctxi) + vg_context_bind_framebuffers(stctxi, stdrawi, streadi); + vg_set_current_context(ctx); + + return TRUE; +} + +static struct st_context_iface * +vg_api_get_current(struct st_api *stapi) +{ + struct vg_context *ctx = vg_current_context(); + + return (ctx) ? &ctx->iface : NULL; +} + +static boolean +vg_api_is_visual_supported(struct st_api *stapi, + const struct st_visual *visual) +{ + /* the impl requires a depth/stencil buffer */ + if (visual->depth_stencil_format == PIPE_FORMAT_NONE) + return FALSE; + + return TRUE; +} + +static st_proc_t +vg_api_get_proc_address(struct st_api *stapi, const char *procname) +{ + /* TODO */ + return (st_proc_t) NULL; +} + +static void +vg_api_destroy(struct st_api *stapi) +{ + free(stapi); +} + +static struct st_api * +vg_module_create_api(void) +{ + struct st_api *stapi; + + stapi = CALLOC_STRUCT(st_api); + if (stapi) { + stapi->destroy = vg_api_destroy; + stapi->get_proc_address = vg_api_get_proc_address; + stapi->is_visual_supported = vg_api_is_visual_supported; + + stapi->create_context = vg_api_create_context; + stapi->make_current = vg_api_make_current; + stapi->get_current = vg_api_get_current; + } + + return stapi; +} + +PUBLIC const struct st_module st_module_OpenVG = { + .api = ST_API_OPENVG, + .create_api = vg_module_create_api, +}; diff --git a/src/gallium/state_trackers/vega/vg_manager.h b/src/gallium/state_trackers/vega/vg_manager.h new file mode 100644 index 00000000000..1a276c0f35e --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_manager.h @@ -0,0 +1,40 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef VG_MANAGER_H +#define VG_MANAGER_H + +#include "state_tracker/st_api.h" +#include "vg_context.h" + +void +vg_manager_flush_frontbuffer(struct vg_context *ctx); + +void +vg_manager_validate_framebuffer(struct vg_context *ctx); + +#endif /* VG_MANAGER_H */ diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c index 57d3baad7fb..ea5c2ce41f6 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.c +++ b/src/gallium/state_trackers/vega/vg_tracker.c @@ -376,12 +376,12 @@ void st_unreference_framebuffer(struct st_framebuffer *stfb) boolean st_make_current(struct vg_context *st, struct st_framebuffer *draw, - struct st_framebuffer *read) + struct st_framebuffer *read, + void *winsys_drawable_handle) { vg_set_current_context(st); - if (st) { + if (st) st->draw_buffer = draw; - } return VG_TRUE; } diff --git a/src/gallium/state_trackers/vega/vg_tracker.h b/src/gallium/state_trackers/vega/vg_tracker.h index c1196954a76..165a6b7a332 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.h +++ b/src/gallium/state_trackers/vega/vg_tracker.h @@ -101,7 +101,8 @@ void st_unreference_framebuffer(struct st_framebuffer *stfb); PUBLIC boolean st_make_current(struct vg_context *st, struct st_framebuffer *draw, - struct st_framebuffer *read); + struct st_framebuffer *read, + void *winsys_drawable_handle); PUBLIC struct vg_context *st_get_current(void); diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 05ccd5febcf..1f11b649c3e 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -226,7 +226,7 @@ DrvDeleteContext( /* Unbind current if deleting current context. */ if (curctx == ctx) - st_make_current( NULL, NULL, NULL ); + st_make_current( NULL, NULL, NULL, NULL ); st_destroy_context(ctx->st); FREE(ctx); @@ -317,7 +317,7 @@ stw_make_current( } if (hdc == NULL || dhglrc == 0) { - return st_make_current( NULL, NULL, NULL ); + return st_make_current( NULL, NULL, NULL, NULL ); } pipe_mutex_lock( stw_dev->ctx_mutex ); @@ -352,7 +352,7 @@ stw_make_current( /* pass to stw_flush_frontbuffer as context_private */ ctx->st->pipe->priv = hdc; - if(!st_make_current( ctx->st, fb->stfb, fb->stfb )) + if(!st_make_current( ctx->st, fb->stfb, fb->stfb, hdc )) goto fail; success: @@ -367,7 +367,7 @@ success: fail: if(fb) stw_framebuffer_release(fb); - st_make_current( NULL, NULL, NULL ); + st_make_current( NULL, NULL, NULL, NULL ); return FALSE; } diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c index 472a2a5379a..ea300f27cb5 100644 --- a/src/gallium/state_trackers/wgl/stw_device.c +++ b/src/gallium/state_trackers/wgl/stw_device.c @@ -33,11 +33,6 @@ #include "pipe/p_screen.h" #include "state_tracker/st_public.h" -#ifdef DEBUG -#include "trace/tr_screen.h" -#include "trace/tr_texture.h" -#endif - #include "stw_device.h" #include "stw_winsys.h" #include "stw_pixelformat.h" @@ -107,13 +102,10 @@ stw_init(const struct stw_winsys *stw_winsys) if(stw_winsys->get_adapter_luid) stw_winsys->get_adapter_luid(screen, &stw_dev->AdapterLuid); -#ifdef DEBUG - stw_dev->screen = trace_screen_create(screen); - stw_dev->trace_running = stw_dev->screen != screen ? TRUE : FALSE; -#else stw_dev->screen = screen; -#endif - + + /* XXX + */ stw_dev->screen->flush_frontbuffer = &stw_flush_frontbuffer; pipe_mutex_init( stw_dev->ctx_mutex ); diff --git a/src/gallium/state_trackers/wgl/stw_device.h b/src/gallium/state_trackers/wgl/stw_device.h index a83841f6b7d..2e9ba197dfa 100644 --- a/src/gallium/state_trackers/wgl/stw_device.h +++ b/src/gallium/state_trackers/wgl/stw_device.h @@ -48,10 +48,6 @@ struct stw_device struct pipe_screen *screen; -#ifdef DEBUG - boolean trace_running; -#endif - LUID AdapterLuid; struct stw_pixelformat_info pixelformats[STW_MAX_PIXELFORMATS]; diff --git a/src/gallium/state_trackers/wgl/stw_ext_gallium.c b/src/gallium/state_trackers/wgl/stw_ext_gallium.c index 8dd63f124ad..5ecbd8048de 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_gallium.c +++ b/src/gallium/state_trackers/wgl/stw_ext_gallium.c @@ -31,11 +31,6 @@ #include "stw_winsys.h" #include "stw_ext_gallium.h" -#ifdef DEBUG -#include "trace/tr_screen.h" -#include "trace/tr_context.h" -#endif - struct pipe_screen * APIENTRY wglGetGalliumScreenMESA(void) diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.c b/src/gallium/state_trackers/wgl/stw_framebuffer.c index 02de21ccb2b..4f1629de2f2 100644 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/stw_framebuffer.c @@ -34,11 +34,6 @@ #include "state_tracker/st_context.h" #include "state_tracker/st_public.h" -#ifdef DEBUG -#include "trace/tr_screen.h" -#include "trace/tr_texture.h" -#endif - #include "stw_icd.h" #include "stw_framebuffer.h" #include "stw_device.h" @@ -495,13 +490,6 @@ DrvPresentBuffers(HDC hdc, PGLPRESENTBUFFERSDATA data) surface = (struct pipe_surface *)data->pPrivateData; -#ifdef DEBUG - if(stw_dev->trace_running) { - screen = trace_screen(screen)->screen; - surface = trace_surface(surface)->surface; - } -#endif - if(data->hSharedSurface != fb->hSharedSurface) { if(fb->shared_surface) { stw_dev->stw_winsys->shared_surface_close(screen, fb->shared_surface); @@ -563,13 +551,6 @@ stw_framebuffer_present_locked(HDC hdc, else { struct pipe_screen *screen = stw_dev->screen; -#ifdef DEBUG - if(stw_dev->trace_running) { - screen = trace_screen(screen)->screen; - surface = trace_surface(surface)->surface; - } -#endif - stw_dev->stw_winsys->present( screen, surface, hdc ); stw_framebuffer_update(fb); diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index c50873c1508..4ff48026e50 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -4,6 +4,7 @@ #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" +#include "util/u_sampler.h" /*XXX also in Xrender.h but the including it here breaks compilition */ @@ -356,17 +357,12 @@ bind_samplers(struct exa_context *exa, int op, { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state src_sampler, mask_sampler; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; + struct pipe_context *pipe = exa->pipe; exa->num_bound_samplers = 0; -#if 0 - if ((pSrc && (exa->pipe->is_texture_referenced(exa->pipe, pSrc->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE)) || - (pMask && (exa->pipe->is_texture_referenced(exa->pipe, pMask->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE))) - xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL); -#endif - memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); @@ -374,7 +370,7 @@ bind_samplers(struct exa_context *exa, int op, if (exa->has_solid_color) { debug_assert(!"solid color with textures"); samplers[0] = NULL; - exa->bound_textures[0] = NULL; + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); } else { unsigned src_wrap = render_repeat_to_gallium( pSrcPicture->repeatType); @@ -389,8 +385,13 @@ bind_samplers(struct exa_context *exa, int op, src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; src_sampler.normalized_coords = 1; samplers[0] = &src_sampler; - exa->bound_textures[0] = pSrc->tex; exa->num_bound_samplers = 1; + u_sampler_view_default_template(&view_templ, + pSrc->tex, + pSrc->tex->format); + src_view = pipe->create_sampler_view(pipe, pSrc->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); + exa->bound_sampler_views[0] = src_view; } } @@ -408,14 +409,19 @@ bind_samplers(struct exa_context *exa, int op, src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; mask_sampler.normalized_coords = 1; samplers[1] = &mask_sampler; - exa->bound_textures[1] = pMask->tex; exa->num_bound_samplers = 2; + u_sampler_view_default_template(&view_templ, + pMask->tex, + pMask->tex->format); + src_view = pipe->create_sampler_view(pipe, pMask->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); + exa->bound_sampler_views[1] = src_view; } cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers, - exa->bound_textures); + cso_set_fragment_sampler_views(exa->renderer->cso, exa->num_bound_samplers, + exa->bound_sampler_views); } @@ -484,7 +490,6 @@ boolean xorg_composite_bind_state(struct exa_context *exa, renderer_begin_solid(exa->renderer); } else { renderer_begin_textures(exa->renderer, - exa->bound_textures, exa->num_bound_samplers); } @@ -514,7 +519,7 @@ void xorg_composite(struct exa_context *exa, renderer_texture(exa->renderer, pos, width, height, - exa->bound_textures, + exa->bound_sampler_views, exa->num_bound_samplers, src_matrix, mask_matrix); } @@ -546,7 +551,7 @@ boolean xorg_solid_bind_state(struct exa_context *exa, pixmap->width, pixmap->height); bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL); cso_set_samplers(exa->renderer->cso, 0, NULL); - cso_set_sampler_textures(exa->renderer->cso, 0, NULL); + cso_set_fragment_sampler_views(exa->renderer->cso, 0, NULL); shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index a428fa8d948..eef428232b0 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -198,11 +198,11 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) if (!crtcp->cursor_tex) { struct pipe_texture templat; - unsigned pitch; + struct winsys_handle whandle; memset(&templat, 0, sizeof(templat)); templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + templat.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; templat.target = PIPE_TEXTURE_2D; templat.last_level = 0; templat.depth0 = 1; @@ -210,25 +210,26 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) templat.width0 = 64; templat.height0 = 64; + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + crtcp->cursor_tex = ms->screen->texture_create(ms->screen, &templat); - ms->api->local_handle_from_texture(ms->api, - ms->screen, - crtcp->cursor_tex, - &pitch, - &crtcp->cursor_handle); + ms->screen->texture_get_handle(ms->screen, crtcp->cursor_tex, &whandle); + + crtcp->cursor_handle = whandle.handle; } - transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex, - 0, 0, 0, - PIPE_TRANSFER_WRITE, - 0, 0, 64, 64); - ptr = ms->screen->transfer_map(ms->screen, transfer); + transfer = ms->ctx->get_tex_transfer(ms->ctx, crtcp->cursor_tex, + 0, 0, 0, + PIPE_TRANSFER_WRITE, + 0, 0, 64, 64); + ptr = ms->ctx->transfer_map(ms->ctx, transfer); util_copy_rect(ptr, crtcp->cursor_tex->format, transfer->stride, 0, 0, 64, 64, (void*)image, 64 * 4, 0, 0); - ms->screen->transfer_unmap(ms->screen, transfer); - ms->screen->tex_transfer_destroy(transfer); + ms->ctx->transfer_unmap(ms->ctx, transfer); + ms->ctx->tex_transfer_destroy(ms->ctx, transfer); } #if HAVE_LIBKMS diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index 5fc85c0e98c..f23e4c6cc7c 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -67,7 +67,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form struct exa_pixmap_priv *exa_priv; BufferPrivatePtr private = buffer->driverPrivate; PixmapPtr pPixmap; - unsigned stride, handle; + struct winsys_handle whandle; if (pDraw->type == DRAWABLE_PIXMAP) pPixmap = (PixmapPtr) pDraw; @@ -75,6 +75,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw); exa_priv = exaGetPixmapDriverPrivate(pPixmap); + switch (buffer->attachment) { default: if (buffer->attachment != DRI2BufferFakeFrontLeft || @@ -128,7 +129,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form template.depth0 = 1; template.last_level = 0; template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + PIPE_TEXTURE_USAGE_SHARED; tex = ms->screen->texture_create(ms->screen, &template); pipe_texture_reference(&exa_priv->depth_stencil_tex, tex); } @@ -153,10 +154,13 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form if (!tex) FatalError("NO TEXTURE IN DRI2\n"); - ms->api->shared_handle_from_texture(ms->api, ms->screen, tex, &stride, &handle); + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + + ms->screen->texture_get_handle(ms->screen, tex, &whandle); - buffer->name = handle; - buffer->pitch = stride; + buffer->name = whandle.handle; + buffer->pitch = whandle.stride; buffer->cpp = 4; buffer->driverPrivate = private; buffer->flags = 0; /* not tiled */ diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index d7c67463d21..8ac5179545a 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -994,8 +994,9 @@ static Bool drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); - unsigned handle, stride, fb_id; struct pipe_texture *tex; + struct winsys_handle whandle; + unsigned fb_id; int ret; ms->noEvict = TRUE; @@ -1006,10 +1007,10 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) if (!tex) return FALSE; - if (!ms->api->local_handle_from_texture(ms->api, ms->screen, - tex, - &stride, - &handle)) + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + if (!ms->screen->texture_get_handle(ms->screen, tex, &whandle)) goto err_destroy; ret = drmModeAddFB(ms->fd, @@ -1017,8 +1018,8 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, - stride, - handle, + whandle.stride, + whandle.handle, &fb_id); if (ret) { debug_printf("%s: failed to create framebuffer (%i, %s)\n", diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index a242e02ee77..76e6411bb8c 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -188,11 +188,7 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, if (!priv || !priv->tex) return FALSE; - if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE) - exa->pipe->flush(exa->pipe, 0, NULL); - - transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, + transfer = exa->pipe->get_tex_transfer(exa->pipe, priv->tex, 0, 0, 0, PIPE_TRANSFER_READ, x, y, w, h); if (!transfer) return FALSE; @@ -203,11 +199,11 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, #endif util_copy_rect((unsigned char*)dst, priv->tex->format, dst_pitch, 0, 0, - w, h, exa->scrn->transfer_map(exa->scrn, transfer), + w, h, exa->pipe->transfer_map(exa->pipe, transfer), transfer->stride, 0, 0); - exa->scrn->transfer_unmap(exa->scrn, transfer); - exa->scrn->tex_transfer_destroy(transfer); + exa->pipe->transfer_unmap(exa->pipe, transfer); + exa->pipe->tex_transfer_destroy(exa->pipe, transfer); return TRUE; } @@ -226,12 +222,7 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, if (!priv || !priv->tex) return FALSE; - /* make sure that any pending operations are flushed to hardware */ - if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & - (PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE)) - xorg_exa_flush(exa, 0, NULL); - - transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, + transfer = exa->pipe->get_tex_transfer(exa->pipe, priv->tex, 0, 0, 0, PIPE_TRANSFER_WRITE, x, y, w, h); if (!transfer) return FALSE; @@ -241,12 +232,12 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, x, y, w, h, src_pitch); #endif - util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), + util_copy_rect(exa->pipe->transfer_map(exa->pipe, transfer), priv->tex->format, transfer->stride, 0, 0, w, h, (unsigned char*)src, src_pitch, 0, 0); - exa->scrn->transfer_unmap(exa->scrn, transfer); - exa->scrn->tex_transfer_destroy(transfer); + exa->pipe->transfer_unmap(exa->pipe, transfer); + exa->pipe->tex_transfer_destroy(exa->pipe, transfer); return TRUE; } @@ -270,15 +261,11 @@ ExaPrepareAccess(PixmapPtr pPix, int index) if (priv->map_count == 0) { - if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE) - exa->pipe->flush(exa->pipe, 0, NULL); - assert(pPix->drawable.width <= priv->tex->width0); assert(pPix->drawable.height <= priv->tex->height0); priv->map_transfer = - exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, + exa->pipe->get_tex_transfer(exa->pipe, priv->tex, 0, 0, 0, #ifdef EXA_MIXED_PIXMAPS PIPE_TRANSFER_MAP_DIRECTLY | #endif @@ -294,7 +281,7 @@ ExaPrepareAccess(PixmapPtr pPix, int index) #endif pPix->devPrivate.ptr = - exa->scrn->transfer_map(exa->scrn, priv->map_transfer); + exa->pipe->transfer_map(exa->pipe, priv->map_transfer); pPix->devKind = priv->map_transfer->stride; } @@ -321,8 +308,8 @@ ExaFinishAccess(PixmapPtr pPix, int index) if (--priv->map_count == 0) { assert(priv->map_transfer); - exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer); - exa->scrn->tex_transfer_destroy(priv->map_transfer); + exa->pipe->transfer_unmap(exa->pipe, priv->map_transfer); + exa->pipe->tex_transfer_destroy(exa->pipe, priv->map_transfer); priv->map_transfer = NULL; pPix->devPrivate.ptr = NULL; } @@ -789,7 +776,7 @@ xorg_exa_set_displayed_usage(PixmapPtr pPixmap) return 0; } - priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY; + priv->flags |= PIPE_TEXTURE_USAGE_SCANOUT; return 0; } @@ -805,7 +792,7 @@ xorg_exa_set_shared_usage(PixmapPtr pPixmap) return 0; } - priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + priv->flags |= PIPE_TEXTURE_USAGE_SHARED; return 0; } @@ -943,7 +930,7 @@ xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex) { struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); - int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + int mask = PIPE_TEXTURE_USAGE_SHARED | PIPE_TEXTURE_USAGE_SCANOUT; if (!priv) return FALSE; @@ -976,8 +963,8 @@ xorg_exa_create_root_texture(ScrnInfoPtr pScrn, template.depth0 = 1; template.last_level = 0; template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; - template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + template.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; + template.tex_usage |= PIPE_TEXTURE_USAGE_SHARED; return exa->scrn->texture_create(exa->scrn, &template); } @@ -988,6 +975,9 @@ xorg_exa_close(ScrnInfoPtr pScrn) modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); + pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); + renderer_destroy(exa->renderer); if (exa->pipe) diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h index f2cefe23b99..41b19061599 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.h +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -18,7 +18,7 @@ struct exa_context struct pipe_screen *scrn; struct xorg_renderer *renderer; - struct pipe_texture *bound_textures[MAX_EXA_SAMPLERS]; + struct pipe_sampler_view *bound_sampler_views[MAX_EXA_SAMPLERS]; int num_bound_samplers; float solid_color[4]; diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c index 83b0d31e38d..81b0dcf656f 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.c +++ b/src/gallium/state_trackers/xorg/xorg_renderer.c @@ -8,6 +8,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_rect.h" +#include "util/u_sampler.h" #include "util/u_inlines.h" @@ -68,6 +69,8 @@ renderer_draw(struct xorg_renderer *r) if (buf) { + cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems); + util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, num_verts, /* verts */ @@ -92,6 +95,7 @@ renderer_init_state(struct xorg_renderer *r) { struct pipe_depth_stencil_alpha_state dsa; struct pipe_rasterizer_state raster; + unsigned i; /* set common initial clip state */ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); @@ -103,6 +107,14 @@ renderer_init_state(struct xorg_renderer *r) raster.gl_rasterization_rules = 1; cso_set_rasterizer(r->cso, &raster); + /* vertex elements state */ + memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3); + for (i = 0; i < 3; i++) { + r->velems[i].src_offset = i * 4 * sizeof(float); + r->velems[i].instance_divisor = 0; + r->velems[i].vertex_buffer_index = 0; + r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } } @@ -471,8 +483,17 @@ void renderer_copy_prepare(struct xorg_renderer *r, dst_surface->width, dst_surface->height); - /* texture */ - cso_set_sampler_textures(r->cso, 1, &src_texture); + /* texture/sampler view */ + { + struct pipe_sampler_view templ; + struct pipe_sampler_view *src_view; + u_sampler_view_default_template(&templ, + src_texture, + src_texture->format); + src_view = pipe->create_sampler_view(pipe, src_texture, &templ); + cso_set_fragment_sampler_views(r->cso, 1, &src_view); + pipe_sampler_view_reference(&src_view, NULL); + } /* shaders */ shader = xorg_shaders_get(r->shaders, @@ -600,6 +621,8 @@ void renderer_draw_yuv(struct xorg_renderer *r, if (buf) { const int num_attribs = 2; /*pos + tex coord*/ + cso_set_vertex_elements(r->cso, num_attribs, r->velems); + util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ @@ -642,7 +665,6 @@ void renderer_draw_flush(struct xorg_renderer *r) } void renderer_begin_textures(struct xorg_renderer *r, - struct pipe_texture **textures, int num_textures) { r->attrs_per_vertex = 1 + num_textures; @@ -652,7 +674,7 @@ void renderer_begin_textures(struct xorg_renderer *r, void renderer_texture(struct xorg_renderer *r, int *pos, int width, int height, - struct pipe_texture **textures, + struct pipe_sampler_view **sampler_view, int num_textures, float *src_matrix, float *mask_matrix) @@ -680,7 +702,7 @@ void renderer_texture(struct xorg_renderer *r, pos[0], pos[1], /* src */ pos[4], pos[5], /* dst */ width, height, - textures[0], src_matrix); + sampler_view[0]->texture, src_matrix); break; case 3: renderer_draw_conditional(r, 4 * 12); @@ -689,7 +711,7 @@ void renderer_texture(struct xorg_renderer *r, pos[2], pos[3], /* mask */ pos[4], pos[5], /* dst */ width, height, - textures[0], textures[1], + sampler_view[0]->texture, sampler_view[1]->texture, src_matrix, mask_matrix); break; default: diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h index af6aa0567d6..cc5802e79b2 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.h +++ b/src/gallium/state_trackers/xorg/xorg_renderer.h @@ -28,6 +28,7 @@ struct xorg_renderer { float buffer[BUF_SIZE]; int buffer_size; + struct pipe_vertex_element velems[3]; /* number of attributes per vertex for the current * draw operation */ @@ -64,12 +65,12 @@ void renderer_solid(struct xorg_renderer *r, float *color); void renderer_begin_textures(struct xorg_renderer *r, - struct pipe_texture **textures, int num_textures); + void renderer_texture(struct xorg_renderer *r, int *pos, int width, int height, - struct pipe_texture **textures, + struct pipe_sampler_view **textures, int num_textures, float *src_matrix, float *mask_matrix); diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c index e37a1c39596..5efda6837de 100644 --- a/src/gallium/state_trackers/xorg/xorg_xv.c +++ b/src/gallium/state_trackers/xorg/xorg_xv.c @@ -9,6 +9,7 @@ #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" +#include "util/u_sampler.h" #include "pipe/p_screen.h" @@ -91,6 +92,7 @@ struct xorg_xv_port_priv { /* juggle two sets of seperate Y, U and V * textures */ struct pipe_texture *yuv[2][3]; + struct pipe_sampler_view *yuv_views[2][3]; }; @@ -180,32 +182,60 @@ static int check_yuv_textures(struct xorg_xv_port_priv *priv, int width, int height) { struct pipe_texture **dst = priv->yuv[priv->current_set]; + struct pipe_sampler_view **dst_view = priv->yuv_views[priv->current_set]; + struct pipe_sampler_view view_templ; + struct pipe_context *pipe = priv->r->pipe; + if (!dst[0] || dst[0]->width0 != width || dst[0]->height0 != height) { pipe_texture_reference(&dst[0], NULL); + pipe_sampler_view_reference(&dst_view[0], NULL); } if (!dst[1] || dst[1]->width0 != width || dst[1]->height0 != height) { pipe_texture_reference(&dst[1], NULL); + pipe_sampler_view_reference(&dst_view[1], NULL); } if (!dst[2] || dst[2]->width0 != width || dst[2]->height0 != height) { pipe_texture_reference(&dst[2], NULL); + pipe_sampler_view_reference(&dst_view[2], NULL); } - if (!dst[0]) + if (!dst[0]) { dst[0] = create_component_texture(priv->r->pipe, width, height); + if (dst[0]) { + u_sampler_view_default_template(&view_templ, + dst[0], + dst[0]->format); + dst_view[0] = pipe->create_sampler_view(pipe, dst[0], &view_templ); + } + } - if (!dst[1]) + if (!dst[1]) { dst[1] = create_component_texture(priv->r->pipe, width, height); + if (dst[1]) { + u_sampler_view_default_template(&view_templ, + dst[1], + dst[1]->format); + dst_view[1] = pipe->create_sampler_view(pipe, dst[1], &view_templ); + } + } - if (!dst[2]) + if (!dst[2]) { dst[2] = create_component_texture(priv->r->pipe, width, height); + if (dst[2]) { + u_sampler_view_default_template(&view_templ, + dst[2], + dst[2]->format); + dst_view[2] = pipe->create_sampler_view(pipe, dst[2], &view_templ); + } + } - if (!dst[0] || !dst[1] || !dst[2]) + if (!dst[0] || !dst[1] || !dst[2] || !dst_view[0] || !dst_view[1] || !dst_view[2] ) return BadAlloc; return Success; @@ -275,28 +305,28 @@ copy_packed_data(ScrnInfoPtr pScrn, int i, j; struct pipe_texture **dst = port->yuv[port->current_set]; struct pipe_transfer *ytrans, *utrans, *vtrans; - struct pipe_screen *screen = port->r->pipe->screen; + struct pipe_context *pipe = port->r->pipe; char *ymap, *vmap, *umap; unsigned char y1, y2, u, v; int yidx, uidx, vidx; int y_array_size = w * h; - ytrans = screen->get_tex_transfer(screen, dst[0], - 0, 0, 0, - PIPE_TRANSFER_WRITE, - left, top, w, h); - utrans = screen->get_tex_transfer(screen, dst[1], - 0, 0, 0, - PIPE_TRANSFER_WRITE, - left, top, w, h); - vtrans = screen->get_tex_transfer(screen, dst[2], - 0, 0, 0, - PIPE_TRANSFER_WRITE, - left, top, w, h); - - ymap = (char*)screen->transfer_map(screen, ytrans); - umap = (char*)screen->transfer_map(screen, utrans); - vmap = (char*)screen->transfer_map(screen, vtrans); + ytrans = pipe->get_tex_transfer(pipe, dst[0], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + utrans = pipe->get_tex_transfer(pipe, dst[1], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + vtrans = pipe->get_tex_transfer(pipe, dst[2], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + + ymap = (char*)pipe->transfer_map(pipe, ytrans); + umap = (char*)pipe->transfer_map(pipe, utrans); + vmap = (char*)pipe->transfer_map(pipe, vtrans); yidx = uidx = vidx = 0; @@ -362,12 +392,12 @@ copy_packed_data(ScrnInfoPtr pScrn, break; } - screen->transfer_unmap(screen, ytrans); - screen->transfer_unmap(screen, utrans); - screen->transfer_unmap(screen, vtrans); - screen->tex_transfer_destroy(ytrans); - screen->tex_transfer_destroy(utrans); - screen->tex_transfer_destroy(vtrans); + pipe->transfer_unmap(pipe, ytrans); + pipe->transfer_unmap(pipe, utrans); + pipe->transfer_unmap(pipe, vtrans); + pipe->tex_transfer_destroy(pipe, ytrans); + pipe->tex_transfer_destroy(pipe, utrans); + pipe->tex_transfer_destroy(pipe, vtrans); } @@ -450,6 +480,7 @@ bind_samplers(struct xorg_xv_port_priv *port) struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state sampler; struct pipe_texture **dst = port->yuv[port->current_set]; + struct pipe_sampler_view **dst_views = port->yuv_views[port->current_set]; memset(&sampler, 0, sizeof(struct pipe_sampler_state)); @@ -469,8 +500,7 @@ bind_samplers(struct xorg_xv_port_priv *port) cso_set_samplers(port->r->cso, 3, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(port->r->cso, 3, - dst); + cso_set_fragment_sampler_views(port->r->cso, 3, dst_views); } static int diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index 87d1dfaace2..12d94e0c5ca 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -106,7 +106,7 @@ CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, u template.width0 = width; template.height0 = height; template.depth0 = 1; - template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + template.tex_usage = PIPE_TEXTURE_USAGE_SHARED; tex = vpipe->screen->texture_create(vpipe->screen, &template); if (!tex) diff --git a/src/gallium/targets/Makefile b/src/gallium/targets/Makefile new file mode 100644 index 00000000000..a0bc5eb14fa --- /dev/null +++ b/src/gallium/targets/Makefile @@ -0,0 +1,12 @@ +# src/gallium/winsys/Makefile +TOP = ../../.. +include $(TOP)/configs/current + +SUBDIRS = $(GALLIUM_TARGET_DIRS) + +default install clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1; \ + fi \ + done diff --git a/src/gallium/targets/SConscript b/src/gallium/targets/SConscript new file mode 100644 index 00000000000..df62fc65fb7 --- /dev/null +++ b/src/gallium/targets/SConscript @@ -0,0 +1,16 @@ +Import('*') + +#if env['dri']: +# SConscript([ +# 'drm/SConscript', +# ]) + +if 'xlib' in env['winsys']: + SConscript([ + 'libgl-xlib/SConscript', + ]) + +if 'gdi' in env['winsys']: + SConscript([ + 'libgl-gdi/SConscript', + ]) diff --git a/src/gallium/targets/libgl-gdi/SConscript b/src/gallium/targets/libgl-gdi/SConscript new file mode 100644 index 00000000000..57704440ce7 --- /dev/null +++ b/src/gallium/targets/libgl-gdi/SConscript @@ -0,0 +1,51 @@ +####################################################################### +# SConscript for gdi winsys + +Import('*') + +if env['platform'] == 'windows': + + env = env.Clone() + + env.Append(CPPPATH = [ + '#src/gallium/state_trackers/wgl', + ]) + + env.Append(LIBS = [ + 'gdi32', + 'user32', + 'kernel32', + 'ws2_32', + ]) + + sources = [] + drivers = [] + + if 'softpipe' in env['drivers']: + sources = ['gdi_softpipe_winsys.c'] + drivers = [softpipe] + + if 'llvmpipe' in env['drivers']: + env.Tool('llvm') + if 'LLVM_VERSION' in env: + sources = ['gdi_llvmpipe_winsys.c'] + drivers = [llvmpipe] + + if not sources or not drivers: + print 'warning: softpipe or llvmpipe not selected, gdi winsys disabled' + Return() + + if env['gcc']: + sources += ['#src/gallium/state_trackers/wgl/opengl32.mingw.def'] + else: + sources += ['#src/gallium/state_trackers/wgl/opengl32.def'] + + drivers += [trace] + + env['no_import_lib'] = 1 + + env.SharedLibrary( + target ='opengl32', + source = sources, + LIBS = wgl + ws_gdi + glapi + mesa + drivers + gallium + glsl + env['LIBS'], + ) diff --git a/src/gallium/targets/libgl-gdi/gdi_llvmpipe_winsys.c b/src/gallium/targets/libgl-gdi/gdi_llvmpipe_winsys.c new file mode 100644 index 00000000000..29316a1ce28 --- /dev/null +++ b/src/gallium/targets/libgl-gdi/gdi_llvmpipe_winsys.c @@ -0,0 +1,124 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/** + * @file + * LLVMpipe support. + * + * @author Jose Fonseca <[email protected]> + */ + + +#include <windows.h> + +#include "stw_winsys.h" +#include "gdi/gdi_sw_winsys.h" +#include "llvmpipe/lp_texture.h" +#include "llvmpipe/lp_screen.h" +#include "llvmpipe/lp_public.h" + + +static struct pipe_screen * +gdi_llvmpipe_screen_create(void) +{ + static struct sw_winsys *winsys; + struct pipe_screen *screen; + + winsys = gdi_create_sw_winsys(); + if(!winsys) + goto no_winsys; + + screen = llvmpipe_create_screen(winsys); + if(!screen) + goto no_screen; + + return screen; + +no_screen: + winsys->destroy(winsys); +no_winsys: + return NULL; +} + + + + +static void +gdi_llvmpipe_present(struct pipe_screen *screen, + struct pipe_surface *surface, + HDC hDC) +{ + /* This will fail if any interposing layer (trace, debug, etc) has + * been introduced between the state-trackers and llvmpipe. + * + * Ideally this would get replaced with a call to + * pipe_screen::flush_frontbuffer(). + * + * Failing that, it may be necessary for intervening layers to wrap + * other structs such as this stw_winsys as well... + */ + gdi_sw_display(llvmpipe_screen(screen)->winsys, + llvmpipe_texture(surface->texture)->dt, + hDC); +} + + +static const struct stw_winsys stw_winsys = { + &gdi_llvmpipe_screen_create, + &gdi_llvmpipe_present, + NULL, /* get_adapter_luid */ + NULL, /* shared_surface_open */ + NULL, /* shared_surface_close */ + NULL /* compose */ +}; + + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + stw_init(&stw_winsys); + stw_init_thread(); + break; + + case DLL_THREAD_ATTACH: + stw_init_thread(); + break; + + case DLL_THREAD_DETACH: + stw_cleanup_thread(); + break; + + case DLL_PROCESS_DETACH: + stw_cleanup_thread(); + stw_cleanup(); + break; + } + return TRUE; +} diff --git a/src/gallium/targets/libgl-gdi/gdi_softpipe_winsys.c b/src/gallium/targets/libgl-gdi/gdi_softpipe_winsys.c new file mode 100644 index 00000000000..dfe60195d94 --- /dev/null +++ b/src/gallium/targets/libgl-gdi/gdi_softpipe_winsys.c @@ -0,0 +1,124 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/** + * @file + * LLVMpipe support. + * + * @author Jose Fonseca <[email protected]> + */ + + +#include <windows.h> + +#include "stw_winsys.h" +#include "gdi/gdi_sw_winsys.h" +#include "softpipe/sp_texture.h" +#include "softpipe/sp_screen.h" +#include "softpipe/sp_public.h" + + +static struct pipe_screen * +gdi_softpipe_screen_create(void) +{ + static struct sw_winsys *winsys; + struct pipe_screen *screen; + + winsys = gdi_create_sw_winsys(); + if(!winsys) + goto no_winsys; + + screen = softpipe_create_screen(winsys); + if(!screen) + goto no_screen; + + return screen; + +no_screen: + winsys->destroy(winsys); +no_winsys: + return NULL; +} + + + + +static void +gdi_softpipe_present(struct pipe_screen *screen, + struct pipe_surface *surface, + HDC hDC) +{ + /* This will fail if any interposing layer (trace, debug, etc) has + * been introduced between the state-trackers and softpipe. + * + * Ideally this would get replaced with a call to + * pipe_screen::flush_frontbuffer(). + * + * Failing that, it may be necessary for intervening layers to wrap + * other structs such as this stw_winsys as well... + */ + gdi_sw_display(softpipe_screen(screen)->winsys, + softpipe_texture(surface->texture)->dt, + hDC); +} + + +static const struct stw_winsys stw_winsys = { + &gdi_softpipe_screen_create, + &gdi_softpipe_present, + NULL, /* get_adapter_luid */ + NULL, /* shared_surface_open */ + NULL, /* shared_surface_close */ + NULL /* compose */ +}; + + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + stw_init(&stw_winsys); + stw_init_thread(); + break; + + case DLL_THREAD_ATTACH: + stw_init_thread(); + break; + + case DLL_THREAD_DETACH: + stw_cleanup_thread(); + break; + + case DLL_PROCESS_DETACH: + stw_cleanup_thread(); + stw_cleanup(); + break; + } + return TRUE; +} diff --git a/src/gallium/targets/libgl-xlib/Makefile b/src/gallium/targets/libgl-xlib/Makefile new file mode 100644 index 00000000000..5a4e035c2eb --- /dev/null +++ b/src/gallium/targets/libgl-xlib/Makefile @@ -0,0 +1,100 @@ +# src/gallium/targets/libgl-xlib/Makefile + +# This makefile produces a "stand-alone" libGL.so which is based on +# Xlib (no DRI HW acceleration) + + +TOP = ../../../.. +include $(TOP)/configs/current + + +GL_MAJOR = 1 +GL_MINOR = 5 +GL_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY) + + +INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/state_trackers/glx/xlib \ + -I$(TOP)/src/gallium/auxiliary + +DEFINES += \ + -DGALLIUM_SOFTPIPE +#-DGALLIUM_CELL will be defined by the config */ + +XLIB_TARGET_SOURCES = \ + xlib.c + + +XLIB_TARGET_OBJECTS = $(XLIB_TARGET_SOURCES:.c=.o) + + +# Note: CELL_SPU_LIB is only defined for cell configs + +LIBS = \ + $(GALLIUM_DRIVERS) \ + $(TOP)/src/gallium/state_trackers/glx/xlib/libxlib.a \ + $(TOP)/src/gallium/winsys/xlib/libws_xlib.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/identity/libidentity.a \ + $(TOP)/src/mesa/libglapi.a \ + $(TOP)/src/mesa/libmesagallium.a \ + $(GALLIUM_AUXILIARIES) \ + $(CELL_SPU_LIB) \ + + +.SUFFIXES : .cpp + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + +.cpp.o: + $(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@ + + + +default: $(TOP)/$(LIB_DIR)/gallium $(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME) + +$(TOP)/$(LIB_DIR)/gallium: + @ mkdir -p $(TOP)/$(LIB_DIR)/gallium + +# Make the libGL.so library +$(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME): $(XLIB_TARGET_OBJECTS) $(LIBS) Makefile + $(TOP)/bin/mklib -o $(GL_LIB) \ + -linker "$(CC)" \ + -major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \ + -install $(TOP)/$(LIB_DIR)/gallium \ + $(MKLIB_OPTIONS) $(XLIB_TARGET_OBJECTS) \ + -Wl,--start-group $(LIBS) -Wl,--end-group $(GL_LIB_DEPS) + + +depend: $(XLIB_TARGET_SOURCES) + @ echo "running $(MKDEP)" + @ rm -f depend # workaround oops on gutsy?!? + @ touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(XLIB_TARGET_SOURCES) \ + > /dev/null 2>/dev/null + + +install: default + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/include/GL + $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) + $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(DESTDIR)$(INSTALL_DIR)/include/GL + @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \ + $(MINSTALL) $(TOP)/$(LIB_DIR)/libGL* $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR); \ + fi + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h + +clean: + -rm -f *.o + + +include depend diff --git a/src/gallium/targets/libgl-xlib/SConscript b/src/gallium/targets/libgl-xlib/SConscript new file mode 100644 index 00000000000..efa7e797d1f --- /dev/null +++ b/src/gallium/targets/libgl-xlib/SConscript @@ -0,0 +1,69 @@ +####################################################################### +# SConscript for xlib winsys + +Import('*') + +if env['platform'] != 'linux': + Return() + +if 'mesa' not in env['statetrackers']: + print 'warning: Mesa state tracker disabled: skipping build of xlib libGL.so' + Return() + +if env['dri']: + print 'warning: DRI enabled: skipping build of xlib libGL.so' + Return() + +if not set(('softpipe', 'llvmpipe', 'cell')).intersection(env['drivers']): + print 'warning: no supported pipe driver: skipping build of xlib libGL.so' + Return() + +env = env.Clone() + +env.Append(CPPPATH = [ + '#/src/mesa', + '#/src/mesa/main', + '#src/gallium/state_trackers/glx/xlib', +]) + +env.Append(CPPDEFINES = ['USE_XSHM']) + +env.Prepend(LIBS = [ + st_xlib, + ws_xlib, + trace, + identity, + glapi, + mesa, + glsl, + gallium, +]) + +sources = [ + 'xlib.c', +] + +if 'softpipe' in env['drivers']: + env.Append(CPPDEFINES = 'GALLIUM_SOFTPIPE') + env.Prepend(LIBS = [softpipe]) + +if 'llvmpipe' in env['drivers']: + env.Tool('llvm') + if 'LLVM_VERSION' in env: + env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE') + env.Tool('udis86') + env.Prepend(LIBS = [llvmpipe]) + +if 'cell' in env['drivers']: + env.Append(CPPDEFINES = 'GALLIUM_CELL') + env.Prepend(LIBS = [cell]) + +# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions +libgl = env.SharedLibrary( + target ='GL', + source = sources, +) + +if not env['dri']: + # Only install this libGL.so if DRI not enabled + env.InstallSharedLibrary(libgl, version=(1, 5)) diff --git a/src/gallium/winsys/xlib/xlib.c b/src/gallium/targets/libgl-xlib/xlib.c index 67617a470d6..48e79fe4f3b 100644 --- a/src/gallium/winsys/xlib/xlib.c +++ b/src/gallium/targets/libgl-xlib/xlib.c @@ -30,66 +30,111 @@ * Authors: * Keith Whitwell */ +#include "pipe/p_compiler.h" +#include "state_tracker/xlib_sw_winsys.h" +#include "util/u_debug.h" +#include "softpipe/sp_public.h" +#include "llvmpipe/lp_public.h" +#include "cell/ppu/cell_public.h" +#include "target-helpers/wrap_screen.h" +#include "xm_public.h" -#include "xlib.h" -#include "xm_winsys.h" - -#include <stdlib.h> -#include <assert.h> - -/* Todo, replace all this with callback-structs provided by the - * individual implementations. - */ - -enum mode { - MODE_CELL, - MODE_LLVMPIPE, - MODE_SOFTPIPE -}; +#include "state_tracker/st_manager.h" /* advertise OpenGL support */ PUBLIC const int st_api_OpenGL = 1; -static enum mode get_mode() +PUBLIC const struct st_module st_module_OpenGL = { + .api = ST_API_OPENGL, + .create_api = st_manager_create_api +}; + +/* Helper function to build a subset of a driver stack consisting of + * one of the software rasterizers (cell, llvmpipe, softpipe) and the + * xlib winsys. + * + * This function could be shared, but currently causes headaches for + * the build systems, particularly scons if we try. Long term, want + * to avoid having global #defines for things like GALLIUM_LLVMPIPE, + * GALLIUM_CELL, etc. Scons already eliminates those #defines, so + * things that are painful for it now are likely to be painful for + * other build systems in the future. + */ +static struct pipe_screen * +swrast_xlib_create_screen( Display *display ) { -#ifdef GALLIUM_CELL - if (!getenv("GALLIUM_NOCELL")) - return MODE_CELL; -#endif + const char *default_driver; + const char *driver; + struct sw_winsys *winsys; + struct pipe_screen *screen = NULL; + + /* Create the underlying winsys, which performs presents to Xlib + * drawables: + */ + winsys = xlib_create_sw_winsys( display ); + if (winsys == NULL) + return NULL; -#if defined(GALLIUM_LLVMPIPE) - return MODE_LLVMPIPE; +#if defined(GALLIUM_CELL) + default_driver = "cell"; +#elif defined(GALLIUM_LLVMPIPE) + default_driver = "llvmpipe"; +#elif defined(GALLIUM_SOFTPIPE) + default_driver = "softpipe"; #else - return MODE_SOFTPIPE; + default_driver = ""; #endif -} -static void _init( void ) __attribute__((constructor)); - -static void _init( void ) -{ - enum mode xlib_mode = get_mode(); + driver = debug_get_option("GALLIUM_DRIVER", default_driver); - switch (xlib_mode) { - case MODE_CELL: + /* Create a software rasterizer on top of that winsys: + */ #if defined(GALLIUM_CELL) - xmesa_set_driver( &xlib_cell_driver ); + if (screen == NULL && + strcmp(driver, "cell") == 0) + screen = cell_create_screen( winsys ); #endif - break; - case MODE_LLVMPIPE: + #if defined(GALLIUM_LLVMPIPE) - xmesa_set_driver( &xlib_llvmpipe_driver ); + if (screen == NULL && + strcmp(driver, "llvmpipe") == 0) + screen = llvmpipe_create_screen( winsys ); #endif - break; - case MODE_SOFTPIPE: + #if defined(GALLIUM_SOFTPIPE) - xmesa_set_driver( &xlib_softpipe_driver ); + if (screen == NULL) + screen = softpipe_create_screen( winsys ); #endif - break; - default: - assert(0); - break; - } + + if (screen == NULL) + goto fail; + + /* Inject any wrapping layers we want to here: + */ + return gallium_wrap_screen( screen ); + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; +} + +static struct xm_driver xlib_driver = +{ + .create_pipe_screen = swrast_xlib_create_screen, + .create_st_api = st_manager_create_api, +}; + + +/* Build the rendering stack. + */ +static void _init( void ) __attribute__((constructor)); +static void _init( void ) +{ + /* Initialize the xlib libgl code, pass in the winsys: + */ + xmesa_set_driver( &xlib_driver ); } diff --git a/src/gallium/winsys/drm/Makefile b/src/gallium/winsys/drm/Makefile index fee01916432..a998aff931d 100644 --- a/src/gallium/winsys/drm/Makefile +++ b/src/gallium/winsys/drm/Makefile @@ -2,7 +2,7 @@ TOP = ../../../.. include $(TOP)/configs/current -SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS) +SUBDIRS = sw $(GALLIUM_WINSYS_DRM_DIRS) default install clean: @for dir in $(SUBDIRS) ; do \ diff --git a/src/gallium/winsys/drm/Makefile.egl b/src/gallium/winsys/drm/Makefile.egl index 8363de6e975..bc5dd3a53b8 100644 --- a/src/gallium/winsys/drm/Makefile.egl +++ b/src/gallium/winsys/drm/Makefile.egl @@ -13,7 +13,8 @@ EGL_DRIVER_OBJECTS = $(EGL_DRIVER_SOURCES:.c=.o) common_LIBS = -ldrm -lm -ldl -x11_ST = $(TOP)/src/gallium/state_trackers/egl/libeglx11.a +x11_ST = $(TOP)/src/gallium/state_trackers/egl/libeglx11.a \ + $(TOP)/src/gallium/winsys/xlib/libws_xlib.a x11_LIBS = $(common_LIBS) -lX11 -lXext -lXfixes kms_ST = $(TOP)/src/gallium/state_trackers/egl/libeglkms.a @@ -38,8 +39,10 @@ $(EGL_DISPLAY_LIBS): $(TOP)/$(LIB_DIR)/%.so: %.so define mklib-egl $(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ - $(MKLIB_OPTIONS) $(EGL_DRIVER_OBJECTS) $($(1)_ST) \ - $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $($(1)_LIBS) $(EGL_DRIVER_LIBS) + $(MKLIB_OPTIONS) $(EGL_DRIVER_OBJECTS) \ + -Wl,--start-group $($(1)_ST) $(EGL_DRIVER_PIPES) \ + $(GALLIUM_AUXILIARIES) -Wl,--end-group \ + $($(1)_LIBS) $(EGL_DRIVER_LIBS) endef egl_x11_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(x11_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile diff --git a/src/gallium/winsys/drm/i965/dri/Makefile b/src/gallium/winsys/drm/i965/dri/Makefile index f7e81eed87b..56690769fc7 100644 --- a/src/gallium/winsys/drm/i965/dri/Makefile +++ b/src/gallium/winsys/drm/i965/dri/Makefile @@ -7,6 +7,7 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/winsys/drm/sw/libswdrm.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/identity/libidentity.a \ $(TOP)/src/gallium/drivers/i965/libi965.a diff --git a/src/gallium/winsys/drm/i965/gem/i965_drm_api.c b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c index a061eef0beb..c644eedcb31 100644 --- a/src/gallium/winsys/drm/i965/gem/i965_drm_api.c +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c @@ -10,6 +10,8 @@ #include "trace/tr_drm.h" +#include "../../sw/sw_drm_api.h" + /* * Helper functions */ @@ -37,129 +39,6 @@ i965_libdrm_get_device_id(unsigned int *device_id) fclose(file); } -static struct i965_libdrm_buffer * -i965_libdrm_buffer_from_handle(struct i965_libdrm_winsys *idws, - const char* name, unsigned handle) -{ - struct i965_libdrm_buffer *buf = CALLOC_STRUCT(i965_libdrm_buffer); - uint32_t swizzle = 0; - - if (BRW_DUMP) - debug_printf("%s\n", __FUNCTION__); - - if (!buf) - return NULL; - pipe_reference_init(&buf->base.reference, 1); - buf->bo = drm_intel_bo_gem_create_from_name(idws->gem, name, handle); - buf->base.size = buf->bo->size; - buf->base.sws = &idws->base; - buf->flinked = TRUE; - buf->flink = handle; - - - if (!buf->bo) - goto err; - - drm_intel_bo_get_tiling(buf->bo, &buf->tiling, &swizzle); - if (buf->tiling != 0) - buf->map_gtt = TRUE; - - return buf; - -err: - FREE(buf); - return NULL; -} - - -/* - * Exported functions - */ - - -static struct pipe_texture * -i965_libdrm_texture_from_shared_handle(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *template, - const char* name, - unsigned pitch, - unsigned handle) -{ - /* XXX: this is silly -- there should be a way to get directly from - * the "drm_api" struct to ourselves, without peering into - * unrelated code: - */ - struct i965_libdrm_winsys *idws = i965_libdrm_winsys(brw_screen(screen)->sws); - struct i965_libdrm_buffer *buffer; - - if (BRW_DUMP) - debug_printf("%s %s pitch %d handle 0x%x\n", __FUNCTION__, - name, pitch, handle); - - buffer = i965_libdrm_buffer_from_handle(idws, name, handle); - if (!buffer) - return NULL; - - return brw_texture_blanket_winsys_buffer(screen, template, pitch, - buffer->tiling, - &buffer->base); -} - - -static boolean -i965_libdrm_shared_handle_from_texture(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *pitch, - unsigned *handle) -{ - struct i965_libdrm_buffer *buf = NULL; - struct brw_winsys_buffer *buffer = NULL; - - if (BRW_DUMP) - debug_printf("%s\n", __FUNCTION__); - - if (!brw_texture_get_winsys_buffer(texture, &buffer, pitch)) - return FALSE; - - buf = i965_libdrm_buffer(buffer); - if (!buf->flinked) { - if (drm_intel_bo_flink(buf->bo, &buf->flink)) - return FALSE; - buf->flinked = TRUE; - } - - *handle = buf->flink; - - if (BRW_DUMP) - debug_printf(" -> pitch %d handle 0x%x\n", *pitch, *handle); - - return TRUE; -} - -static boolean -i965_libdrm_local_handle_from_texture(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *pitch, - unsigned *handle) -{ - struct brw_winsys_buffer *buffer = NULL; - - if (BRW_DUMP) - debug_printf("%s\n", __FUNCTION__); - - if (!brw_texture_get_winsys_buffer(texture, &buffer, pitch)) - return FALSE; - - *handle = i965_libdrm_buffer(buffer)->bo->handle; - - if (BRW_DUMP) - debug_printf(" -> pitch %d handle 0x%x\n", *pitch, *handle); - - return TRUE; -} - static void i965_libdrm_winsys_destroy(struct brw_winsys_screen *iws) { @@ -225,14 +104,19 @@ struct drm_api i965_libdrm_api = { .name = "i965", .create_screen = i965_libdrm_create_screen, - .texture_from_shared_handle = i965_libdrm_texture_from_shared_handle, - .shared_handle_from_texture = i965_libdrm_shared_handle_from_texture, - .local_handle_from_texture = i965_libdrm_local_handle_from_texture, .destroy = destroy, }; struct drm_api * drm_api_create() { - return trace_drm_create(&i965_libdrm_api); + struct drm_api *api = NULL; + + if (api == NULL && debug_get_bool_option("BRW_SOFTPIPE", FALSE)) + api = sw_drm_api_create(&i965_libdrm_api); + + if (api == NULL) + api = &i965_libdrm_api; + + return trace_drm_create(api); } diff --git a/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c b/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c index 07be1df87f0..33a17496b2b 100644 --- a/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_buffer.c @@ -1,4 +1,5 @@ +#include "state_tracker/drm_api.h" #include "i965_drm_winsys.h" #include "util/u_memory.h" #include "util/u_inlines.h" @@ -122,6 +123,78 @@ err: return PIPE_ERROR_OUT_OF_MEMORY; } +static enum pipe_error +i965_libdrm_bo_from_handle(struct brw_winsys_screen *sws, + struct winsys_handle *whandle, + unsigned *stride, + unsigned *tile, + struct brw_winsys_buffer **bo_out) +{ + struct i965_libdrm_winsys *idws = i965_libdrm_winsys(sws); + struct i965_libdrm_buffer *buf = CALLOC_STRUCT(i965_libdrm_buffer); + uint32_t swizzle = 0; + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + if (!buf) + return PIPE_ERROR_OUT_OF_MEMORY; + + pipe_reference_init(&buf->base.reference, 1); + buf->bo = drm_intel_bo_gem_create_from_name(idws->gem, "FROM_HANDLE", whandle->handle); + buf->base.size = buf->bo->size; + buf->base.sws = &idws->base; + buf->flinked = TRUE; + buf->flink = whandle->handle; + + + if (!buf->bo) + goto err; + + drm_intel_bo_get_tiling(buf->bo, &buf->tiling, &swizzle); + if (buf->tiling != 0) + buf->map_gtt = TRUE; + + *tile = buf->tiling; + *stride = whandle->stride; + + *bo_out = &buf->base; + return PIPE_OK; + +err: + FREE(buf); + return PIPE_ERROR_OUT_OF_MEMORY; +} + +static enum pipe_error +i965_libdrm_bo_get_handle(struct brw_winsys_buffer *buffer, + struct winsys_handle *whandle, + unsigned stride) +{ + struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer); + + if (BRW_DUMP) + debug_printf("%s\n", __FUNCTION__); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!buf->flinked) { + if (drm_intel_bo_flink(buf->bo, &buf->flink)) + return PIPE_ERROR_BAD_INPUT; + buf->flinked = TRUE; + } + + whandle->handle = buf->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = buf->bo->handle; + } else { + assert(!"unknown usage"); + return PIPE_ERROR_BAD_INPUT; + } + + whandle->stride = stride; + return PIPE_OK; +} + static void i965_libdrm_bo_destroy(struct brw_winsys_buffer *buffer) { @@ -415,6 +488,8 @@ void i965_libdrm_winsys_init_buffer_functions(struct i965_libdrm_winsys *idws) { idws->base.bo_alloc = i965_libdrm_bo_alloc; + idws->base.bo_from_handle = i965_libdrm_bo_from_handle; + idws->base.bo_get_handle = i965_libdrm_bo_get_handle; idws->base.bo_destroy = i965_libdrm_bo_destroy; idws->base.bo_emit_reloc = i965_libdrm_bo_emit_reloc; idws->base.bo_exec = i965_libdrm_bo_exec; diff --git a/src/gallium/winsys/drm/i965/xlib/xlib_i965.c b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c index 74501eeb16f..063e9f600b9 100644 --- a/src/gallium/winsys/drm/i965/xlib/xlib_i965.c +++ b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c @@ -38,7 +38,7 @@ #include "pipe/p_error.h" #include "pipe/p_context.h" -#include "xm_winsys.h" +#include "xm_public.h" #include "i965/brw_winsys.h" #include "i965/brw_screen.h" diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c index 377ed255131..e3b980a832b 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c @@ -38,99 +38,6 @@ intel_drm_get_device_id(unsigned int *device_id) fclose(file); } -static struct intel_buffer * -intel_drm_buffer_from_handle(struct intel_drm_winsys *idws, - const char* name, unsigned handle) -{ - struct intel_drm_buffer *buf = CALLOC_STRUCT(intel_drm_buffer); - uint32_t tile = 0, swizzle = 0; - - if (!buf) - return NULL; - - buf->magic = 0xDEAD1337; - buf->bo = drm_intel_bo_gem_create_from_name(idws->pools.gem, name, handle); - buf->flinked = TRUE; - buf->flink = handle; - - if (!buf->bo) - goto err; - - drm_intel_bo_get_tiling(buf->bo, &tile, &swizzle); - if (tile != INTEL_TILE_NONE) - buf->map_gtt = TRUE; - - return (struct intel_buffer *)buf; - -err: - FREE(buf); - return NULL; -} - - -/* - * Exported functions - */ - - -static struct pipe_texture * -intel_drm_texture_from_shared_handle(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *templ, - const char* name, - unsigned pitch, - unsigned handle) -{ - struct intel_drm_winsys *idws = intel_drm_winsys(i915_screen(screen)->iws); - struct intel_buffer *buffer; - - buffer = intel_drm_buffer_from_handle(idws, name, handle); - if (!buffer) - return NULL; - - return i915_texture_blanket_intel(screen, templ, pitch, buffer); -} - -static boolean -intel_drm_shared_handle_from_texture(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *pitch, - unsigned *handle) -{ - struct intel_drm_buffer *buf = NULL; - struct intel_buffer *buffer = NULL; - if (!i915_get_texture_buffer_intel(texture, &buffer, pitch)) - return FALSE; - - buf = intel_drm_buffer(buffer); - if (!buf->flinked) { - if (drm_intel_bo_flink(buf->bo, &buf->flink)) - return FALSE; - buf->flinked = TRUE; - } - - *handle = buf->flink; - - return TRUE; -} - -static boolean -intel_drm_local_handle_from_texture(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *pitch, - unsigned *handle) -{ - struct intel_buffer *buffer = NULL; - if (!i915_get_texture_buffer_intel(texture, &buffer, pitch)) - return FALSE; - - *handle = intel_drm_buffer(buffer)->bo->handle; - - return TRUE; -} - static void intel_drm_winsys_destroy(struct intel_winsys *iws) { @@ -192,9 +99,6 @@ struct drm_api intel_drm_api = .name = "i915", .driver_name = "i915", .create_screen = intel_drm_create_screen, - .texture_from_shared_handle = intel_drm_texture_from_shared_handle, - .shared_handle_from_texture = intel_drm_shared_handle_from_texture, - .local_handle_from_texture = intel_drm_local_handle_from_texture, .destroy = destroy, }; diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c b/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c index ac4dd6e00e9..cb4f92a3b17 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c +++ b/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c @@ -1,4 +1,5 @@ +#include "state_tracker/drm_api.h" #include "intel_drm_winsys.h" #include "util/u_memory.h" @@ -52,6 +53,66 @@ err: return NULL; } +static struct intel_buffer * +intel_drm_buffer_from_handle(struct intel_winsys *iws, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct intel_drm_winsys *idws = intel_drm_winsys(iws); + struct intel_drm_buffer *buf = CALLOC_STRUCT(intel_drm_buffer); + uint32_t tile = 0, swizzle = 0; + + if (!buf) + return NULL; + + buf->magic = 0xDEAD1337; + buf->bo = drm_intel_bo_gem_create_from_name(idws->pools.gem, "gallium3d_from_handle", whandle->handle); + buf->flinked = TRUE; + buf->flink = whandle->handle; + + if (!buf->bo) + goto err; + + drm_intel_bo_get_tiling(buf->bo, &tile, &swizzle); + if (tile != INTEL_TILE_NONE) + buf->map_gtt = TRUE; + + *stride = whandle->stride; + + return (struct intel_buffer *)buf; + +err: + FREE(buf); + return NULL; +} + +static boolean +intel_drm_buffer_get_handle(struct intel_winsys *iws, + struct intel_buffer *buffer, + struct winsys_handle *whandle, + unsigned stride) +{ + struct intel_drm_buffer *buf = intel_drm_buffer(buffer); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!buf->flinked) { + if (drm_intel_bo_flink(buf->bo, &buf->flink)) + return FALSE; + buf->flinked = TRUE; + } + + whandle->handle = buf->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = buf->bo->handle; + } else { + assert(!"unknown usage"); + return FALSE; + } + + whandle->stride = stride; + return TRUE; +} + static int intel_drm_buffer_set_fence_reg(struct intel_winsys *iws, struct intel_buffer *buffer, @@ -146,6 +207,8 @@ void intel_drm_winsys_init_buffer_functions(struct intel_drm_winsys *idws) { idws->base.buffer_create = intel_drm_buffer_create; + idws->base.buffer_from_handle = intel_drm_buffer_from_handle; + idws->base.buffer_get_handle = intel_drm_buffer_get_handle; idws->base.buffer_set_fence_reg = intel_drm_buffer_set_fence_reg; idws->base.buffer_map = intel_drm_buffer_map; idws->base.buffer_unmap = intel_drm_buffer_unmap; diff --git a/src/gallium/winsys/drm/nouveau/dri/Makefile b/src/gallium/winsys/drm/nouveau/dri/Makefile index 7e95f79d03c..50ac3f203e5 100644 --- a/src/gallium/winsys/drm/nouveau/dri/Makefile +++ b/src/gallium/winsys/drm/nouveau/dri/Makefile @@ -6,8 +6,7 @@ LIBNAME = nouveau_dri.so PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv30/libnv30.a \ - $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c index 0d05f316c42..716d4bacd3b 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -21,9 +21,10 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen, struct pipe_surface *ps = NULL; struct pipe_texture *pt = NULL; struct pipe_texture tmpl; + struct winsys_handle whandle; memset(&tmpl, 0, sizeof(tmpl)); - tmpl.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY; + tmpl.tex_usage = PIPE_TEXTURE_USAGE_SCANOUT; tmpl.target = PIPE_TEXTURE_2D; tmpl.last_level = 0; tmpl.depth0 = 1; @@ -31,8 +32,11 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen, tmpl.width0 = width; tmpl.height0 = height; - pt = api->texture_from_shared_handle(api, pscreen, &tmpl, - "front buffer", pitch, handle); + memset(&whandle, 0, sizeof(whandle)); + whandle.stride = pitch; + whandle.handle = handle; + + pt = pscreen->texture_from_handle(pscreen, &tmpl, &whandle); if (!pt) return NULL; @@ -82,11 +86,9 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, switch (dev->chipset & 0xf0) { case 0x30: - init = nv30_screen_create; - break; case 0x40: case 0x60: - init = nv40_screen_create; + init = nvfx_screen_create; break; case 0x50: case 0x80: @@ -142,74 +144,10 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, return nvws->pscreen; } -static struct pipe_texture * -nouveau_drm_pt_from_name(struct drm_api *api, struct pipe_screen *pscreen, - struct pipe_texture *templ, const char *name, - unsigned stride, unsigned handle) -{ - struct nouveau_device *dev = nouveau_screen(pscreen)->device; - struct pipe_texture *pt; - struct pipe_buffer *pb; - int ret; - - pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*)); - if (!pb) - return NULL; - - ret = nouveau_bo_handle_ref(dev, handle, (struct nouveau_bo**)(pb+1)); - if (ret) { - debug_printf("%s: ref name 0x%08x failed with %d\n", - __func__, handle, ret); - FREE(pb); - return NULL; - } - - pipe_reference_init(&pb->reference, 1); - pb->screen = pscreen; - pb->alignment = 0; - pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | - PIPE_BUFFER_USAGE_CPU_READ_WRITE; - pb->size = nouveau_bo(pb)->size; - pt = pscreen->texture_blanket(pscreen, templ, &stride, pb); - pipe_buffer_reference(&pb, NULL); - return pt; -} - -static boolean -nouveau_drm_name_from_pt(struct drm_api *api, struct pipe_screen *pscreen, - struct pipe_texture *pt, unsigned *stride, - unsigned *handle) -{ - struct nouveau_miptree *mt = nouveau_miptree(pt); - - if (!mt || !mt->bo) - return false; - - return nouveau_bo_handle_get(mt->bo, handle) == 0; -} - -static boolean -nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen, - struct pipe_texture *pt, unsigned *stride, - unsigned *handle) -{ - struct nouveau_miptree *mt = nouveau_miptree(pt); - - if (!mt || !mt->bo) - return false; - - *handle = mt->bo->handle; - *stride = util_format_get_stride(mt->base.format, mt->base.width0); - return true; -} - struct drm_api drm_api_hooks = { .name = "nouveau", .driver_name = "nouveau", .create_screen = nouveau_drm_create_screen, - .texture_from_shared_handle = nouveau_drm_pt_from_name, - .shared_handle_from_texture = nouveau_drm_name_from_pt, - .local_handle_from_texture = nouveau_drm_handle_from_pt, }; struct drm_api * diff --git a/src/gallium/winsys/drm/nouveau/egl/Makefile b/src/gallium/winsys/drm/nouveau/egl/Makefile index 2c352603320..47d11276155 100644 --- a/src/gallium/winsys/drm/nouveau/egl/Makefile +++ b/src/gallium/winsys/drm/nouveau/egl/Makefile @@ -7,8 +7,7 @@ EGL_DRIVER_LIBS = -ldrm_nouveau EGL_DRIVER_PIPES = \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv30/libnv30.a \ - $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a diff --git a/src/gallium/winsys/drm/nouveau/xorg/Makefile b/src/gallium/winsys/drm/nouveau/xorg/Makefile index 179b50230b5..f7f6fe17dd6 100644 --- a/src/gallium/winsys/drm/nouveau/xorg/Makefile +++ b/src/gallium/winsys/drm/nouveau/xorg/Makefile @@ -18,8 +18,7 @@ INCLUDES = \ LIBS = \ $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv30/libnv30.a \ - $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ $(GALLIUM_AUXILIARIES) diff --git a/src/gallium/winsys/drm/radeon/core/Makefile b/src/gallium/winsys/drm/radeon/core/Makefile index 860cbb6dbf8..13bbbf730d6 100644 --- a/src/gallium/winsys/drm/radeon/core/Makefile +++ b/src/gallium/winsys/drm/radeon/core/Makefile @@ -5,7 +5,7 @@ include $(TOP)/configs/current LIBNAME = radeonwinsys C_SOURCES = \ - radeon_buffer.c \ + radeon_drm_buffer.c \ radeon_drm.c \ radeon_r300.c diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c index e5c69199330..25b58b2926c 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -213,6 +213,18 @@ static void radeon_buffer_unmap(struct pipe_winsys *ws, } } +static boolean radeon_is_buffer_referenced(struct radeon_winsys *ws, + struct pipe_buffer *buffer) +{ + struct radeon_pipe_buffer *radeon_buffer = + (struct radeon_pipe_buffer*)buffer; + uint32_t domain; + + /* Referenced by CS or HW. */ + return radeon_bo_is_referenced_by_cs(radeon_buffer->bo, ws->priv->cs) || + radeon_bo_is_busy(radeon_buffer->bo, &domain); +} + static void radeon_buffer_set_tiling(struct radeon_winsys *ws, struct pipe_buffer *buffer, uint32_t pitch, @@ -264,6 +276,75 @@ static int radeon_fence_finish(struct pipe_winsys *ws, return 0; } +/* Create a buffer from a handle. */ +static struct pipe_buffer* radeon_buffer_from_handle(struct radeon_winsys *radeon_ws, + struct pipe_screen *screen, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct radeon_bo_manager* bom = radeon_ws->priv->bom; + struct radeon_pipe_buffer* radeon_buffer; + struct radeon_bo* bo = NULL; + + bo = radeon_bo_open(bom, whandle->handle, 0, 0, 0, 0); + if (bo == NULL) { + return NULL; + } + + radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer); + if (radeon_buffer == NULL) { + radeon_bo_unref(bo); + return NULL; + } + + pipe_reference_init(&radeon_buffer->base.reference, 1); + radeon_buffer->base.screen = screen; + radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL; + radeon_buffer->bo = bo; + + *stride = whandle->stride; + + return &radeon_buffer->base; +} + +static boolean radeon_buffer_get_handle(struct radeon_winsys *radeon_ws, + struct pipe_buffer *buffer, + unsigned stride, + struct winsys_handle *whandle) +{ + int retval, fd; + struct drm_gem_flink flink; + struct radeon_pipe_buffer* radeon_buffer; + + radeon_buffer = (struct radeon_pipe_buffer*)buffer; + + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!radeon_buffer->flinked) { + fd = radeon_ws->priv->fd; + + flink.handle = radeon_buffer->bo->handle; + + retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); + if (retval) { + debug_printf("radeon: DRM_IOCTL_GEM_FLINK failed, error %d\n", + retval); + return FALSE; + } + + radeon_buffer->flink = flink.name; + radeon_buffer->flinked = TRUE; + } + + whandle->handle = radeon_buffer->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = ((struct radeon_pipe_buffer*)buffer)->bo->handle; + } + whandle->stride = stride; + + return TRUE; +} + struct radeon_winsys* radeon_pipe_winsys(int fd) { struct radeon_winsys* radeon_ws; @@ -298,6 +379,10 @@ struct radeon_winsys* radeon_pipe_winsys(int fd) radeon_ws->base.get_name = radeon_get_name; radeon_ws->buffer_set_tiling = radeon_buffer_set_tiling; + radeon_ws->buffer_from_handle = radeon_buffer_from_handle; + radeon_ws->buffer_get_handle = radeon_buffer_get_handle; + + radeon_ws->is_buffer_referenced = radeon_is_buffer_referenced; return radeon_ws; } diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h index f776e2d9008..e1fcfcfccaa 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h @@ -30,48 +30,56 @@ #ifndef RADEON_BUFFER_H #define RADEON_BUFFER_H +#include <stdio.h> + +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + #include "pipebuffer/pb_buffer.h" +#include "pipebuffer/pb_bufmgr.h" #include "radeon_bo.h" #include "radeon_cs.h" #include "radeon_winsys.h" -struct radeon_pipe_buffer { - struct pipe_buffer base; - /* Pointer to GPU-backed BO. */ - struct radeon_bo *bo; - /* Pointer to fallback PB buffer. */ - struct pb_buffer *pb; - boolean flinked; - uint32_t flink; -}; #define RADEON_MAX_BOS 24 -struct radeon_winsys_priv { - /* DRM FD */ - int fd; +static INLINE struct pb_buffer * +radeon_pb_buffer(struct r300_winsys_buffer *buffer) +{ + return (struct pb_buffer *)buffer; +} - /* Radeon BO manager. */ - struct radeon_bo_manager* bom; +static INLINE struct r300_winsys_buffer * +radeon_libdrm_winsys_buffer(struct pb_buffer *buffer) +{ + return (struct r300_winsys_buffer *)buffer; +} - /* Radeon CS manager. */ - struct radeon_cs_manager* csm; +struct pb_manager * +radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws); - /* Current CS. */ - struct radeon_cs* cs; +boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf, + uint32_t rd, uint32_t wd); - /* Flush CB */ - void (*flush_cb)(void *); - void *flush_data; -}; -struct radeon_winsys* radeon_pipe_winsys(int fb); -#if 0 -struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context, - uint32_t handle, - enum pipe_format format, - int w, int h, int pitch); -#endif +void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf, + uint32_t rd, uint32_t wd, + uint32_t flags); + +struct radeon_libdrm_winsys* radeon_pipe_winsys(int fd); + +struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, + uint32_t handle); + +void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, boolean microtiled, boolean macrotiled, uint32_t pitch); + +void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr); + +boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, + struct winsys_handle *whandle); + +boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf); #endif diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c index e817a26da6d..d70173e805d 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -41,8 +41,22 @@ #include "xf86drm.h" #include <sys/ioctl.h> +static struct radeon_libdrm_winsys * +radeon_winsys_create(int fd) +{ + struct radeon_libdrm_winsys *rws; + + rws = CALLOC_STRUCT(radeon_libdrm_winsys); + if (rws == NULL) { + return NULL; + } + + rws->fd = fd; + return rws; +} + /* Helper function to do the ioctls needed for setup and init. */ -static void do_ioctls(int fd, struct radeon_winsys* winsys) +static void do_ioctls(int fd, struct radeon_libdrm_winsys* winsys) { struct drm_radeon_gem_info gem_info = {0}; struct drm_radeon_info info = {0}; @@ -133,137 +147,28 @@ struct pipe_screen* radeon_create_screen(struct drm_api* api, int drmFB, struct drm_create_screen_arg *arg) { - struct radeon_winsys* rwinsys = radeon_pipe_winsys(drmFB); - do_ioctls(drmFB, rwinsys); + struct radeon_libdrm_winsys* rws; + boolean ret; + + rws = radeon_winsys_create(drmFB); + if (!rws) + return NULL; + + do_ioctls(drmFB, rws); /* The state tracker can organize a softpipe fallback if no hw * driver is found. */ - if (is_r3xx(rwinsys->pci_id)) { - radeon_setup_winsys(drmFB, rwinsys); - return r300_create_screen(rwinsys); - } else { - FREE(rwinsys); - return NULL; - } -} - - -boolean radeon_buffer_from_texture(struct drm_api* api, - struct pipe_screen* screen, - struct pipe_texture* texture, - struct pipe_buffer** buffer, - unsigned* stride) -{ - /* XXX fix this */ - return r300_get_texture_buffer(screen, texture, buffer, stride); -} - -/* Create a buffer from a handle. */ -/* XXX what's up with name? */ -struct pipe_buffer* radeon_buffer_from_handle(struct drm_api* api, - struct pipe_screen* screen, - const char* name, - unsigned handle) -{ - struct radeon_bo_manager* bom = - ((struct radeon_winsys*)screen->winsys)->priv->bom; - struct radeon_pipe_buffer* radeon_buffer; - struct radeon_bo* bo = NULL; - - bo = radeon_bo_open(bom, handle, 0, 0, 0, 0); - if (bo == NULL) { - return NULL; - } - - radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer); - if (radeon_buffer == NULL) { - radeon_bo_unref(bo); - return NULL; - } - - pipe_reference_init(&radeon_buffer->base.reference, 1); - radeon_buffer->base.screen = screen; - radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL; - radeon_buffer->bo = bo; - return &radeon_buffer->base; -} - -static struct pipe_texture* -radeon_texture_from_shared_handle(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *templ, - const char *name, - unsigned stride, - unsigned handle) -{ - struct pipe_buffer *buffer; - struct pipe_texture *blanket; - - buffer = radeon_buffer_from_handle(api, screen, name, handle); - if (!buffer) { - return NULL; - } - - blanket = screen->texture_blanket(screen, templ, &stride, buffer); - - pipe_buffer_reference(&buffer, NULL); - - return blanket; -} - -static boolean radeon_shared_handle_from_texture(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *stride, - unsigned *handle) -{ - int retval, fd; - struct drm_gem_flink flink; - struct radeon_pipe_buffer* radeon_buffer; - struct pipe_buffer *buffer = NULL; - - if (!radeon_buffer_from_texture(api, screen, texture, &buffer, stride)) { - return FALSE; + if (is_r3xx(rws->pci_id)) { + ret = radeon_setup_winsys(drmFB, rws); + if (ret == FALSE) + goto fail; + return r300_create_screen(&rws->base); } - radeon_buffer = (struct radeon_pipe_buffer*)buffer; - if (!radeon_buffer->flinked) { - fd = ((struct radeon_winsys*)screen->winsys)->priv->fd; - - flink.handle = radeon_buffer->bo->handle; - - retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - if (retval) { - debug_printf("radeon: DRM_IOCTL_GEM_FLINK failed, error %d\n", - retval); - return FALSE; - } - - radeon_buffer->flink = flink.name; - radeon_buffer->flinked = TRUE; - } - - *handle = radeon_buffer->flink; - return TRUE; -} - -static boolean radeon_local_handle_from_texture(struct drm_api *api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *stride, - unsigned *handle) -{ - struct pipe_buffer *buffer = NULL; - if (!radeon_buffer_from_texture(api, screen, texture, &buffer, stride)) { - return FALSE; - } - - *handle = ((struct radeon_pipe_buffer*)buffer)->bo->handle; - - pipe_buffer_reference(&buffer, NULL); - - return TRUE; +fail: + FREE(rws); + return NULL; } static void radeon_drm_api_destroy(struct drm_api *api) @@ -275,9 +180,6 @@ struct drm_api drm_api_hooks = { .name = "radeon", .driver_name = "radeon", .create_screen = radeon_create_screen, - .texture_from_shared_handle = radeon_texture_from_shared_handle, - .shared_handle_from_texture = radeon_shared_handle_from_texture, - .local_handle_from_texture = radeon_local_handle_from_texture, .destroy = radeon_drm_api_destroy, }; diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.h b/src/gallium/winsys/drm/radeon/core/radeon_drm.h index f62a9b80485..2dc077c0521 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.h @@ -37,18 +37,12 @@ struct pipe_screen* radeon_create_screen(struct drm_api* api, int drmFB, struct drm_create_screen_arg *arg); - boolean radeon_buffer_from_texture(struct drm_api* api, struct pipe_screen* screen, struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); -struct pipe_buffer* radeon_buffer_from_handle(struct drm_api* api, - struct pipe_screen* screen, - const char* name, - unsigned handle); - boolean radeon_handle_from_buffer(struct drm_api* api, struct pipe_screen* screen, struct pipe_buffer* buffer, diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c new file mode 100644 index 00000000000..cc56a2bb8fd --- /dev/null +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c @@ -0,0 +1,368 @@ + +#include <sys/ioctl.h> +#include "radeon_drm.h" +#include "radeon_bo_gem.h" +#include "radeon_cs_gem.h" +#include "radeon_buffer.h" + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" +#include "pipebuffer/pb_buffer.h" +#include "pipebuffer/pb_bufmgr.h" + +#include "radeon_winsys.h" +struct radeon_drm_bufmgr; + +struct radeon_drm_buffer { + struct pb_buffer base; + struct radeon_drm_bufmgr *mgr; + + struct radeon_bo *bo; + + boolean flinked; + uint32_t flink; + + boolean mapped; + struct radeon_drm_buffer *next, *prev; +}; + +extern const struct pb_vtbl radeon_drm_buffer_vtbl; + + +static INLINE struct radeon_drm_buffer * +radeon_drm_buffer(struct pb_buffer *buf) +{ + assert(buf); + assert(buf->vtbl == &radeon_drm_buffer_vtbl); + return (struct radeon_drm_buffer *)buf; +} + +struct radeon_drm_bufmgr { + struct pb_manager base; + struct radeon_libdrm_winsys *rws; + struct radeon_drm_buffer buffer_map_list; +}; + +static INLINE struct radeon_drm_bufmgr * +radeon_drm_bufmgr(struct pb_manager *mgr) +{ + assert(mgr); + return (struct radeon_drm_bufmgr *)mgr; +} + +static void +radeon_drm_buffer_destroy(struct pb_buffer *_buf) +{ + struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); + + if (buf->mapped) { + remove_from_list(buf); + radeon_bo_unmap(buf->bo); + buf->mapped = false; + } + radeon_bo_unref(buf->bo); + + FREE(buf); +} + +static void * +radeon_drm_buffer_map(struct pb_buffer *_buf, + unsigned flags) +{ + struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); + int write; + + if (buf->mapped) + return buf->bo->ptr; + + if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { + uint32_t domain; + + if (radeon_bo_is_busy(buf->bo, &domain)) + return NULL; + } + + + if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) { + buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data); + } + + if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) { + write = 1; + } + + if (radeon_bo_map(buf->bo, write)) { + return NULL; + } + buf->mapped = true; + insert_at_tail(&buf->mgr->buffer_map_list, buf); + return buf->bo->ptr; +} + +static void +radeon_drm_buffer_unmap(struct pb_buffer *_buf) +{ + (void)_buf; +} + +static void +radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf, + struct pb_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + + +static enum pipe_error +radeon_drm_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + /* Always pinned */ + return PIPE_OK; +} + +static void +radeon_drm_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ +} + +const struct pb_vtbl radeon_drm_buffer_vtbl = { + radeon_drm_buffer_destroy, + radeon_drm_buffer_map, + radeon_drm_buffer_unmap, + radeon_drm_buffer_validate, + radeon_drm_buffer_fence, + radeon_drm_buffer_get_base_buffer, +}; + + +static uint32_t radeon_domain_from_usage(unsigned usage) +{ + uint32_t domain = 0; + + if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_PIXEL) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_VERTEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + if (usage & PIPE_BUFFER_USAGE_INDEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + + return domain; +} + +struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, + uint32_t handle) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + struct radeon_libdrm_winsys *rws = mgr->rws; + struct radeon_drm_buffer *buf; + struct radeon_bo *bo; + + bo = radeon_bo_open(rws->bom, handle, 0, + 0, 0, 0); + if (bo == NULL) + return NULL; + + buf = CALLOC_STRUCT(radeon_drm_buffer); + if (!buf) { + radeon_bo_unref(bo); + return NULL; + } + + make_empty_list(buf); + + pipe_reference_init(&buf->base.base.reference, 1); + buf->base.base.alignment = 0; + buf->base.base.usage = PIPE_BUFFER_USAGE_PIXEL; + buf->base.base.size = 0; + buf->base.vtbl = &radeon_drm_buffer_vtbl; + buf->mgr = mgr; + + buf->bo = bo; + + return &buf->base; +} + +static struct pb_buffer * +radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr, + pb_size size, + const struct pb_desc *desc) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + struct radeon_libdrm_winsys *rws = mgr->rws; + struct radeon_drm_buffer *buf; + uint32_t domain; + + buf = CALLOC_STRUCT(radeon_drm_buffer); + if (!buf) + goto error1; + + pipe_reference_init(&buf->base.base.reference, 1); + buf->base.base.alignment = desc->alignment; + buf->base.base.usage = desc->usage; + buf->base.base.size = size; + buf->base.vtbl = &radeon_drm_buffer_vtbl; + buf->mgr = mgr; + + make_empty_list(buf); + domain = radeon_domain_from_usage(desc->usage); + buf->bo = radeon_bo_open(rws->bom, 0, size, + desc->alignment, domain, 0); + if (buf->bo == NULL) + goto error2; + + return &buf->base; + + error2: + FREE(buf); + error1: + return NULL; +} + +static void +radeon_drm_bufmgr_flush(struct pb_manager *mgr) +{ + /* NOP */ +} + +static void +radeon_drm_bufmgr_destroy(struct pb_manager *_mgr) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + FREE(mgr); +} + +struct pb_manager * +radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws) +{ + struct radeon_drm_bufmgr *mgr; + + mgr = CALLOC_STRUCT(radeon_drm_bufmgr); + if (!mgr) + return NULL; + + mgr->base.destroy = radeon_drm_bufmgr_destroy; + mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer; + mgr->base.flush = radeon_drm_bufmgr_flush; + + mgr->rws = rws; + make_empty_list(&mgr->buffer_map_list); + return &mgr->base; +} + +static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf) +{ + struct radeon_drm_buffer *buf; + if (_buf->vtbl == &radeon_drm_buffer_vtbl) { + buf = radeon_drm_buffer(_buf); + } else { + struct pb_buffer *base_buf; + pb_size offset; + pb_get_base_buffer(_buf, &base_buf, &offset); + + buf = radeon_drm_buffer(base_buf); + } + return buf; +} + +boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, + struct winsys_handle *whandle) +{ + int retval, fd; + struct drm_gem_flink flink; + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!buf->flinked) { + fd = buf->mgr->rws->fd; + flink.handle = buf->bo->handle; + + retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); + if (retval) { + return false; + } + + buf->flinked = TRUE; + buf->flink = flink.name; + } + whandle->handle = buf->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = buf->bo->handle; + } + return TRUE; +} + + +void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, boolean microtiled, boolean macrotiled, uint32_t pitch) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + uint32_t flags = 0; + + if (microtiled) + flags |= RADEON_BO_FLAGS_MICRO_TILE; + if (macrotiled) + flags |= RADEON_BO_FLAGS_MACRO_TILE; + + radeon_bo_set_tiling(buf->bo, flags, pitch); + +} + +boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf, + uint32_t rd, uint32_t wd) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo, + rd, wd); + return true; +} + +void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf, + uint32_t rd, uint32_t wd, + uint32_t flags) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + int retval; + + retval = radeon_cs_write_reloc(buf->mgr->rws->cs, + buf->bo, rd, wd, flags); + if (retval) { + debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", + buf, rd, wd, flags); + } +} + +boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + uint32_t domain; + + return (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs) || + radeon_bo_is_busy(buf->bo, &domain)); +} + + +void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + struct radeon_drm_buffer *rpb, *t_rpb; + + foreach_s(rpb, t_rpb, &mgr->buffer_map_list) { + rpb->mapped = 0; + radeon_bo_unmap(rpb->bo); + remove_from_list(rpb); + } + + make_empty_list(&mgr->buffer_map_list); + + +} diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index 122bd213543..5b82a776a81 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -23,31 +23,139 @@ #include "radeon_r300.h" #include "radeon_buffer.h" +#include "radeon_bo_gem.h" #include "radeon_cs_gem.h" +#include "state_tracker/drm_api.h" -static void radeon_set_flush_cb(struct radeon_winsys *winsys, +static struct r300_winsys_buffer * +radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + struct pb_desc desc; + struct pb_manager *provider; + struct pb_buffer *buffer; + + memset(&desc, 0, sizeof(desc)); + desc.alignment = alignment; + desc.usage = usage; + + if (usage & PIPE_BUFFER_USAGE_CONSTANT) + provider = ws->mman; + else + provider = ws->kman; + buffer = provider->create_buffer(provider, size, &desc); + if (!buffer) + return NULL; + + return radeon_libdrm_winsys_buffer(buffer); +} + +static void radeon_r300_winsys_buffer_destroy(struct r300_winsys_buffer *buf) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + pb_destroy(_buf); +} +static void radeon_r300_winsys_buffer_set_tiling(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, + uint32_t pitch, + boolean microtiled, + boolean macrotiled) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + radeon_drm_bufmgr_set_tiling(_buf, microtiled, macrotiled, pitch); +} + +static void *radeon_r300_winsys_buffer_map(struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf, + unsigned usage) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + return pb_map(_buf, usage); +} + +static void radeon_r300_winsys_buffer_unmap(struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + pb_unmap(_buf); +} + +static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws, + struct r300_winsys_buffer **pdst, + struct r300_winsys_buffer *src) +{ + struct pb_buffer *_src = radeon_pb_buffer(src); + struct pb_buffer *_dst = radeon_pb_buffer(*pdst); + + pb_reference(&_dst, _src); + + *pdst = radeon_libdrm_winsys_buffer(_dst); +} + +static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + return radeon_drm_bufmgr_is_buffer_referenced(_buf); +} + +static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws, + struct pipe_screen *screen, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + struct pb_buffer *_buf; + + _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle); + *stride = whandle->stride; + return radeon_libdrm_winsys_buffer(_buf); +} + +static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buffer, + unsigned stride, + struct winsys_handle *whandle) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buffer); + boolean ret; + ret = radeon_drm_bufmgr_get_handle(_buf, whandle); + if (ret) + whandle->stride = stride; + return ret; +} + +static void radeon_set_flush_cb(struct r300_winsys_screen *rws, void (*flush_cb)(void *), void *data) { - winsys->priv->flush_cb = flush_cb; - winsys->priv->flush_data = data; - radeon_cs_space_set_flush(winsys->priv->cs, flush_cb, data); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + ws->flush_cb = flush_cb; + ws->flush_data = data; + radeon_cs_space_set_flush(ws->cs, flush_cb, data); } -static boolean radeon_add_buffer(struct radeon_winsys* winsys, - struct pipe_buffer* pbuffer, +static boolean radeon_add_buffer(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, uint32_t rd, uint32_t wd) { - struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo; + struct pb_buffer *_buf = radeon_pb_buffer(buf); - radeon_cs_space_add_persistent_bo(winsys->priv->cs, bo, rd, wd); - return TRUE; + return radeon_drm_bufmgr_add_buffer(_buf, rd, wd); } -static boolean radeon_validate(struct radeon_winsys* winsys) +static boolean radeon_validate(struct r300_winsys_screen *rws) { - if (radeon_cs_space_check(winsys->priv->cs) < 0) { + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + if (radeon_cs_space_check(ws->cs) < 0) { return FALSE; } @@ -55,108 +163,175 @@ static boolean radeon_validate(struct radeon_winsys* winsys) return TRUE; } -static boolean radeon_check_cs(struct radeon_winsys* winsys, int size) +static boolean radeon_check_cs(struct r300_winsys_screen *rws, int size) { - struct radeon_cs* cs = winsys->priv->cs; + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + struct radeon_cs *cs = ws->cs; - return radeon_validate(winsys) && cs->cdw + size <= cs->ndw; + return radeon_validate(rws) && cs->cdw + size <= cs->ndw; } -static void radeon_begin_cs(struct radeon_winsys* winsys, +static void radeon_begin_cs(struct r300_winsys_screen *rws, int size, const char* file, const char* function, int line) { - radeon_cs_begin(winsys->priv->cs, size, file, function, line); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_begin(ws->cs, size, file, function, line); } -static void radeon_write_cs_dword(struct radeon_winsys* winsys, +static void radeon_write_cs_dword(struct r300_winsys_screen *rws, uint32_t dword) { - radeon_cs_write_dword(winsys->priv->cs, dword); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_write_dword(ws->cs, dword); } -static void radeon_write_cs_reloc(struct radeon_winsys* winsys, - struct pipe_buffer* pbuffer, +static void radeon_write_cs_reloc(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, uint32_t rd, uint32_t wd, uint32_t flags) { - int retval = 0; - struct radeon_pipe_buffer* radeon_buffer = - (struct radeon_pipe_buffer*)pbuffer; - - assert(!radeon_buffer->pb); - - retval = radeon_cs_write_reloc(winsys->priv->cs, radeon_buffer->bo, - rd, wd, flags); - - if (retval) { - debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", - pbuffer, rd, wd, flags); - } + struct pb_buffer *_buf = radeon_pb_buffer(buf); + radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags); } -static void radeon_reset_bos(struct radeon_winsys *winsys) +static void radeon_reset_bos(struct r300_winsys_screen *rws) { - radeon_cs_space_reset_bos(winsys->priv->cs); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_space_reset_bos(ws->cs); } -static void radeon_end_cs(struct radeon_winsys* winsys, +static void radeon_end_cs(struct r300_winsys_screen *rws, const char* file, const char* function, int line) { - radeon_cs_end(winsys->priv->cs, file, function, line); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_end(ws->cs, file, function, line); } -static void radeon_flush_cs(struct radeon_winsys* winsys) +static void radeon_flush_cs(struct r300_winsys_screen *rws) { + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); int retval; /* Don't flush a zero-sized CS. */ - if (!winsys->priv->cs->cdw) { + if (!ws->cs->cdw) { return; } + radeon_drm_bufmgr_flush_maps(ws->kman); /* Emit the CS. */ - retval = radeon_cs_emit(winsys->priv->cs); + retval = radeon_cs_emit(ws->cs); if (retval) { debug_printf("radeon: Bad CS, dumping...\n"); - radeon_cs_print(winsys->priv->cs, stderr); + radeon_cs_print(ws->cs, stderr); } /* Reset CS. * Someday, when we care about performance, we should really find a way * to rotate between two or three CS objects so that the GPU can be * spinning through one CS while another one is being filled. */ - radeon_cs_erase(winsys->priv->cs); + radeon_cs_erase(ws->cs); } -void -radeon_setup_winsys(int fd, struct radeon_winsys* winsys) +static uint32_t radeon_get_value(struct r300_winsys_screen *rws, + enum r300_value_id id) { - struct radeon_winsys_priv* priv = winsys->priv; + struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws; - priv->csm = radeon_cs_manager_gem_ctor(fd); + switch(id) { + case R300_VID_PCI_ID: + return ws->pci_id; + case R300_VID_GB_PIPES: + return ws->gb_pipes; + case R300_VID_Z_PIPES: + return ws->z_pipes; + } + return 0; +} + +static void +radeon_winsys_destroy(struct r300_winsys_screen *rws) +{ + struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws; + radeon_cs_destroy(ws->cs); + + ws->kman->destroy(ws->kman); + ws->mman->destroy(ws->mman); + + radeon_bo_manager_gem_dtor(ws->bom); + radeon_cs_manager_gem_dtor(ws->csm); +} + +boolean +radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws) +{ + + ws->csm = radeon_cs_manager_gem_ctor(fd); + if (!ws->csm) + goto fail; + ws->bom = radeon_bo_manager_gem_ctor(fd); + if (!ws->bom) + goto fail; + ws->kman = radeon_drm_bufmgr_create(ws); + if (!ws->kman) + goto fail; + + ws->mman = pb_malloc_bufmgr_create(); + if (!ws->mman) + goto fail; /* Size limit on IBs is 64 kibibytes. */ - priv->cs = radeon_cs_create(priv->csm, 1024 * 64 / 4); - radeon_cs_set_limit(priv->cs, - RADEON_GEM_DOMAIN_GTT, winsys->gart_size); - radeon_cs_set_limit(priv->cs, - RADEON_GEM_DOMAIN_VRAM, winsys->vram_size); - - winsys->add_buffer = radeon_add_buffer; - winsys->validate = radeon_validate; - - winsys->check_cs = radeon_check_cs; - winsys->begin_cs = radeon_begin_cs; - winsys->write_cs_dword = radeon_write_cs_dword; - winsys->write_cs_reloc = radeon_write_cs_reloc; - winsys->end_cs = radeon_end_cs; - winsys->flush_cs = radeon_flush_cs; - winsys->reset_bos = radeon_reset_bos; - winsys->set_flush_cb = radeon_set_flush_cb; + ws->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4); + if (!ws->cs) + goto fail; + radeon_cs_set_limit(ws->cs, + RADEON_GEM_DOMAIN_GTT, ws->gart_size); + radeon_cs_set_limit(ws->cs, + RADEON_GEM_DOMAIN_VRAM, ws->vram_size); + + ws->base.add_buffer = radeon_add_buffer; + ws->base.validate = radeon_validate; + ws->base.destroy = radeon_winsys_destroy; + ws->base.check_cs = radeon_check_cs; + ws->base.begin_cs = radeon_begin_cs; + ws->base.write_cs_dword = radeon_write_cs_dword; + ws->base.write_cs_reloc = radeon_write_cs_reloc; + ws->base.end_cs = radeon_end_cs; + ws->base.flush_cs = radeon_flush_cs; + ws->base.reset_bos = radeon_reset_bos; + ws->base.set_flush_cb = radeon_set_flush_cb; + ws->base.get_value = radeon_get_value; + + ws->base.buffer_create = radeon_r300_winsys_buffer_create; + ws->base.buffer_destroy = radeon_r300_winsys_buffer_destroy; + ws->base.buffer_set_tiling = radeon_r300_winsys_buffer_set_tiling; + ws->base.buffer_map = radeon_r300_winsys_buffer_map; + ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap; + ws->base.buffer_reference = radeon_r300_winsys_buffer_reference; + ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle; + ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle; + ws->base.is_buffer_referenced = radeon_r300_winsys_is_buffer_referenced; + return TRUE; + +fail: + if (ws->csm) + radeon_cs_manager_gem_dtor(ws->csm); + + if (ws->bom) + radeon_bo_manager_gem_dtor(ws->bom); + + + if (ws->kman) + ws->kman->destroy(ws->kman); + if (ws->mman) + ws->mman->destroy(ws->mman); + + if (ws->cs) + radeon_cs_destroy(ws->cs); + return FALSE; } diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.h b/src/gallium/winsys/drm/radeon/core/radeon_r300.h index e655dc32c85..2703464ad8f 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.h @@ -25,6 +25,6 @@ #include "radeon_winsys.h" -void radeon_setup_winsys(int fd, struct radeon_winsys* winsys); +boolean radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* winsys); #endif /* RADEON_R300_H */ diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h index 4901080ca7b..16cc701ad6f 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h @@ -30,16 +30,15 @@ #ifndef RADEON_WINSYS_H #define RADEON_WINSYS_H -#include "util/u_simple_screen.h" +#include "r300_winsys.h" -struct radeon_winsys_priv; - -struct radeon_winsys { +struct radeon_libdrm_winsys { /* Parent class. */ - struct pipe_winsys base; + struct r300_winsys_screen base; + + struct pb_manager *kman; - /* Winsys private */ - struct radeon_winsys_priv* priv; + struct pb_manager *mman; /* PCI ID */ uint32_t pci_id; @@ -56,56 +55,27 @@ struct radeon_winsys { /* VRAM size. */ uint32_t vram_size; - /* Add a pipe_buffer to the list of buffer objects to validate. */ - boolean (*add_buffer)(struct radeon_winsys* winsys, - struct pipe_buffer* pbuffer, - uint32_t rd, - uint32_t wd); - - /* Revalidate all currently setup pipe_buffers. - * Returns TRUE if a flush is required. */ - boolean (*validate)(struct radeon_winsys* winsys); - - /* Check to see if there's room for commands. */ - boolean (*check_cs)(struct radeon_winsys* winsys, int size); - - /* Start a command emit. */ - void (*begin_cs)(struct radeon_winsys* winsys, - int size, - const char* file, - const char* function, - int line); - - /* Write a dword to the command buffer. */ - void (*write_cs_dword)(struct radeon_winsys* winsys, uint32_t dword); - - /* Write a relocated dword to the command buffer. */ - void (*write_cs_reloc)(struct radeon_winsys* winsys, - struct pipe_buffer* bo, - uint32_t rd, - uint32_t wd, - uint32_t flags); - - /* Finish a command emit. */ - void (*end_cs)(struct radeon_winsys* winsys, - const char* file, - const char* function, - int line); - - /* Flush the CS. */ - void (*flush_cs)(struct radeon_winsys* winsys); - - /* winsys flush - callback from winsys when flush required */ - void (*set_flush_cb)(struct radeon_winsys *winsys, - void (*flush_cb)(void *), void *data); - - void (*reset_bos)(struct radeon_winsys *winsys); - - void (*buffer_set_tiling)(struct radeon_winsys* winsys, - struct pipe_buffer* buffer, - uint32_t pitch, - boolean microtiled, - boolean macrotiled); + /* DRM FD */ + int fd; + + /* Radeon BO manager. */ + struct radeon_bo_manager *bom; + + /* Radeon CS manager. */ + struct radeon_cs_manager *csm; + + /* Current CS. */ + struct radeon_cs *cs; + + /* Flush CB */ + void (*flush_cb)(void *); + void *flush_data; }; +static INLINE struct radeon_libdrm_winsys * +radeon_winsys_screen(struct r300_winsys_screen *base) +{ + return (struct radeon_libdrm_winsys *)base; +} + #endif diff --git a/src/gallium/winsys/drm/radeon/python/README b/src/gallium/winsys/drm/radeon/python/README deleted file mode 100644 index 339836a592b..00000000000 --- a/src/gallium/winsys/drm/radeon/python/README +++ /dev/null @@ -1,15 +0,0 @@ -Python bindings for the radeon gallium driver. - - -See gallium/src/gallium/state_trackers/python/README for more information. - - -Build as: - - scons debug=1 statetrackers=python winsys=drm/radeon/python - -Run as: - - export PYTHONPATH=$PWD/build/linux-x86-debug/gallium/winsys/drm/radeon/python:$PWD/build/linux-x86-debug/gallium/state_trackers/python - - python progs/gallium/python/samples/tri.py diff --git a/src/gallium/winsys/drm/radeon/python/SConscript b/src/gallium/winsys/drm/radeon/python/SConscript deleted file mode 100644 index 91cae986975..00000000000 --- a/src/gallium/winsys/drm/radeon/python/SConscript +++ /dev/null @@ -1,33 +0,0 @@ -import os.path - -Import('*') - -if env['platform'] == 'linux': - - env = env.Clone() - - env.Tool('python') - - env.ParseConfig('pkg-config --cflags --libs libdrm') - - env.Prepend(CPPPATH = [ - '#src/gallium/state_trackers/python', - '../core', - ]) - - drivers = [ - softpipe, - radeon, - trace, - ] - - sources = [ - 'radeon_hardpipe_winsys.c', - 'xf86dri.c', - ] - - env.SharedLibrary( - target ='_gallium', - source = sources, - LIBS = [pyst] + drivers + gallium + env['LIBS'], - ) diff --git a/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c b/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c deleted file mode 100644 index fc63081a4cc..00000000000 --- a/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c +++ /dev/null @@ -1,132 +0,0 @@ - /************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#include <X11/X.h> -#include <X11/Xlib.h> -#include <drm/drm.h> - -#include "pipe/p_screen.h" -#include "pipe/p_context.h" - -#include "st_winsys.h" - -#include "radeon_winsys.h" - -#include "xf86dri.h" - - -/* XXX: Force init_gallium symbol to be linked */ -extern void init_gallium(void); -void (*force_init_gallium_linkage)(void) = &init_gallium; - - -static struct pipe_screen * -radeon_hardpipe_screen_create(void) -{ - Display *dpy; - Window rootWin; - XWindowAttributes winAttr; - int isCapable; - int screen; - char *driverName; - char *curBusID; - unsigned magic; - int ddxDriverMajor; - int ddxDriverMinor; - int ddxDriverPatch; - drm_handle_t sAreaOffset; - int ret; - int drmFD; - drm_context_t hHWContext; - XID id; - - dpy = XOpenDisplay(":0"); - if (!dpy) { - fprintf(stderr, "Open Display Failed\n"); - return NULL; - } - - screen = DefaultScreen(dpy); - rootWin = RootWindow(dpy, screen); - XGetWindowAttributes(dpy, rootWin, &winAttr); - - ret = uniDRIQueryDirectRenderingCapable(dpy, screen, &isCapable); - if (!ret || !isCapable) { - fprintf(stderr, "No DRI on this display:sceen\n"); - goto error; - } - - if (!uniDRIOpenConnection(dpy, screen, &sAreaOffset, - &curBusID)) { - fprintf(stderr, "Could not open DRI connection.\n"); - goto error; - } - - if (!uniDRIGetClientDriverName(dpy, screen, &ddxDriverMajor, - &ddxDriverMinor, &ddxDriverPatch, - &driverName)) { - fprintf(stderr, "Could not get DRI driver name.\n"); - goto error; - } - - if ((drmFD = drmOpen(NULL, curBusID)) < 0) { - perror("DRM Device could not be opened"); - goto error; - } - - drmGetMagic(drmFD, &magic); - if (!uniDRIAuthConnection(dpy, screen, magic)) { - fprintf(stderr, "Could not get X server to authenticate us.\n"); - goto error; - } - - if (!uniDRICreateContext(dpy, screen, winAttr.visual, - &id, &hHWContext)) { - fprintf(stderr, "Could not create DRI context.\n"); - goto error; - } - - /* FIXME: create a radeon pipe_screen from drmFD and hHWContext */ - - return NULL; - -error: - return NULL; -} - - - - -const struct st_winsys st_hardpipe_winsys = { - &radeon_hardpipe_screen_create, -}; - diff --git a/src/gallium/winsys/drm/radeon/python/xf86dri.c b/src/gallium/winsys/drm/radeon/python/xf86dri.c deleted file mode 100644 index 1736f1e54f8..00000000000 --- a/src/gallium/winsys/drm/radeon/python/xf86dri.c +++ /dev/null @@ -1,605 +0,0 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -/* - * Authors: - * Kevin E. Martin <[email protected]> - * Jens Owen <[email protected]> - * Rickard E. (Rik) Faith <[email protected]> - * - */ - -/* THIS IS NOT AN X CONSORTIUM STANDARD */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define NEED_REPLIES -#include <X11/Xlibint.h> -#include <X11/extensions/Xext.h> -#include <X11/extensions/extutil.h> -#include "xf86dristr.h" - -static XExtensionInfo _xf86dri_info_data; -static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; -static char xf86dri_extension_name[] = XF86DRINAME; - -#define uniDRICheckExtension(dpy,i,val) \ - XextCheckExtension (dpy, i, xf86dri_extension_name, val) - -/***************************************************************************** - * * - * private utility routines * - * * - *****************************************************************************/ - -static int close_display(Display * dpy, XExtCodes * extCodes); -static /* const */ XExtensionHooks xf86dri_extension_hooks = { - NULL, /* create_gc */ - NULL, /* copy_gc */ - NULL, /* flush_gc */ - NULL, /* free_gc */ - NULL, /* create_font */ - NULL, /* free_font */ - close_display, /* close_display */ - NULL, /* wire_to_event */ - NULL, /* event_to_wire */ - NULL, /* error */ - NULL, /* error_string */ -}; - -static -XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info, - xf86dri_extension_name, &xf86dri_extension_hooks, - 0, NULL) - - static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info) - -/***************************************************************************** - * * - * public XFree86-DRI Extension routines * - * * - *****************************************************************************/ -#if 0 -#include <stdio.h> -#define TRACE(msg) fprintf(stderr,"uniDRI%s\n", msg); -#else -#define TRACE(msg) -#endif - Bool uniDRIQueryExtension(dpy, event_basep, error_basep) - Display *dpy; - int *event_basep, *error_basep; -{ - XExtDisplayInfo *info = find_display(dpy); - - TRACE("QueryExtension..."); - if (XextHasExtension(info)) { - *event_basep = info->codes->first_event; - *error_basep = info->codes->first_error; - TRACE("QueryExtension... return True"); - return True; - } else { - TRACE("QueryExtension... return False"); - return False; - } -} - -Bool -uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) - Display *dpy; - int *majorVersion; - int *minorVersion; - int *patchVersion; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIQueryVersionReply rep; - xXF86DRIQueryVersionReq *req; - - TRACE("QueryVersion..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIQueryVersion, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIQueryVersion; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("QueryVersion... return False"); - return False; - } - *majorVersion = rep.majorVersion; - *minorVersion = rep.minorVersion; - *patchVersion = rep.patchVersion; - UnlockDisplay(dpy); - SyncHandle(); - TRACE("QueryVersion... return True"); - return True; -} - -Bool -uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable) - Display *dpy; - int screen; - Bool *isCapable; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIQueryDirectRenderingCapableReply rep; - xXF86DRIQueryDirectRenderingCapableReq *req; - - TRACE("QueryDirectRenderingCapable..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIQueryDirectRenderingCapable, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIQueryDirectRenderingCapable; - req->screen = screen; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("QueryDirectRenderingCapable... return False"); - return False; - } - *isCapable = rep.isCapable; - UnlockDisplay(dpy); - SyncHandle(); - TRACE("QueryDirectRenderingCapable... return True"); - return True; -} - -Bool -uniDRIOpenConnection(dpy, screen, hSAREA, busIdString) - Display *dpy; - int screen; - drm_handle_t *hSAREA; - char **busIdString; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIOpenConnectionReply rep; - xXF86DRIOpenConnectionReq *req; - - TRACE("OpenConnection..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIOpenConnection, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIOpenConnection; - req->screen = screen; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("OpenConnection... return False"); - return False; - } - - *hSAREA = rep.hSAREALow; -#ifdef LONG64 - if (sizeof(drm_handle_t) == 8) { - *hSAREA |= ((unsigned long)rep.hSAREAHigh) << 32; - } -#endif - if (rep.length) { - if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) { - _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3)); - UnlockDisplay(dpy); - SyncHandle(); - TRACE("OpenConnection... return False"); - return False; - } - _XReadPad(dpy, *busIdString, rep.busIdStringLength); - } else { - *busIdString = NULL; - } - UnlockDisplay(dpy); - SyncHandle(); - TRACE("OpenConnection... return True"); - return True; -} - -Bool -uniDRIAuthConnection(dpy, screen, magic) - Display *dpy; - int screen; - drm_magic_t magic; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIAuthConnectionReq *req; - xXF86DRIAuthConnectionReply rep; - - TRACE("AuthConnection..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIAuthConnection, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIAuthConnection; - req->screen = screen; - req->magic = magic; - rep.authenticated = 0; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("AuthConnection... return False"); - return False; - } - UnlockDisplay(dpy); - SyncHandle(); - TRACE("AuthConnection... return True"); - return True; -} - -Bool -uniDRICloseConnection(dpy, screen) - Display *dpy; - int screen; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRICloseConnectionReq *req; - - TRACE("CloseConnection..."); - - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRICloseConnection, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRICloseConnection; - req->screen = screen; - UnlockDisplay(dpy); - SyncHandle(); - TRACE("CloseConnection... return True"); - return True; -} - -Bool -uniDRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion, - ddxDriverMinorVersion, ddxDriverPatchVersion, - clientDriverName) - Display *dpy; - int screen; - int *ddxDriverMajorVersion; - int *ddxDriverMinorVersion; - int *ddxDriverPatchVersion; - char **clientDriverName; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIGetClientDriverNameReply rep; - xXF86DRIGetClientDriverNameReq *req; - - TRACE("GetClientDriverName..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIGetClientDriverName, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIGetClientDriverName; - req->screen = screen; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetClientDriverName... return False"); - return False; - } - - *ddxDriverMajorVersion = rep.ddxDriverMajorVersion; - *ddxDriverMinorVersion = rep.ddxDriverMinorVersion; - *ddxDriverPatchVersion = rep.ddxDriverPatchVersion; - - if (rep.length) { - if (!(*clientDriverName = - (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) { - _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3)); - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetClientDriverName... return False"); - return False; - } - _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength); - } else { - *clientDriverName = NULL; - } - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetClientDriverName... return True"); - return True; -} - -Bool -uniDRICreateContextWithConfig(dpy, screen, configID, context, hHWContext) - Display *dpy; - int screen; - int configID; - XID *context; - drm_context_t *hHWContext; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRICreateContextReply rep; - xXF86DRICreateContextReq *req; - - TRACE("CreateContext..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRICreateContext, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRICreateContext; - req->visual = configID; - req->screen = screen; - *context = XAllocID(dpy); - req->context = *context; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("CreateContext... return False"); - return False; - } - *hHWContext = rep.hHWContext; - UnlockDisplay(dpy); - SyncHandle(); - TRACE("CreateContext... return True"); - return True; -} - -Bool -uniDRICreateContext(dpy, screen, visual, context, hHWContext) - Display *dpy; - int screen; - Visual *visual; - XID *context; - drm_context_t *hHWContext; -{ - return uniDRICreateContextWithConfig(dpy, screen, visual->visualid, - context, hHWContext); -} - -Bool -uniDRIDestroyContext(Display * ndpy, int screen, XID context) -{ - Display *const dpy = (Display *) ndpy; - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIDestroyContextReq *req; - - TRACE("DestroyContext..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIDestroyContext, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIDestroyContext; - req->screen = screen; - req->context = context; - UnlockDisplay(dpy); - SyncHandle(); - TRACE("DestroyContext... return True"); - return True; -} - -Bool -uniDRICreateDrawable(Display * ndpy, int screen, - Drawable drawable, drm_drawable_t * hHWDrawable) -{ - Display *const dpy = (Display *) ndpy; - XExtDisplayInfo *info = find_display(dpy); - xXF86DRICreateDrawableReply rep; - xXF86DRICreateDrawableReq *req; - - TRACE("CreateDrawable..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRICreateDrawable, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRICreateDrawable; - req->screen = screen; - req->drawable = drawable; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("CreateDrawable... return False"); - return False; - } - *hHWDrawable = rep.hHWDrawable; - UnlockDisplay(dpy); - SyncHandle(); - TRACE("CreateDrawable... return True"); - return True; -} - -Bool -uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable) -{ - Display *const dpy = (Display *) ndpy; - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIDestroyDrawableReq *req; - - TRACE("DestroyDrawable..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIDestroyDrawable, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIDestroyDrawable; - req->screen = screen; - req->drawable = drawable; - UnlockDisplay(dpy); - SyncHandle(); - TRACE("DestroyDrawable... return True"); - return True; -} - -Bool -uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable, - unsigned int *index, unsigned int *stamp, - int *X, int *Y, int *W, int *H, - int *numClipRects, drm_clip_rect_t ** pClipRects, - int *backX, int *backY, - int *numBackClipRects, - drm_clip_rect_t ** pBackClipRects) -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIGetDrawableInfoReply rep; - xXF86DRIGetDrawableInfoReq *req; - int total_rects; - - TRACE("GetDrawableInfo..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIGetDrawableInfo, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIGetDrawableInfo; - req->screen = screen; - req->drawable = drawable; - - if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetDrawableInfo... return False"); - return False; - } - *index = rep.drawableTableIndex; - *stamp = rep.drawableTableStamp; - *X = (int)rep.drawableX; - *Y = (int)rep.drawableY; - *W = (int)rep.drawableWidth; - *H = (int)rep.drawableHeight; - *numClipRects = rep.numClipRects; - total_rects = *numClipRects; - - *backX = rep.backX; - *backY = rep.backY; - *numBackClipRects = rep.numBackClipRects; - total_rects += *numBackClipRects; - -#if 0 - /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks - * backwards compatibility (Because of the >> 2 shift) but the fix - * enables multi-threaded apps to work. - */ - if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - - SIZEOF(xGenericReply) + - total_rects * sizeof(drm_clip_rect_t)) + - 3) & ~3) >> 2)) { - _XEatData(dpy, rep.length); - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetDrawableInfo... return False"); - return False; - } -#endif - - if (*numClipRects) { - int len = sizeof(drm_clip_rect_t) * (*numClipRects); - - *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); - if (*pClipRects) - _XRead(dpy, (char *)*pClipRects, len); - } else { - *pClipRects = NULL; - } - - if (*numBackClipRects) { - int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); - - *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); - if (*pBackClipRects) - _XRead(dpy, (char *)*pBackClipRects, len); - } else { - *pBackClipRects = NULL; - } - - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetDrawableInfo... return True"); - return True; -} - -Bool -uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer, - fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate) - Display *dpy; - int screen; - drm_handle_t *hFrameBuffer; - int *fbOrigin; - int *fbSize; - int *fbStride; - int *devPrivateSize; - void **pDevPrivate; -{ - XExtDisplayInfo *info = find_display(dpy); - xXF86DRIGetDeviceInfoReply rep; - xXF86DRIGetDeviceInfoReq *req; - - TRACE("GetDeviceInfo..."); - uniDRICheckExtension(dpy, info, False); - - LockDisplay(dpy); - GetReq(XF86DRIGetDeviceInfo, req); - req->reqType = info->codes->major_opcode; - req->driReqType = X_XF86DRIGetDeviceInfo; - req->screen = screen; - if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetDeviceInfo... return False"); - return False; - } - - *hFrameBuffer = rep.hFrameBufferLow; -#ifdef LONG64 - if (sizeof(drm_handle_t) == 8) { - *hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32; - } -#endif - - *fbOrigin = rep.framebufferOrigin; - *fbSize = rep.framebufferSize; - *fbStride = rep.framebufferStride; - *devPrivateSize = rep.devPrivateSize; - - if (rep.length) { - if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) { - _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3)); - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetDeviceInfo... return False"); - return False; - } - _XRead(dpy, (char *)*pDevPrivate, rep.devPrivateSize); - } else { - *pDevPrivate = NULL; - } - - UnlockDisplay(dpy); - SyncHandle(); - TRACE("GetDeviceInfo... return True"); - return True; -} diff --git a/src/gallium/winsys/drm/radeon/python/xf86dri.h b/src/gallium/winsys/drm/radeon/python/xf86dri.h deleted file mode 100644 index bf6de37d9dd..00000000000 --- a/src/gallium/winsys/drm/radeon/python/xf86dri.h +++ /dev/null @@ -1,123 +0,0 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -/** - * \file xf86dri.h - * Protocol numbers and function prototypes for DRI X protocol. - * - * \author Kevin E. Martin <[email protected]> - * \author Jens Owen <[email protected]> - * \author Rickard E. (Rik) Faith <[email protected]> - */ - -#ifndef _XF86DRI_H_ -#define _XF86DRI_H_ - -#include <stdint.h> -#include <X11/Xfuncproto.h> -#include <drm/drm.h> - -#define X_XF86DRIQueryVersion 0 -#define X_XF86DRIQueryDirectRenderingCapable 1 -#define X_XF86DRIOpenConnection 2 -#define X_XF86DRICloseConnection 3 -#define X_XF86DRIGetClientDriverName 4 -#define X_XF86DRICreateContext 5 -#define X_XF86DRIDestroyContext 6 -#define X_XF86DRICreateDrawable 7 -#define X_XF86DRIDestroyDrawable 8 -#define X_XF86DRIGetDrawableInfo 9 -#define X_XF86DRIGetDeviceInfo 10 -#define X_XF86DRIAuthConnection 11 -#define X_XF86DRIOpenFullScreen 12 /* Deprecated */ -#define X_XF86DRICloseFullScreen 13 /* Deprecated */ - -#define XF86DRINumberEvents 0 - -#define XF86DRIClientNotLocal 0 -#define XF86DRIOperationNotSupported 1 -#define XF86DRINumberErrors (XF86DRIOperationNotSupported + 1) - -#ifndef _XF86DRI_SERVER_ - -_XFUNCPROTOBEGIN - Bool uniDRIQueryExtension(Display * dpy, int *event_base, - int *error_base); - -Bool uniDRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion, - int *patchVersion); - -Bool uniDRIQueryDirectRenderingCapable(Display * dpy, int screen, - Bool * isCapable); - -Bool uniDRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA, - char **busIDString); - -Bool uniDRIAuthConnection(Display * dpy, int screen, drm_magic_t magic); - -Bool uniDRICloseConnection(Display * dpy, int screen); - -Bool uniDRIGetClientDriverName(Display * dpy, int screen, - int *ddxDriverMajorVersion, - int *ddxDriverMinorVersion, - int *ddxDriverPatchVersion, - char **clientDriverName); - -Bool uniDRICreateContext(Display * dpy, int screen, Visual * visual, - XID * ptr_to_returned_context_id, - drm_context_t * hHWContext); - -Bool uniDRICreateContextWithConfig(Display * dpy, int screen, int configID, - XID * ptr_to_returned_context_id, - drm_context_t * hHWContext); - -extern Bool uniDRIDestroyContext(Display * dpy, int screen, XID context_id); - -extern Bool uniDRICreateDrawable(Display * dpy, int screen, - Drawable drawable, - drm_drawable_t * hHWDrawable); - -extern Bool uniDRIDestroyDrawable(Display * dpy, int screen, - Drawable drawable); - -Bool uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable, - unsigned int *index, unsigned int *stamp, - int *X, int *Y, int *W, int *H, - int *numClipRects, drm_clip_rect_t ** pClipRects, - int *backX, int *backY, - int *numBackClipRects, - drm_clip_rect_t ** pBackClipRects); - -Bool uniDRIGetDeviceInfo(Display * dpy, int screen, - drm_handle_t * hFrameBuffer, int *fbOrigin, - int *fbSize, int *fbStride, int *devPrivateSize, - void **pDevPrivate); - -_XFUNCPROTOEND -#endif /* _XF86DRI_SERVER_ */ -#endif /* _XF86DRI_H_ */ diff --git a/src/gallium/winsys/drm/radeon/python/xf86dristr.h b/src/gallium/winsys/drm/radeon/python/xf86dristr.h deleted file mode 100644 index d8989963609..00000000000 --- a/src/gallium/winsys/drm/radeon/python/xf86dristr.h +++ /dev/null @@ -1,389 +0,0 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -/* - * Authors: - * Kevin E. Martin <[email protected]> - * Jens Owen <[email protected]> - * Rickard E. (Rik) Fiath <[email protected]> - * - */ - -#ifndef _XF86DRISTR_H_ -#define _XF86DRISTR_H_ - -#include "xf86dri.h" - -#define XF86DRINAME "XFree86-DRI" - -/* The DRI version number. This was originally set to be the same of the - * XFree86 version number. However, this version is really indepedent of - * the XFree86 version. - * - * Version History: - * 4.0.0: Original - * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02 - * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02 - */ -#define XF86DRI_MAJOR_VERSION 4 -#define XF86DRI_MINOR_VERSION 1 -#define XF86DRI_PATCH_VERSION 0 - -typedef struct _XF86DRIQueryVersion -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIQueryVersion */ - CARD16 length B16; -} xXF86DRIQueryVersionReq; - -#define sz_xXF86DRIQueryVersionReq 4 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD16 majorVersion B16; /* major version of DRI protocol */ - CARD16 minorVersion B16; /* minor version of DRI protocol */ - CARD32 patchVersion B32; /* patch version of DRI protocol */ - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; -} xXF86DRIQueryVersionReply; - -#define sz_xXF86DRIQueryVersionReply 32 - -typedef struct _XF86DRIQueryDirectRenderingCapable -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ - CARD16 length B16; - CARD32 screen B32; -} xXF86DRIQueryDirectRenderingCapableReq; - -#define sz_xXF86DRIQueryDirectRenderingCapableReq 8 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - BOOL isCapable; - BOOL pad2; - BOOL pad3; - BOOL pad4; - CARD32 pad5 B32; - CARD32 pad6 B32; - CARD32 pad7 B32; - CARD32 pad8 B32; - CARD32 pad9 B32; -} xXF86DRIQueryDirectRenderingCapableReply; - -#define sz_xXF86DRIQueryDirectRenderingCapableReply 32 - -typedef struct _XF86DRIOpenConnection -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIOpenConnection */ - CARD16 length B16; - CARD32 screen B32; -} xXF86DRIOpenConnectionReq; - -#define sz_xXF86DRIOpenConnectionReq 8 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 hSAREALow B32; - CARD32 hSAREAHigh B32; - CARD32 busIdStringLength B32; - CARD32 pad6 B32; - CARD32 pad7 B32; - CARD32 pad8 B32; -} xXF86DRIOpenConnectionReply; - -#define sz_xXF86DRIOpenConnectionReply 32 - -typedef struct _XF86DRIAuthConnection -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICloseConnection */ - CARD16 length B16; - CARD32 screen B32; - CARD32 magic B32; -} xXF86DRIAuthConnectionReq; - -#define sz_xXF86DRIAuthConnectionReq 12 - -typedef struct -{ - BYTE type; - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 authenticated B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; -} xXF86DRIAuthConnectionReply; - -#define zx_xXF86DRIAuthConnectionReply 32 - -typedef struct _XF86DRICloseConnection -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICloseConnection */ - CARD16 length B16; - CARD32 screen B32; -} xXF86DRICloseConnectionReq; - -#define sz_xXF86DRICloseConnectionReq 8 - -typedef struct _XF86DRIGetClientDriverName -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIGetClientDriverName */ - CARD16 length B16; - CARD32 screen B32; -} xXF86DRIGetClientDriverNameReq; - -#define sz_xXF86DRIGetClientDriverNameReq 8 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 ddxDriverMajorVersion B32; - CARD32 ddxDriverMinorVersion B32; - CARD32 ddxDriverPatchVersion B32; - CARD32 clientDriverNameLength B32; - CARD32 pad5 B32; - CARD32 pad6 B32; -} xXF86DRIGetClientDriverNameReply; - -#define sz_xXF86DRIGetClientDriverNameReply 32 - -typedef struct _XF86DRICreateContext -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICreateContext */ - CARD16 length B16; - CARD32 screen B32; - CARD32 visual B32; - CARD32 context B32; -} xXF86DRICreateContextReq; - -#define sz_xXF86DRICreateContextReq 16 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 hHWContext B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; -} xXF86DRICreateContextReply; - -#define sz_xXF86DRICreateContextReply 32 - -typedef struct _XF86DRIDestroyContext -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIDestroyContext */ - CARD16 length B16; - CARD32 screen B32; - CARD32 context B32; -} xXF86DRIDestroyContextReq; - -#define sz_xXF86DRIDestroyContextReq 12 - -typedef struct _XF86DRICreateDrawable -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICreateDrawable */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; -} xXF86DRICreateDrawableReq; - -#define sz_xXF86DRICreateDrawableReq 12 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 hHWDrawable B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; -} xXF86DRICreateDrawableReply; - -#define sz_xXF86DRICreateDrawableReply 32 - -typedef struct _XF86DRIDestroyDrawable -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIDestroyDrawable */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; -} xXF86DRIDestroyDrawableReq; - -#define sz_xXF86DRIDestroyDrawableReq 12 - -typedef struct _XF86DRIGetDrawableInfo -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIGetDrawableInfo */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; -} xXF86DRIGetDrawableInfoReq; - -#define sz_xXF86DRIGetDrawableInfoReq 12 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 drawableTableIndex B32; - CARD32 drawableTableStamp B32; - INT16 drawableX B16; - INT16 drawableY B16; - INT16 drawableWidth B16; - INT16 drawableHeight B16; - CARD32 numClipRects B32; - INT16 backX B16; - INT16 backY B16; - CARD32 numBackClipRects B32; -} xXF86DRIGetDrawableInfoReply; - -#define sz_xXF86DRIGetDrawableInfoReply 36 - -typedef struct _XF86DRIGetDeviceInfo -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIGetDeviceInfo */ - CARD16 length B16; - CARD32 screen B32; -} xXF86DRIGetDeviceInfoReq; - -#define sz_xXF86DRIGetDeviceInfoReq 8 - -typedef struct -{ - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 hFrameBufferLow B32; - CARD32 hFrameBufferHigh B32; - CARD32 framebufferOrigin B32; - CARD32 framebufferSize B32; - CARD32 framebufferStride B32; - CARD32 devPrivateSize B32; -} xXF86DRIGetDeviceInfoReply; - -#define sz_xXF86DRIGetDeviceInfoReply 32 - -typedef struct _XF86DRIOpenFullScreen -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIOpenFullScreen */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; -} xXF86DRIOpenFullScreenReq; - -#define sz_xXF86DRIOpenFullScreenReq 12 - -typedef struct -{ - BYTE type; - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 isFullScreen B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; -} xXF86DRIOpenFullScreenReply; - -#define sz_xXF86DRIOpenFullScreenReply 32 - -typedef struct _XF86DRICloseFullScreen -{ - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICloseFullScreen */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; -} xXF86DRICloseFullScreenReq; - -#define sz_xXF86DRICloseFullScreenReq 12 - -typedef struct -{ - BYTE type; - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; - CARD32 pad7 B32; -} xXF86DRICloseFullScreenReply; - -#define sz_xXF86DRICloseFullScreenReply 32 - -#endif /* _XF86DRISTR_H_ */ diff --git a/src/gallium/winsys/drm/sw/Makefile b/src/gallium/winsys/drm/sw/Makefile new file mode 100644 index 00000000000..5f3c3ec325d --- /dev/null +++ b/src/gallium/winsys/drm/sw/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = swdrm + +C_SOURCES = \ + wrapper_sw_winsys.c \ + sw_drm_api.c + +LIBRARY_INCLUDES = + +LIBRARY_DEFINES = + +include ../../../Makefile.template diff --git a/src/gallium/winsys/drm/sw/sw_drm_api.c b/src/gallium/winsys/drm/sw/sw_drm_api.c new file mode 100644 index 00000000000..0fd2163913e --- /dev/null +++ b/src/gallium/winsys/drm/sw/sw_drm_api.c @@ -0,0 +1,97 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "util/u_memory.h" +#include "softpipe/sp_public.h" +#include "state_tracker/drm_api.h" +#include "wrapper_sw_winsys.h" +#include "sw_drm_api.h" + + +/* + * Defines + */ + + +struct sw_drm_api +{ + struct drm_api base; + struct drm_api *api; + struct sw_winsys *sw; +}; + +static INLINE struct sw_drm_api * +sw_drm_api(struct drm_api *api) +{ + return (struct sw_drm_api *)api; +} + + +/* + * Exported functions + */ + + +static struct pipe_screen * +sw_drm_create_screen(struct drm_api *_api, int drmFD, + struct drm_create_screen_arg *arg) +{ + struct sw_drm_api *swapi = sw_drm_api(_api); + struct drm_api *api = swapi->api; + struct sw_winsys *sww; + struct pipe_screen *screen; + + screen = api->create_screen(api, drmFD, arg); + + sww = wrapper_sw_winsys_warp_pipe_screen(screen); + + return softpipe_create_screen(sww); +} + +static void +sw_drm_destroy(struct drm_api *api) +{ + struct sw_drm_api *swapi = sw_drm_api(api); + if (swapi->api->destroy) + swapi->api->destroy(swapi->api); + + FREE(swapi); +} + +struct drm_api * +sw_drm_api_create(struct drm_api *api) +{ + struct sw_drm_api *swapi = CALLOC_STRUCT(sw_drm_api); + + swapi->base.name = "sw"; + swapi->base.driver_name = api->driver_name; + swapi->base.create_screen = sw_drm_create_screen; + swapi->base.destroy = sw_drm_destroy; + + swapi->api = api; + + return &swapi->base; +} diff --git a/src/gallium/winsys/drm/sw/sw_drm_api.h b/src/gallium/winsys/drm/sw/sw_drm_api.h new file mode 100644 index 00000000000..ce90a04ae0c --- /dev/null +++ b/src/gallium/winsys/drm/sw/sw_drm_api.h @@ -0,0 +1,34 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 SW_DRM_API_H +#define SW_DRM_API_H + +struct drm_api; + +struct drm_api * sw_drm_api_create(struct drm_api *api); + +#endif diff --git a/src/gallium/winsys/drm/sw/wrapper_sw_winsys.c b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.c new file mode 100644 index 00000000000..459b1c1e2a3 --- /dev/null +++ b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.c @@ -0,0 +1,282 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "wrapper_sw_winsys.h" + +#include "pipe/p_format.h" +#include "pipe/p_state.h" + +#include "state_tracker/sw_winsys.h" + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +/* + * This code wraps a pipe_screen and exposes a sw_winsys interface for use + * with software resterizers. This code is used by the DRM based winsys to + * allow access to the drm driver. + * + * We must borrow the whole stack because only the pipe screen knows how + * to decode the content of a buffer. Or how to create a buffer that + * can still be used by drivers using real hardware (as the case is + * with software st/xorg but hw st/dri). + * + * We also need a pipe context for the transfers. + */ + +struct wrapper_sw_winsys +{ + struct sw_winsys base; + struct pipe_screen *screen; + struct pipe_context *pipe; +}; + +struct wrapper_sw_displaytarget +{ + struct wrapper_sw_winsys *winsys; + struct pipe_texture *tex; + struct pipe_transfer *transfer; + + unsigned width; + unsigned height; + unsigned map_count; + unsigned stride; /**< because we give stride at create */ + void *ptr; +}; + +static INLINE struct wrapper_sw_winsys * +wrapper_sw_winsys(struct sw_winsys *ws) +{ + return (struct wrapper_sw_winsys *)ws; +} + +static INLINE struct wrapper_sw_displaytarget * +wrapper_sw_displaytarget(struct sw_displaytarget *dt) +{ + return (struct wrapper_sw_displaytarget *)dt; +} + + +/* + * Functions + */ + + +static boolean +wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride) +{ + struct pipe_context *pipe = wdt->winsys->pipe; + struct pipe_texture *tex = wdt->tex; + struct pipe_transfer *tr; + + tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0, + PIPE_TRANSFER_READ_WRITE, + 0, 0, wdt->width, wdt->height); + if (!tr) + return FALSE; + + *stride = tr->stride; + wdt->stride = tr->stride; + + pipe->tex_transfer_destroy(pipe, tr); + + return TRUE; +} + +static struct sw_displaytarget * +wsw_dt_wrap_texture(struct wrapper_sw_winsys *wsw, + struct pipe_texture *tex, unsigned *stride) +{ + struct wrapper_sw_displaytarget *wdt = CALLOC_STRUCT(wrapper_sw_displaytarget); + if (!wdt) + goto err_unref; + + wdt->tex = tex; + wdt->winsys = wsw; + + if (!wsw_dt_get_stride(wdt, stride)) + goto err_free; + + return (struct sw_displaytarget *)wdt; + +err_free: + FREE(wdt); +err_unref: + pipe_texture_reference(&tex, NULL); + return NULL; +} + +static struct sw_displaytarget * +wsw_dt_create(struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); + struct pipe_texture templ; + struct pipe_texture *tex; + + /* + * XXX Why don't we just get the template. + */ + memset(&templ, 0, sizeof(templ)); + templ.width0 = width; + templ.height0 = height; + templ.format = format; + templ.tex_usage = tex_usage; + + /* XXX alignment: we can't do anything about this */ + + tex = wsw->screen->texture_create(wsw->screen, &templ); + if (!tex) + return NULL; + + return wsw_dt_wrap_texture(wsw, tex, stride); +} + +static struct sw_displaytarget * +wsw_dt_from_handle(struct sw_winsys *ws, + const struct pipe_texture *templ, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); + struct pipe_texture *tex; + + tex = wsw->screen->texture_from_handle(wsw->screen, templ, whandle); + if (!tex) + return NULL; + + return wsw_dt_wrap_texture(wsw, tex, stride); +} + +static void * +wsw_dt_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags) +{ + struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); + struct pipe_context *pipe = wdt->winsys->pipe; + struct pipe_texture *tex = wdt->tex; + struct pipe_transfer *tr; + void *ptr; + + if (!wdt->map_count) { + + assert(!wdt->transfer); + + tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0, + PIPE_TRANSFER_READ_WRITE, + 0, 0, wdt->width, wdt->height); + if (!tr) + return NULL; + + ptr = pipe->transfer_map(pipe, tr); + if (!ptr) + goto err; + + wdt->transfer = tr; + wdt->ptr = ptr; + + /* XXX Handle this case */ + assert(tr->stride == wdt->stride); + } + + wdt->map_count++; + + return wdt->ptr; + +err: + pipe->tex_transfer_destroy(pipe, tr); + return NULL; +} + +static void +wsw_dt_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); + struct pipe_context *pipe = wdt->winsys->pipe; + + assert(wdt->transfer); + + wdt->map_count--; + + if (wdt->map_count) + return; + + pipe->transfer_unmap(pipe, wdt->transfer); + pipe->tex_transfer_destroy(pipe, wdt->transfer); + wdt->transfer = NULL; +} + +static void +wsw_dt_destroy(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); + + pipe_texture_reference(&wdt->tex, NULL); + + FREE(wdt); +} + +static void +wsw_destroy(struct sw_winsys *ws) +{ + struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); + + wsw->pipe->destroy(wsw->pipe); + wsw->screen->destroy(wsw->screen); + + FREE(wsw); +} + +struct sw_winsys * +wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen) +{ + struct wrapper_sw_winsys *wsw = CALLOC_STRUCT(wrapper_sw_winsys); + + wsw->base.displaytarget_create = wsw_dt_create; + wsw->base.displaytarget_from_handle = wsw_dt_from_handle; + wsw->base.displaytarget_map = wsw_dt_map; + wsw->base.displaytarget_unmap = wsw_dt_unmap; + wsw->base.displaytarget_destroy = wsw_dt_destroy; + wsw->base.destroy = wsw_destroy; + + wsw->screen = screen; + wsw->pipe = screen->context_create(screen, NULL); + if (!wsw->pipe) + goto err; + + return &wsw->base; + +err: + FREE(wsw); + return NULL; +} diff --git a/src/gallium/winsys/drm/sw/wrapper_sw_winsys.h b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.h new file mode 100644 index 00000000000..b5c25a3c50f --- /dev/null +++ b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.h @@ -0,0 +1,35 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 WRAPPER_SW_WINSYS +#define WRAPPER_SW_WINSYS + +struct sw_winsys; +struct pipe_screen; + +struct sw_winsys *wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen); + +#endif diff --git a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c index a7c6e88b9eb..657544dcb21 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_screen_dri.c @@ -44,6 +44,16 @@ #include <stdio.h> +static struct svga_winsys_surface * +vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, + struct winsys_handle *whandle, + SVGA3dSurfaceFormat *format); +static boolean +vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, + struct svga_winsys_surface *surface, + unsigned stride, + struct winsys_handle *whandle); + static struct dri1_api dri1_api_hooks; static struct dri1_api_version ddx_required = { 0, 1, 0 }; static struct dri1_api_version ddx_compat = { 0, 0, 0 }; @@ -129,7 +139,12 @@ vmw_drm_create_screen(struct drm_api *drm_api, &drm_compat, "use old scanout field (not a error)")) use_old_scanout_flag = TRUE; dri1->api = &dri1_api_hooks; +#if 0 break; +#else + assert(!"No dri 1 support for now\n"); + return NULL; +#endif default: return NULL; } @@ -139,6 +154,10 @@ vmw_drm_create_screen(struct drm_api *drm_api, if (!vws) goto out_no_vws; + /* XXX do this properly */ + vws->base.surface_from_handle = vmw_drm_surface_from_handle; + vws->base.surface_get_handle = vmw_drm_surface_get_handle; + screen = svga_screen_create( &vws->base ); if (!screen) goto out_no_screen; @@ -200,6 +219,7 @@ vmw_dri1_present_locked(struct pipe_context *locked_pipe, const struct drm_clip_rect *bbox, struct pipe_fence_handle **p_fence) { +#if 0 struct svga_winsys_surface *srf = svga_screen_texture_get_winsys_surface(surf->texture); struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); @@ -246,21 +266,19 @@ vmw_dri1_present_locked(struct pipe_context *locked_pipe, *p_fence = (visible) ? vmw_pipe_fence(fence_seq) : NULL; vmw_svga_winsys_surface_reference(&vsrf, NULL); +#else + assert(!"No dri 1 support for now\n"); +#endif } -static struct pipe_texture * -vmw_drm_texture_from_handle(struct drm_api *drm_api, - struct pipe_screen *screen, - struct pipe_texture *templat, - const char *name, - unsigned stride, - unsigned handle) +static struct svga_winsys_surface * +vmw_drm_surface_from_handle(struct svga_winsys_screen *sws, + struct winsys_handle *whandle, + SVGA3dSurfaceFormat *format) { struct vmw_svga_winsys_surface *vsrf; struct svga_winsys_surface *ssrf; - struct vmw_winsys_screen *vws = - vmw_winsys_screen(svga_winsys_screen(screen)); - struct pipe_texture *tex; + struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); union drm_vmw_surface_reference_arg arg; struct drm_vmw_surface_arg *req = &arg.req; struct drm_vmw_surface_create_req *rep = &arg.rep; @@ -273,7 +291,7 @@ vmw_drm_texture_from_handle(struct drm_api *drm_api, */ memset(&arg, 0, sizeof(arg)); - req->sid = handle; + req->sid = whandle->handle; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE, &arg, sizeof(arg)); @@ -281,14 +299,14 @@ vmw_drm_texture_from_handle(struct drm_api *drm_api, if (ret) { fprintf(stderr, "Failed referencing shared surface. SID %d.\n" "Error %d (%s).\n", - handle, ret, strerror(-ret)); + whandle->handle, ret, strerror(-ret)); return NULL; } if (rep->mip_levels[0] != 1) { fprintf(stderr, "Incorrect number of mipmap levels on shared surface." " SID %d, levels %d\n", - handle, rep->mip_levels[0]); + whandle->handle, rep->mip_levels[0]); goto out_mip; } @@ -296,7 +314,7 @@ vmw_drm_texture_from_handle(struct drm_api *drm_api, if (rep->mip_levels[i] != 0) { fprintf(stderr, "Incorrect number of faces levels on shared surface." " SID %d, face %d present.\n", - handle, i); + whandle->handle, i); goto out_mip; } } @@ -308,38 +326,32 @@ vmw_drm_texture_from_handle(struct drm_api *drm_api, pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); vsrf->screen = vws; - vsrf->sid = handle; + vsrf->sid = whandle->handle; ssrf = svga_winsys_surface(vsrf); - tex = svga_screen_texture_wrap_surface(screen, templat, rep->format, ssrf); - if (!tex) - vmw_svga_winsys_surface_reference(&vsrf, NULL); + *format = rep->format; + + return ssrf; - return tex; - out_mip: - vmw_ioctl_surface_destroy(vws, handle); +out_mip: + vmw_ioctl_surface_destroy(vws, whandle->handle); return NULL; } static boolean -vmw_drm_handle_from_texture(struct drm_api *drm_api, - struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned *stride, - unsigned *handle) +vmw_drm_surface_get_handle(struct svga_winsys_screen *sws, + struct svga_winsys_surface *surface, + unsigned stride, + struct winsys_handle *whandle) { - struct svga_winsys_surface *surface = - svga_screen_texture_get_winsys_surface(texture); struct vmw_svga_winsys_surface *vsrf; if (!surface) return FALSE; vsrf = vmw_svga_winsys_surface(surface); - *handle = vsrf->sid; - *stride = util_format_get_nblocksx(texture->format, texture->width0) * - util_format_get_blocksize(texture->format); + whandle->handle = vsrf->sid; + whandle->stride = stride; - vmw_svga_winsys_surface_reference(&vsrf, NULL); return TRUE; } @@ -353,9 +365,6 @@ static struct drm_api vmw_drm_api_hooks = { .name = "vmwgfx", .driver_name = "vmwgfx", .create_screen = vmw_drm_create_screen, - .texture_from_shared_handle = vmw_drm_texture_from_handle, - .shared_handle_from_texture = vmw_drm_handle_from_texture, - .local_handle_from_texture = vmw_drm_handle_from_texture, }; struct drm_api* drm_api_create() diff --git a/src/gallium/winsys/gdi/SConscript b/src/gallium/winsys/gdi/SConscript index 4cbc86f3311..1267fc6eea4 100644 --- a/src/gallium/winsys/gdi/SConscript +++ b/src/gallium/winsys/gdi/SConscript @@ -1,5 +1,6 @@ ####################################################################### -# SConscript for gdi winsys +# SConscript for xlib winsys + Import('*') @@ -8,44 +9,15 @@ if env['platform'] == 'windows': env = env.Clone() env.Append(CPPPATH = [ - '#src/gallium/state_trackers/wgl', - ]) - - env.Append(LIBS = [ - 'gdi32', - 'user32', - 'kernel32', - 'ws2_32', + '#/src/gallium/include', + '#/src/gallium/auxiliary', + '#/src/gallium/drivers', ]) - sources = [] - drivers = [] - - if 'softpipe' in env['drivers']: - sources = ['gdi_softpipe_winsys.c'] - drivers = [softpipe] - - if 'llvmpipe' in env['drivers']: - env.Tool('llvm') - if 'LLVM_VERSION' in env: - sources = ['gdi_llvmpipe_winsys.c'] - drivers = [llvmpipe] - - if not sources or not drivers: - print 'warning: softpipe or llvmpipe not selected, gdi winsys disabled' - Return() - - if env['gcc']: - sources += ['#src/gallium/state_trackers/wgl/opengl32.mingw.def'] - else: - sources += ['#src/gallium/state_trackers/wgl/opengl32.def'] - - drivers += [trace] - - env['no_import_lib'] = 1 - - env.SharedLibrary( - target ='opengl32', - source = sources, - LIBS = wgl + glapi + mesa + drivers + gallium + glsl + env['LIBS'], + ws_gdi = env.ConvenienceLibrary( + target = 'ws_gdi', + source = [ + 'gdi_sw_winsys.c', + ] ) + Export('ws_gdi') diff --git a/src/gallium/winsys/gdi/gdi_softpipe_winsys.c b/src/gallium/winsys/gdi/gdi_softpipe_winsys.c deleted file mode 100644 index 71360e55aac..00000000000 --- a/src/gallium/winsys/gdi/gdi_softpipe_winsys.c +++ /dev/null @@ -1,318 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/** - * @file - * Softpipe support. - * - * @author Keith Whitwell - * @author Brian Paul - * @author Jose Fonseca - */ - - -#include <windows.h> - -#include "util/u_simple_screen.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "softpipe/sp_winsys.h" -#include "softpipe/sp_texture.h" -#include "stw_winsys.h" - - -struct gdi_softpipe_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; -}; - - -/** Cast wrapper */ -static INLINE struct gdi_softpipe_buffer * -gdi_softpipe_buffer( struct pipe_buffer *buf ) -{ - return (struct gdi_softpipe_buffer *)buf; -} - - -static void * -gdi_softpipe_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags) -{ - struct gdi_softpipe_buffer *gdi_softpipe_buf = gdi_softpipe_buffer(buf); - gdi_softpipe_buf->mapped = gdi_softpipe_buf->data; - return gdi_softpipe_buf->mapped; -} - - -static void -gdi_softpipe_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - struct gdi_softpipe_buffer *gdi_softpipe_buf = gdi_softpipe_buffer(buf); - gdi_softpipe_buf->mapped = NULL; -} - - -static void -gdi_softpipe_buffer_destroy(struct pipe_buffer *buf) -{ - struct gdi_softpipe_buffer *oldBuf = gdi_softpipe_buffer(buf); - - if (oldBuf->data) { - if (!oldBuf->userBuffer) - align_free(oldBuf->data); - - oldBuf->data = NULL; - } - - FREE(oldBuf); -} - - -static const char * -gdi_softpipe_get_name(struct pipe_winsys *winsys) -{ - return "softpipe"; -} - - -static struct pipe_buffer * -gdi_softpipe_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct gdi_softpipe_buffer *buffer = CALLOC_STRUCT(gdi_softpipe_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - buffer->data = align_malloc(size, alignment); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -gdi_softpipe_user_buffer_create(struct pipe_winsys *winsys, - void *ptr, - unsigned bytes) -{ - struct gdi_softpipe_buffer *buffer; - - buffer = CALLOC_STRUCT(gdi_softpipe_buffer); - if(!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -gdi_softpipe_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -gdi_softpipe_dummy_flush_frontbuffer(struct pipe_winsys *winsys, - struct pipe_surface *surface, - void *context_private) -{ - assert(0); -} - - -static void -gdi_softpipe_fence_reference(struct pipe_winsys *winsys, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -gdi_softpipe_fence_signalled(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -gdi_softpipe_fence_finish(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static void -gdi_softpipe_destroy(struct pipe_winsys *winsys) -{ - FREE(winsys); -} - - -static struct pipe_screen * -gdi_softpipe_screen_create(void) -{ - static struct pipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(pipe_winsys); - if(!winsys) - return NULL; - - winsys->destroy = gdi_softpipe_destroy; - - winsys->buffer_create = gdi_softpipe_buffer_create; - winsys->user_buffer_create = gdi_softpipe_user_buffer_create; - winsys->buffer_map = gdi_softpipe_buffer_map; - winsys->buffer_unmap = gdi_softpipe_buffer_unmap; - winsys->buffer_destroy = gdi_softpipe_buffer_destroy; - - winsys->surface_buffer_create = gdi_softpipe_surface_buffer_create; - - winsys->fence_reference = gdi_softpipe_fence_reference; - winsys->fence_signalled = gdi_softpipe_fence_signalled; - winsys->fence_finish = gdi_softpipe_fence_finish; - - winsys->flush_frontbuffer = gdi_softpipe_dummy_flush_frontbuffer; - winsys->get_name = gdi_softpipe_get_name; - - screen = softpipe_create_screen(winsys); - if(!screen) - gdi_softpipe_destroy(winsys); - - return screen; -} - - -static void -gdi_softpipe_present(struct pipe_screen *screen, - struct pipe_surface *surface, - HDC hDC) -{ - struct softpipe_texture *texture; - struct gdi_softpipe_buffer *buffer; - BITMAPINFO bmi; - - texture = softpipe_texture(surface->texture); - - buffer = gdi_softpipe_buffer(texture->buffer); - - memset(&bmi, 0, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = texture->stride[surface->level] / util_format_get_blocksize(surface->format); - bmi.bmiHeader.biHeight= -(long)surface->height; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = util_format_get_blocksizebits(surface->format); - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = 0; - bmi.bmiHeader.biXPelsPerMeter = 0; - bmi.bmiHeader.biYPelsPerMeter = 0; - bmi.bmiHeader.biClrUsed = 0; - bmi.bmiHeader.biClrImportant = 0; - - StretchDIBits(hDC, - 0, 0, surface->width, surface->height, - 0, 0, surface->width, surface->height, - buffer->data, &bmi, 0, SRCCOPY); -} - - -static const struct stw_winsys stw_winsys = { - &gdi_softpipe_screen_create, - &gdi_softpipe_present, - NULL, /* get_adapter_luid */ - NULL, /* shared_surface_open */ - NULL, /* shared_surface_close */ - NULL /* compose */ -}; - - -BOOL WINAPI -DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) -{ - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - stw_init(&stw_winsys); - stw_init_thread(); - break; - - case DLL_THREAD_ATTACH: - stw_init_thread(); - break; - - case DLL_THREAD_DETACH: - stw_cleanup_thread(); - break; - - case DLL_PROCESS_DETACH: - stw_cleanup_thread(); - stw_cleanup(); - break; - } - return TRUE; -} diff --git a/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c b/src/gallium/winsys/gdi/gdi_sw_winsys.c index a9fa03b8e57..4dba4b577b8 100644 --- a/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c +++ b/src/gallium/winsys/gdi/gdi_sw_winsys.c @@ -28,7 +28,7 @@ /** * @file - * LLVMpipe support. + * GDI software rasterizer support. * * @author Jose Fonseca <[email protected]> */ @@ -42,12 +42,11 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" -#include "llvmpipe/lp_winsys.h" -#include "llvmpipe/lp_texture.h" -#include "stw_winsys.h" +#include "state_tracker/sw_winsys.h" +#include "gdi_sw_winsys.h" -struct gdi_llvmpipe_displaytarget +struct gdi_sw_displaytarget { enum pipe_format format; unsigned width; @@ -63,15 +62,16 @@ struct gdi_llvmpipe_displaytarget /** Cast wrapper */ -static INLINE struct gdi_llvmpipe_displaytarget * -gdi_llvmpipe_displaytarget( struct llvmpipe_displaytarget *buf ) +static INLINE struct gdi_sw_displaytarget * +gdi_sw_displaytarget( struct sw_displaytarget *buf ) { - return (struct gdi_llvmpipe_displaytarget *)buf; + return (struct gdi_sw_displaytarget *)buf; } static boolean -gdi_llvmpipe_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, +gdi_sw_is_displaytarget_format_supported( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format ) { switch(format) { @@ -89,47 +89,48 @@ gdi_llvmpipe_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, static void * -gdi_llvmpipe_displaytarget_map(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, +gdi_sw_displaytarget_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, unsigned flags ) { - struct gdi_llvmpipe_displaytarget *gdt = gdi_llvmpipe_displaytarget(dt); + struct gdi_sw_displaytarget *gdt = gdi_sw_displaytarget(dt); return gdt->data; } static void -gdi_llvmpipe_displaytarget_unmap(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ) +gdi_sw_displaytarget_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt ) { } static void -gdi_llvmpipe_displaytarget_destroy(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt) +gdi_sw_displaytarget_destroy(struct sw_winsys *winsys, + struct sw_displaytarget *dt) { - struct gdi_llvmpipe_displaytarget *gdt = gdi_llvmpipe_displaytarget(dt); + struct gdi_sw_displaytarget *gdt = gdi_sw_displaytarget(dt); align_free(gdt->data); FREE(gdt); } -static struct llvmpipe_displaytarget * -gdi_llvmpipe_displaytarget_create(struct llvmpipe_winsys *winsys, +static struct sw_displaytarget * +gdi_sw_displaytarget_create(struct sw_winsys *winsys, + unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, unsigned *stride) { - struct gdi_llvmpipe_displaytarget *gdt; + struct gdi_sw_displaytarget *gdt; unsigned cpp; unsigned bpp; - gdt = CALLOC_STRUCT(gdi_llvmpipe_displaytarget); + gdt = CALLOC_STRUCT(gdi_sw_displaytarget); if(!gdt) goto no_gdt; @@ -160,7 +161,7 @@ gdi_llvmpipe_displaytarget_create(struct llvmpipe_winsys *winsys, gdt->bmi.bmiHeader.biClrImportant = 0; *stride = gdt->stride; - return (struct llvmpipe_displaytarget *)gdt; + return (struct sw_displaytarget *)gdt; no_data: FREE(gdt); @@ -169,65 +170,33 @@ no_gdt: } -static void -gdi_llvmpipe_displaytarget_display(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt, - void *context_private) +static struct sw_displaytarget * +gdi_sw_displaytarget_from_handle(struct sw_winsys *winsys, + const struct pipe_texture *templet, + struct winsys_handle *whandle, + unsigned *stride) { assert(0); + return NULL; } -static void -gdi_llvmpipe_destroy(struct llvmpipe_winsys *winsys) +static boolean +gdi_sw_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) { - FREE(winsys); + assert(0); + return FALSE; } -static struct pipe_screen * -gdi_llvmpipe_screen_create(void) +void +gdi_sw_display( struct sw_winsys *winsys, + struct sw_displaytarget *dt, + HDC hDC ) { - static struct llvmpipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(llvmpipe_winsys); - if(!winsys) - goto no_winsys; - - winsys->destroy = gdi_llvmpipe_destroy; - winsys->is_displaytarget_format_supported = gdi_llvmpipe_is_displaytarget_format_supported; - winsys->displaytarget_create = gdi_llvmpipe_displaytarget_create; - winsys->displaytarget_map = gdi_llvmpipe_displaytarget_map; - winsys->displaytarget_unmap = gdi_llvmpipe_displaytarget_unmap; - winsys->displaytarget_display = gdi_llvmpipe_displaytarget_display; - winsys->displaytarget_destroy = gdi_llvmpipe_displaytarget_destroy; - - screen = llvmpipe_create_screen(winsys); - if(!screen) - goto no_screen; - - return screen; - -no_screen: - FREE(winsys); -no_winsys: - return NULL; -} - - - - -static void -gdi_llvmpipe_present(struct pipe_screen *screen, - struct pipe_surface *surface, - HDC hDC) -{ - struct llvmpipe_texture *texture; - struct gdi_llvmpipe_displaytarget *gdt; - - texture = llvmpipe_texture(surface->texture); - gdt = gdi_llvmpipe_displaytarget(texture->dt); + struct gdi_sw_displaytarget *gdt = gdi_sw_displaytarget(dt); StretchDIBits(hDC, 0, 0, gdt->width, gdt->height, @@ -235,38 +204,44 @@ gdi_llvmpipe_present(struct pipe_screen *screen, gdt->data, &gdt->bmi, 0, SRCCOPY); } +static void +gdi_sw_displaytarget_display(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + void *context_private) +{ + /* nasty: + */ + HDC hDC = (HDC)context_private; -static const struct stw_winsys stw_winsys = { - &gdi_llvmpipe_screen_create, - &gdi_llvmpipe_present, - NULL, /* get_adapter_luid */ - NULL, /* shared_surface_open */ - NULL, /* shared_surface_close */ - NULL /* compose */ -}; + gdi_sw_display(winsys, dt, hDC); +} -BOOL WINAPI -DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) +static void +gdi_sw_destroy(struct sw_winsys *winsys) { - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - stw_init(&stw_winsys); - stw_init_thread(); - break; - - case DLL_THREAD_ATTACH: - stw_init_thread(); - break; - - case DLL_THREAD_DETACH: - stw_cleanup_thread(); - break; - - case DLL_PROCESS_DETACH: - stw_cleanup_thread(); - stw_cleanup(); - break; - } - return TRUE; + FREE(winsys); +} + +struct sw_winsys * +gdi_create_sw_winsys(void) +{ + static struct sw_winsys *winsys; + + winsys = CALLOC_STRUCT(sw_winsys); + if(!winsys) + return NULL; + + winsys->destroy = gdi_sw_destroy; + winsys->is_displaytarget_format_supported = gdi_sw_is_displaytarget_format_supported; + winsys->displaytarget_create = gdi_sw_displaytarget_create; + winsys->displaytarget_from_handle = gdi_sw_displaytarget_from_handle; + winsys->displaytarget_get_handle = gdi_sw_displaytarget_get_handle; + winsys->displaytarget_map = gdi_sw_displaytarget_map; + winsys->displaytarget_unmap = gdi_sw_displaytarget_unmap; + winsys->displaytarget_display = gdi_sw_displaytarget_display; + winsys->displaytarget_destroy = gdi_sw_displaytarget_destroy; + + return winsys; } + diff --git a/src/gallium/winsys/gdi/gdi_sw_winsys.h b/src/gallium/winsys/gdi/gdi_sw_winsys.h new file mode 100644 index 00000000000..4bbcb47848b --- /dev/null +++ b/src/gallium/winsys/gdi/gdi_sw_winsys.h @@ -0,0 +1,16 @@ +#ifndef GDI_SW_WINSYS_H +#define GDI_SW_WINSYS_H + +#include <windows.h> + +#include "pipe/p_compiler.h" +#include "state_tracker/sw_winsys.h" + +void gdi_sw_display( struct sw_winsys *winsys, + struct sw_displaytarget *dt, + HDC hDC ); + +struct sw_winsys * +gdi_create_sw_winsys(void); + +#endif diff --git a/src/gallium/winsys/null/Makefile b/src/gallium/winsys/null/Makefile new file mode 100644 index 00000000000..3a3fb75ab36 --- /dev/null +++ b/src/gallium/winsys/null/Makefile @@ -0,0 +1,16 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = ws_null + +LIBRARY_INCLUDES = \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary + +C_SOURCES = \ + null_sw_winsys.c + +include ../../Makefile.template + + diff --git a/src/gallium/winsys/null/SConscript b/src/gallium/winsys/null/SConscript new file mode 100644 index 00000000000..21837dc60c2 --- /dev/null +++ b/src/gallium/winsys/null/SConscript @@ -0,0 +1,21 @@ +####################################################################### +# SConscript for xlib winsys + + +Import('*') + +env = env.Clone() + +env.Append(CPPPATH = [ + '#/src/gallium/include', + '#/src/gallium/auxiliary', + '#/src/gallium/drivers', +]) + +ws_null = env.ConvenienceLibrary( + target = 'ws_null', + source = [ + 'null_sw_winsys.c', + ] +) +Export('ws_null') diff --git a/src/gallium/winsys/null/null_sw_winsys.c b/src/gallium/winsys/null/null_sw_winsys.c new file mode 100644 index 00000000000..5027e57b303 --- /dev/null +++ b/src/gallium/winsys/null/null_sw_winsys.c @@ -0,0 +1,148 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/** + * @file + * Null software rasterizer winsys. + * + * There is no present support. Framebuffer data needs to be obtained via + * transfers. + * + * @author Jose Fonseca + */ + + +#include "pipe/p_format.h" +#include "util/u_memory.h" +#include "state_tracker/sw_winsys.h" +#include "null_sw_winsys.h" + + +static boolean +null_sw_is_displaytarget_format_supported(struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format ) +{ + return FALSE; +} + + +static void * +null_sw_displaytarget_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags ) +{ + assert(0); + return NULL; +} + + +static void +null_sw_displaytarget_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt ) +{ + assert(0); +} + + +static void +null_sw_displaytarget_destroy(struct sw_winsys *winsys, + struct sw_displaytarget *dt) +{ + assert(0); +} + + +static struct sw_displaytarget * +null_sw_displaytarget_create(struct sw_winsys *winsys, + unsigned tex_usage, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + return NULL; +} + + +static struct sw_displaytarget * +null_sw_displaytarget_from_handle(struct sw_winsys *winsys, + const struct pipe_texture *templet, + struct winsys_handle *whandle, + unsigned *stride) +{ + return NULL; +} + + +static boolean +null_sw_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + assert(0); + return FALSE; +} + + +static void +null_sw_displaytarget_display(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + void *context_private) +{ + assert(0); +} + + +static void +null_sw_destroy(struct sw_winsys *winsys) +{ + FREE(winsys); +} + + +struct sw_winsys * +null_sw_create(void) +{ + static struct sw_winsys *winsys; + + winsys = CALLOC_STRUCT(sw_winsys); + if (!winsys) + return NULL; + + winsys->destroy = null_sw_destroy; + winsys->is_displaytarget_format_supported = null_sw_is_displaytarget_format_supported; + winsys->displaytarget_create = null_sw_displaytarget_create; + winsys->displaytarget_from_handle = null_sw_displaytarget_from_handle; + winsys->displaytarget_get_handle = null_sw_displaytarget_get_handle; + winsys->displaytarget_map = null_sw_displaytarget_map; + winsys->displaytarget_unmap = null_sw_displaytarget_unmap; + winsys->displaytarget_display = null_sw_displaytarget_display; + winsys->displaytarget_destroy = null_sw_displaytarget_destroy; + + return winsys; +} diff --git a/src/gallium/winsys/null/null_sw_winsys.h b/src/gallium/winsys/null/null_sw_winsys.h new file mode 100644 index 00000000000..1986186febe --- /dev/null +++ b/src/gallium/winsys/null/null_sw_winsys.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#ifndef NULL_SW_WINSYS_H_ +#define NULL_SW_WINSYS_H_ + + +struct sw_winsys; + + +struct sw_winsys * +null_sw_create(void); + + +#endif /* NULL_SW_WINSYS_H_ */ diff --git a/src/gallium/winsys/xlib/Makefile b/src/gallium/winsys/xlib/Makefile index 824c666ae30..18357a41127 100644 --- a/src/gallium/winsys/xlib/Makefile +++ b/src/gallium/winsys/xlib/Makefile @@ -1,100 +1,17 @@ -# src/gallium/winsys/xlib/Makefile - -# This makefile produces a "stand-alone" libGL.so which is based on -# Xlib (no DRI HW acceleration) - - TOP = ../../../.. include $(TOP)/configs/current +LIBNAME = ws_xlib -GL_MAJOR = 1 -GL_MINOR = 5 -GL_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY) - - -INCLUDE_DIRS = \ - -I$(TOP)/include \ - -I$(TOP)/src/mesa \ - -I$(TOP)/src/mesa/main \ +LIBRARY_INCLUDES = \ -I$(TOP)/src/gallium/include \ -I$(TOP)/src/gallium/drivers \ - -I$(TOP)/src/gallium/state_trackers/glx/xlib \ - -I$(TOP)/src/gallium/auxiliary - -DEFINES += \ - -DGALLIUM_SOFTPIPE -#-DGALLIUM_CELL will be defined by the config */ - -XLIB_WINSYS_SOURCES = \ - xlib.c \ - xlib_cell.c \ - xlib_llvmpipe.c \ - xlib_softpipe.c - - -XLIB_WINSYS_OBJECTS = $(XLIB_WINSYS_SOURCES:.c=.o) - - -# Note: CELL_SPU_LIB is only defined for cell configs - -LIBS = \ - $(GALLIUM_DRIVERS) \ - $(TOP)/src/gallium/state_trackers/glx/xlib/libxlib.a \ - $(TOP)/src/mesa/libglapi.a \ - $(TOP)/src/mesa/libmesagallium.a \ - $(GALLIUM_AUXILIARIES) \ - $(CELL_SPU_LIB) \ - - -.SUFFIXES : .cpp - -.c.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ - -.cpp.o: - $(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@ - - - -default: $(TOP)/$(LIB_DIR)/gallium $(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME) - -$(TOP)/$(LIB_DIR)/gallium: - @ mkdir -p $(TOP)/$(LIB_DIR)/gallium - -# Make the libGL.so library -$(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME): $(XLIB_WINSYS_OBJECTS) $(LIBS) Makefile - $(TOP)/bin/mklib -o $(GL_LIB) \ - -linker "$(CC)" \ - -major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \ - -install $(TOP)/$(LIB_DIR)/gallium \ - $(MKLIB_OPTIONS) $(XLIB_WINSYS_OBJECTS) \ - -Wl,--start-group $(LIBS) -Wl,--end-group $(GL_LIB_DEPS) - - -depend: $(XLIB_WINSYS_SOURCES) - @ echo "running $(MKDEP)" - @ rm -f depend # workaround oops on gutsy?!? - @ touch depend - $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(XLIB_WINSYS_SOURCES) \ - > /dev/null 2>/dev/null - - -install: default - $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/include/GL - $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR) - $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(DESTDIR)$(INSTALL_DIR)/include/GL - @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \ - $(MINSTALL) $(TOP)/$(LIB_DIR)/libGL* $(DESTDIR)$(INSTALL_DIR)/$(LIB_DIR); \ - fi - + -I$(TOP)/src/gallium/auxiliary \ + $(X_CFLAGS) -# Emacs tags -tags: - etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h +C_SOURCES = \ + xlib_sw_winsys.c -clean: - -rm -f *.o +include ../../Makefile.template -include depend diff --git a/src/gallium/winsys/xlib/SConscript b/src/gallium/winsys/xlib/SConscript index 8c9d318af2b..2af6153b4c7 100644 --- a/src/gallium/winsys/xlib/SConscript +++ b/src/gallium/winsys/xlib/SConscript @@ -1,64 +1,23 @@ ####################################################################### # SConscript for xlib winsys -Import('*') - -if env['platform'] != 'linux': - Return() - -if 'mesa' not in env['statetrackers']: - print 'warning: Mesa state tracker disabled: skipping build of xlib libGL.so' - Return() - -if env['dri']: - print 'warning: DRI enabled: skipping build of xlib libGL.so' - Return() - -if not set(('softpipe', 'llvmpipe', 'cell')).intersection(env['drivers']): - print 'warning: no supported pipe driver: skipping build of xlib libGL.so' - Return() -env = env.Clone() - -env.Append(CPPPATH = [ - '#/src/mesa', - '#/src/mesa/main', - '#src/gallium/state_trackers/glx/xlib', -]) - -env.Append(CPPDEFINES = ['USE_XSHM']) - -sources = [ - 'xlib.c', -] +Import('*') -drivers = [trace] - -if 'softpipe' in env['drivers']: - env.Append(CPPDEFINES = 'GALLIUM_SOFTPIPE') - sources += ['xlib_softpipe.c'] - drivers += [softpipe] +if env['platform'] == 'linux': -if 'llvmpipe' in env['drivers']: - env.Tool('llvm') - if 'LLVM_VERSION' in env: - env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE') - env.Tool('udis86') - sources += ['xlib_llvmpipe.c'] - drivers += [llvmpipe] - -if 'cell' in env['drivers']: - env.Append(CPPDEFINES = 'GALLIUM_CELL') - sources += ['xlib_cell.c'] - drivers += [cell] + env = env.Clone() -# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions -libgl = env.SharedLibrary( - target ='GL', - source = sources, - LIBS = st_xlib + glapi + mesa + glsl + drivers + gallium + env['LIBS'], -) + env.Append(CPPPATH = [ + '#/src/gallium/include', + '#/src/gallium/auxiliary', + '#/src/gallium/drivers', + ]) -if not env['dri']: - # Only install this libGL.so if DRI not enabled - env.InstallSharedLibrary(libgl, version=(1, 5)) + ws_xlib = env.ConvenienceLibrary( + target = 'ws_xlib', + source = [ + 'xlib_sw_winsys.c', + ] + ) + Export('ws_xlib') diff --git a/src/gallium/winsys/xlib/xlib.h b/src/gallium/winsys/xlib/xlib.h deleted file mode 100644 index 8e091d0c084..00000000000 --- a/src/gallium/winsys/xlib/xlib.h +++ /dev/null @@ -1,13 +0,0 @@ - -#ifndef XLIB_H -#define XLIB_H - -#include "pipe/p_compiler.h" -#include "xm_winsys.h" - -extern struct xm_driver xlib_softpipe_driver; -extern struct xm_driver xlib_llvmpipe_driver; -extern struct xm_driver xlib_cell_driver; - - -#endif diff --git a/src/gallium/winsys/xlib/xlib_brw_context.c b/src/gallium/winsys/xlib/xlib_brw_context.c deleted file mode 100644 index 22bf41a46f7..00000000000 --- a/src/gallium/winsys/xlib/xlib_brw_context.c +++ /dev/null @@ -1,209 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/* - * Authors: - * Keith Whitwell - * Brian Paul - */ - - -/* #include "glxheader.h" */ -/* #include "xmesaP.h" */ - -#include "util/u_simple_screen.h" -#include "util/u_inlines.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "i965simple/brw_winsys.h" -#include "xlib_brw_aub.h" -#include "xlib_brw.h" - - - - -#define XBCWS_BATCHBUFFER_SIZE 1024 - - -/* The backend to the brw driver (ie struct brw_winsys) is actually a - * per-context entity. - */ -struct xlib_brw_context_winsys { - struct brw_winsys brw_context_winsys; /**< batch buffer funcs */ - struct aub_context *aub; - - struct pipe_winsys *pipe_winsys; - - unsigned batch_data[XBCWS_BATCHBUFFER_SIZE]; - unsigned batch_nr; - unsigned batch_size; - unsigned batch_alloc; -}; - - -/* Turn a brw_winsys into an xlib_brw_context_winsys: - */ -static inline struct xlib_brw_context_winsys * -xlib_brw_context_winsys( struct brw_winsys *sws ) -{ - return (struct xlib_brw_context_winsys *)sws; -} - - -/* Simple batchbuffer interface: - */ - -static unsigned *xbcws_batch_start( struct brw_winsys *sws, - unsigned dwords, - unsigned relocs ) -{ - struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws); - - if (xbcws->batch_size < xbcws->batch_nr + dwords) - return NULL; - - xbcws->batch_alloc = xbcws->batch_nr + dwords; - return (void *)1; /* not a valid pointer! */ -} - -static void xbcws_batch_dword( struct brw_winsys *sws, - unsigned dword ) -{ - struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws); - - assert(xbcws->batch_nr < xbcws->batch_alloc); - xbcws->batch_data[xbcws->batch_nr++] = dword; -} - -static void xbcws_batch_reloc( struct brw_winsys *sws, - struct pipe_buffer *buf, - unsigned access_flags, - unsigned delta ) -{ - struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws); - - assert(xbcws->batch_nr < xbcws->batch_alloc); - xbcws->batch_data[xbcws->batch_nr++] = - ( xlib_brw_get_buffer_offset( NULL, buf, access_flags ) + - delta ); -} - -static void xbcws_batch_end( struct brw_winsys *sws ) -{ - struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws); - - assert(xbcws->batch_nr <= xbcws->batch_alloc); - xbcws->batch_alloc = 0; -} - -static void xbcws_batch_flush( struct brw_winsys *sws, - struct pipe_fence_handle **fence ) -{ - struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws); - assert(xbcws->batch_nr <= xbcws->batch_size); - - if (xbcws->batch_nr) { - xlib_brw_commands_aub( xbcws->pipe_winsys, - xbcws->batch_data, - xbcws->batch_nr ); - } - - xbcws->batch_nr = 0; -} - - - -/* Really a per-device function, just pass through: - */ -static unsigned xbcws_get_buffer_offset( struct brw_winsys *sws, - struct pipe_buffer *buf, - unsigned access_flags ) -{ - struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws); - - return xlib_brw_get_buffer_offset( xbcws->pipe_winsys, - buf, - access_flags ); -} - - -/* Really a per-device function, just pass through: - */ -static void xbcws_buffer_subdata_typed( struct brw_winsys *sws, - struct pipe_buffer *buf, - unsigned long offset, - unsigned long size, - const void *data, - unsigned data_type ) -{ - struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws); - - xlib_brw_buffer_subdata_typed( xbcws->pipe_winsys, - buf, - offset, - size, - data, - data_type ); -} - - -/** - * Create i965 hardware rendering context, but plugged into a - * dump-to-aubfile backend. - */ -struct pipe_context * -xlib_create_brw_context( struct pipe_screen *screen, - void *unused ) -{ - struct xlib_brw_context_winsys *xbcws = CALLOC_STRUCT( xlib_brw_context_winsys ); - - /* Fill in this struct with callbacks that i965simple will need to - * communicate with the window system, buffer manager, etc. - */ - xbcws->brw_context_winsys.batch_start = xbcws_batch_start; - xbcws->brw_context_winsys.batch_dword = xbcws_batch_dword; - xbcws->brw_context_winsys.batch_reloc = xbcws_batch_reloc; - xbcws->brw_context_winsys.batch_end = xbcws_batch_end; - xbcws->brw_context_winsys.batch_flush = xbcws_batch_flush; - xbcws->brw_context_winsys.buffer_subdata_typed = xbcws_buffer_subdata_typed; - xbcws->brw_context_winsys.get_buffer_offset = xbcws_get_buffer_offset; - - xbcws->pipe_winsys = screen->winsys; /* redundant */ - - xbcws->batch_size = XBCWS_BATCHBUFFER_SIZE; - - /* Create the i965simple context: - */ -#ifdef GALLIUM_CELL - return NULL; -#else - return brw_create( screen, - &xbcws->brw_context_winsys, - 0 ); -#endif -} diff --git a/src/gallium/winsys/xlib/xlib_cell.c b/src/gallium/winsys/xlib/xlib_cell.c deleted file mode 100644 index 1dc9e8fa11f..00000000000 --- a/src/gallium/winsys/xlib/xlib_cell.c +++ /dev/null @@ -1,401 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/* - * Authors: - * Keith Whitwell - * Brian Paul - */ - -#include "xlib.h" - -#ifdef GALLIUM_CELL - -#include "xm_api.h" - -#undef ASSERT -#undef Elements - -#include "util/u_simple_screen.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "cell/ppu/cell_context.h" -#include "cell/ppu/cell_screen.h" -#include "cell/ppu/cell_winsys.h" -#include "cell/ppu/cell_texture.h" - - -/** - * Subclass of pipe_buffer for Xlib winsys. - * Low-level OS/window system memory buffer - */ -struct xm_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; - - XImage *tempImage; - int shm; -}; - - -/** - * Subclass of pipe_winsys for Xlib winsys - */ -struct xmesa_pipe_winsys -{ - struct pipe_winsys base; -}; - - - -/** Cast wrapper */ -static INLINE struct xm_buffer * -xm_buffer( struct pipe_buffer *buf ) -{ - return (struct xm_buffer *)buf; -} - - -/* Most callbacks map direcly onto dri_bufmgr operations: - */ -static void * -xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, - unsigned flags) -{ - struct xm_buffer *xm_buf = xm_buffer(buf); - xm_buf->mapped = xm_buf->data; - return xm_buf->mapped; -} - -static void -xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct xm_buffer *xm_buf = xm_buffer(buf); - xm_buf->mapped = NULL; -} - -static void -xm_buffer_destroy(/*struct pipe_winsys *pws,*/ - struct pipe_buffer *buf) -{ - struct xm_buffer *oldBuf = xm_buffer(buf); - - if (oldBuf) { - if (oldBuf->data) { - if (!oldBuf->userBuffer) { - align_free(oldBuf->data); - } - - oldBuf->data = NULL; - } - free(oldBuf); - } -} - - -/** - * For Cell. Basically, rearrange the pixels/quads from this layout: - * +--+--+--+--+ - * |p0|p1|p2|p3|.... - * +--+--+--+--+ - * - * to this layout: - * +--+--+ - * |p0|p1|.... - * +--+--+ - * |p2|p3| - * +--+--+ - */ -static void -twiddle_tile(const uint *tileIn, uint *tileOut) -{ - int y, x; - - for (y = 0; y < TILE_SIZE; y+=2) { - for (x = 0; x < TILE_SIZE; x+=2) { - int k = 4 * (y/2 * TILE_SIZE/2 + x/2); - tileOut[y * TILE_SIZE + (x + 0)] = tileIn[k]; - tileOut[y * TILE_SIZE + (x + 1)] = tileIn[k+1]; - tileOut[(y + 1) * TILE_SIZE + (x + 0)] = tileIn[k+2]; - tileOut[(y + 1) * TILE_SIZE + (x + 1)] = tileIn[k+3]; - } - } -} - - - -/** - * Display a surface that's in a tiled configuration. That is, all the - * pixels for a TILE_SIZExTILE_SIZE block are contiguous in memory. - */ -static void -xlib_cell_display_surface(struct xmesa_buffer *b, struct pipe_surface *surf) -{ - XImage *ximage; - struct xm_buffer *xm_buf = xm_buffer( - cell_texture(surf->texture)->buffer); - const uint tilesPerRow = (surf->width + TILE_SIZE - 1) / TILE_SIZE; - uint x, y; - - ximage = b->tempImage; - - /* check that the XImage has been previously initialized */ - assert(ximage->format); - assert(ximage->bitmap_unit); - - /* update XImage's fields */ - ximage->width = TILE_SIZE; - ximage->height = TILE_SIZE; - ximage->bytes_per_line = TILE_SIZE * 4; - - for (y = 0; y < surf->height; y += TILE_SIZE) { - for (x = 0; x < surf->width; x += TILE_SIZE) { - uint tmpTile[TILE_SIZE * TILE_SIZE]; - int tx = x / TILE_SIZE; - int ty = y / TILE_SIZE; - int offset = ty * tilesPerRow + tx; - int w = TILE_SIZE; - int h = TILE_SIZE; - - if (y + h > surf->height) - h = surf->height - y; - if (x + w > surf->width) - w = surf->width - x; - - /* offset in pixels */ - offset *= TILE_SIZE * TILE_SIZE; - - /* twiddle from ximage buffer to temp tile */ - twiddle_tile((uint *) xm_buf->data + offset, tmpTile); - /* display temp tile data */ - ximage->data = (char *) tmpTile; - XPutImage(b->xm_visual->display, b->drawable, b->gc, - ximage, 0, 0, x, y, w, h); - } - } -} - - - - - -static void -xm_flush_frontbuffer(struct pipe_winsys *pws, - struct pipe_surface *surf, - void *context_private) -{ - /* - * The front color buffer is actually just another XImage buffer. - * This function copies that XImage to the actual X Window. - */ - XMesaContext xmctx = (XMesaContext) context_private; - if (xmctx) - xlib_cell_display_surface(xmctx->xm_buffer, surf); -} - - - -static const char * -xm_get_name(struct pipe_winsys *pws) -{ - return "Xlib/Cell"; -} - - -static struct pipe_buffer * -xm_buffer_create(struct pipe_winsys *pws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - - if (buffer->data == NULL) { - buffer->shm = 0; - - /* align to 16-byte multiple for Cell */ - buffer->data = align_malloc(size, max(alignment, 16)); - } - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - buffer->shm = 0; - - return &buffer->base; -} - - - -static struct pipe_buffer * -xm_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - /* XXX a bit of a hack */ - *stride * align(nblocksy, TILE_SIZE)); -} - - -/* - * Fence functions - basically nothing to do, as we don't create any actual - * fence objects. - */ - -static void -xm_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -xm_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -xm_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - - -static struct pipe_winsys * -xlib_create_cell_winsys( void ) -{ - static struct xmesa_pipe_winsys *ws = NULL; - - if (!ws) { - ws = CALLOC_STRUCT(xmesa_pipe_winsys); - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - */ - ws->base.buffer_create = xm_buffer_create; - ws->base.user_buffer_create = xm_user_buffer_create; - ws->base.buffer_map = xm_buffer_map; - ws->base.buffer_unmap = xm_buffer_unmap; - ws->base.buffer_destroy = xm_buffer_destroy; - - ws->base.surface_buffer_create = xm_surface_buffer_create; - - ws->base.fence_reference = xm_fence_reference; - ws->base.fence_signalled = xm_fence_signalled; - ws->base.fence_finish = xm_fence_finish; - - ws->base.flush_frontbuffer = xm_flush_frontbuffer; - ws->base.get_name = xm_get_name; - } - - return &ws->base; -} - - -static struct pipe_screen * -xlib_create_cell_screen( void ) -{ - struct pipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = xlib_create_cell_winsys(); - if (winsys == NULL) - return NULL; - - screen = cell_create_screen(winsys); - if (screen == NULL) - goto fail; - - return screen; - -fail: - if (winsys) - winsys->destroy( winsys ); - - return NULL; -} - - - -struct xm_driver xlib_cell_driver = -{ - .create_pipe_screen = xlib_create_cell_screen, - .display_surface = xlib_cell_display_surface, -}; - -#else - -struct xm_driver xlib_cell_driver = -{ - .create_pipe_screen = NULL, - .display_surface = NULL, -}; - -#endif diff --git a/src/gallium/winsys/xlib/xlib_softpipe.c b/src/gallium/winsys/xlib/xlib_softpipe.c deleted file mode 100644 index 716338aef47..00000000000 --- a/src/gallium/winsys/xlib/xlib_softpipe.c +++ /dev/null @@ -1,508 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/* - * Authors: - * Keith Whitwell - * Brian Paul - */ - - -#include "xm_api.h" - -#undef ASSERT -#undef Elements - -#include "util/u_simple_screen.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "softpipe/sp_winsys.h" -#include "softpipe/sp_texture.h" - -#include "xlib.h" - -/** - * Subclass of pipe_buffer for Xlib winsys. - * Low-level OS/window system memory buffer - */ -struct xm_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; - - XImage *tempImage; -#ifdef USE_XSHM - boolean shm; /** Is this a shared memory buffer? */ - XShmSegmentInfo shminfo; -#endif -}; - - -/** - * Subclass of pipe_winsys for Xlib winsys - */ -struct xmesa_pipe_winsys -{ - struct pipe_winsys base; -/* struct xmesa_visual *xm_visual; */ -}; - - - -/** Cast wrapper */ -static INLINE struct xm_buffer * -xm_buffer( struct pipe_buffer *buf ) -{ - return (struct xm_buffer *)buf; -} - - -/** - * X Shared Memory Image extension code - */ - -#ifdef USE_XSHM - -static volatile int mesaXErrorFlag = 0; - -/** - * Catches potential Xlib errors. - */ -static int -mesaHandleXError(Display *dpy, XErrorEvent *event) -{ - (void) dpy; - (void) event; - mesaXErrorFlag = 1; - return 0; -} - - -static char *alloc_shm(struct xm_buffer *buf, unsigned size) -{ - XShmSegmentInfo *const shminfo = & buf->shminfo; - - shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777); - if (shminfo->shmid < 0) { - return NULL; - } - - shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); - if (shminfo->shmaddr == (char *) -1) { - shmctl(shminfo->shmid, IPC_RMID, 0); - return NULL; - } - - shminfo->readOnly = False; - return shminfo->shmaddr; -} - - -/** - * Allocate a shared memory XImage back buffer for the given XMesaBuffer. - */ -static void -alloc_shm_ximage(struct xm_buffer *b, struct xmesa_buffer *xmb, - unsigned width, unsigned height) -{ - /* - * We have to do a _lot_ of error checking here to be sure we can - * really use the XSHM extension. It seems different servers trigger - * errors at different points if the extension won't work. Therefore - * we have to be very careful... - */ - int (*old_handler)(Display *, XErrorEvent *); - - b->tempImage = XShmCreateImage(xmb->xm_visual->display, - xmb->xm_visual->visinfo->visual, - xmb->xm_visual->visinfo->depth, - ZPixmap, - NULL, - &b->shminfo, - width, height); - if (b->tempImage == NULL) { - b->shm = FALSE; - return; - } - - - mesaXErrorFlag = 0; - old_handler = XSetErrorHandler(mesaHandleXError); - /* This may trigger the X protocol error we're ready to catch: */ - XShmAttach(xmb->xm_visual->display, &b->shminfo); - XSync(xmb->xm_visual->display, False); - - if (mesaXErrorFlag) { - /* we are on a remote display, this error is normal, don't print it */ - XFlush(xmb->xm_visual->display); - mesaXErrorFlag = 0; - XDestroyImage(b->tempImage); - b->tempImage = NULL; - b->shm = FALSE; - (void) XSetErrorHandler(old_handler); - return; - } - - b->shm = TRUE; -} - -#endif /* USE_XSHM */ - - - -/* Most callbacks map direcly onto dri_bufmgr operations: - */ -static void * -xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, - unsigned flags) -{ - struct xm_buffer *xm_buf = xm_buffer(buf); - xm_buf->mapped = xm_buf->data; - return xm_buf->mapped; -} - -static void -xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct xm_buffer *xm_buf = xm_buffer(buf); - xm_buf->mapped = NULL; -} - -static void -xm_buffer_destroy(struct pipe_buffer *buf) -{ - struct xm_buffer *oldBuf = xm_buffer(buf); - - /* - * Note oldBuf->data may point to one of three things: - * 1. XShm shared memory image data - * 2. User-provided (wrapped) memory, see xm_user_buffer_create() - * 3. Regular, malloc'd memory - * We need to be careful with freeing that data now. - */ - - if (oldBuf->data) { -#ifdef USE_XSHM - if (oldBuf->shminfo.shmid >= 0) { - shmdt(oldBuf->shminfo.shmaddr); - shmctl(oldBuf->shminfo.shmid, IPC_RMID, 0); - - oldBuf->shminfo.shmid = -1; - oldBuf->shminfo.shmaddr = (char *) -1; - } - - if (oldBuf->shm) { - oldBuf->data = NULL; - } - - if (oldBuf->tempImage) { - XDestroyImage(oldBuf->tempImage); - oldBuf->tempImage = NULL; - } -#endif - - if (oldBuf->data && !oldBuf->userBuffer) { - /* this was regular malloc'd memory */ - align_free(oldBuf->data); - } - - oldBuf->data = NULL; - } - - free(oldBuf); -} - - -/** - * Display/copy the image in the surface into the X window specified - * by the XMesaBuffer. - */ -static void -xlib_softpipe_display_surface(struct xmesa_buffer *b, - struct pipe_surface *surf) -{ - XImage *ximage; - struct softpipe_texture *spt = softpipe_texture(surf->texture); - struct xm_buffer *xm_buf = xm_buffer(spt->buffer); - static boolean no_swap = 0; - static boolean firsttime = 1; - - if (firsttime) { - no_swap = getenv("SP_NO_RAST") != NULL; - firsttime = 0; - } - - if (no_swap) - return; - -#ifdef USE_XSHM - if (xm_buf->shm) - { - if (xm_buf->tempImage == NULL) - { - assert(util_format_get_blockwidth(surf->texture->format) == 1); - assert(util_format_get_blockheight(surf->texture->format) == 1); - alloc_shm_ximage(xm_buf, b, spt->stride[surf->level] / - util_format_get_blocksize(surf->texture->format), surf->height); - } - - ximage = xm_buf->tempImage; - ximage->data = xm_buf->data; - - /* _debug_printf("XSHM\n"); */ - XShmPutImage(b->xm_visual->display, b->drawable, b->gc, - ximage, 0, 0, 0, 0, surf->width, surf->height, False); - } - else -#endif - { - /* display image in Window */ - ximage = b->tempImage; - ximage->data = xm_buf->data; - - /* check that the XImage has been previously initialized */ - assert(ximage->format); - assert(ximage->bitmap_unit); - - /* update XImage's fields */ - ximage->width = surf->width; - ximage->height = surf->height; - ximage->bytes_per_line = spt->stride[surf->level]; - - /* _debug_printf("XPUT\n"); */ - XPutImage(b->xm_visual->display, b->drawable, b->gc, - ximage, 0, 0, 0, 0, surf->width, surf->height); - } -} - - -static void -xm_flush_frontbuffer(struct pipe_winsys *pws, - struct pipe_surface *surf, - void *context_private) -{ - /* - * The front color buffer is actually just another XImage buffer. - * This function copies that XImage to the actual X Window. - */ - XMesaContext xmctx = (XMesaContext) context_private; - xlib_softpipe_display_surface(xmctx->xm_buffer, surf); - xmesa_check_and_update_buffer_size(xmctx, xmctx->xm_buffer); -} - - - -static const char * -xm_get_name(struct pipe_winsys *pws) -{ - return "Xlib"; -} - - -static struct pipe_buffer * -xm_buffer_create(struct pipe_winsys *pws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - /* align to 16-byte multiple for Cell */ - buffer->data = align_malloc(size, max(alignment, 16)); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -xm_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy, size; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - size = *stride * nblocksy; - -#ifdef USE_XSHM - if (!debug_get_bool_option("XLIB_NO_SHM", FALSE)) - { - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - buffer->userBuffer = FALSE; - buffer->shminfo.shmid = -1; - buffer->shminfo.shmaddr = (char *) -1; - buffer->shm = TRUE; - - buffer->data = alloc_shm(buffer, size); - if (!buffer->data) - goto out; - - return &buffer->base; - - out: - if (buffer) - FREE(buffer); - } -#endif - - - return winsys->buffer_create(winsys, alignment, - usage, - size); -} - - -/* - * Fence functions - basically nothing to do, as we don't create any actual - * fence objects. - */ - -static void -xm_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -xm_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -xm_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - - -static struct pipe_winsys * -xlib_create_softpipe_winsys( void ) -{ - static struct xmesa_pipe_winsys *ws = NULL; - - if (!ws) { - ws = CALLOC_STRUCT(xmesa_pipe_winsys); - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - */ - ws->base.buffer_create = xm_buffer_create; - ws->base.user_buffer_create = xm_user_buffer_create; - ws->base.buffer_map = xm_buffer_map; - ws->base.buffer_unmap = xm_buffer_unmap; - ws->base.buffer_destroy = xm_buffer_destroy; - - ws->base.surface_buffer_create = xm_surface_buffer_create; - - ws->base.fence_reference = xm_fence_reference; - ws->base.fence_signalled = xm_fence_signalled; - ws->base.fence_finish = xm_fence_finish; - - ws->base.flush_frontbuffer = xm_flush_frontbuffer; - ws->base.get_name = xm_get_name; - } - - return &ws->base; -} - - -static struct pipe_screen * -xlib_create_softpipe_screen( void ) -{ - struct pipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = xlib_create_softpipe_winsys(); - if (winsys == NULL) - return NULL; - - screen = softpipe_create_screen(winsys); - if (screen == NULL) - goto fail; - - return screen; - -fail: - if (winsys) - winsys->destroy( winsys ); - - return NULL; -} - - -struct xm_driver xlib_softpipe_driver = -{ - .create_pipe_screen = xlib_create_softpipe_screen, - .display_surface = xlib_softpipe_display_surface -}; - - - diff --git a/src/gallium/winsys/xlib/xlib_llvmpipe.c b/src/gallium/winsys/xlib/xlib_sw_winsys.c index 6cebd4c2012..54789d7a87c 100644 --- a/src/gallium/winsys/xlib/xlib_llvmpipe.c +++ b/src/gallium/winsys/xlib/xlib_sw_winsys.c @@ -32,25 +32,21 @@ * Brian Paul */ - -#if defined(GALLIUM_LLVMPIPE) - -#include "xm_api.h" - -#undef ASSERT -#undef Elements - -#include "util/u_simple_screen.h" #include "pipe/p_format.h" #include "pipe/p_context.h" #include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" -#include "llvmpipe/lp_winsys.h" -#include "llvmpipe/lp_texture.h" -#include "xlib.h" +#include "state_tracker/xlib_sw_winsys.h" + +#include <X11/Xlib.h> +#include <X11/Xlibint.h> +#include <X11/Xutil.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> /** * Subclass of pipe_buffer for Xlib winsys. @@ -66,28 +62,38 @@ struct xm_displaytarget void *data; void *mapped; + Display *display; + Visual *visual; XImage *tempImage; -#ifdef USE_XSHM - int shm; + GC gc; + + /* This is the last drawable that this display target was presented + * against. May need to recreate gc, tempImage when this changes?? + */ + Drawable drawable; + XShmSegmentInfo shminfo; -#endif + int shm; }; /** - * Subclass of llvmpipe_winsys for Xlib winsys + * Subclass of sw_winsys for Xlib winsys */ -struct xmesa_llvmpipe_winsys +struct xlib_sw_winsys { - struct llvmpipe_winsys base; -/* struct xmesa_visual *xm_visual; */ + struct sw_winsys base; + + + + Display *display; }; /** Cast wrapper */ static INLINE struct xm_displaytarget * -xm_displaytarget( struct llvmpipe_displaytarget *dt ) +xm_displaytarget( struct sw_displaytarget *dt ) { return (struct xm_displaytarget *)dt; } @@ -97,8 +103,6 @@ xm_displaytarget( struct llvmpipe_displaytarget *dt ) * X Shared Memory Image extension code */ -#ifdef USE_XSHM - static volatile int mesaXErrorFlag = 0; /** @@ -138,8 +142,8 @@ static char *alloc_shm(struct xm_displaytarget *buf, unsigned size) * Allocate a shared memory XImage back buffer for the given XMesaBuffer. */ static void -alloc_shm_ximage(struct xm_displaytarget *xm_buffer, - struct xmesa_buffer *xmb, +alloc_shm_ximage(struct xm_displaytarget *xm_dt, + struct xlib_drawable *xmb, unsigned width, unsigned height) { /* @@ -150,15 +154,15 @@ alloc_shm_ximage(struct xm_displaytarget *xm_buffer, */ int (*old_handler)(Display *, XErrorEvent *); - xm_buffer->tempImage = XShmCreateImage(xmb->xm_visual->display, - xmb->xm_visual->visinfo->visual, - xmb->xm_visual->visinfo->depth, - ZPixmap, - NULL, - &xm_buffer->shminfo, - width, height); - if (xm_buffer->tempImage == NULL) { - xm_buffer->shm = 0; + xm_dt->tempImage = XShmCreateImage(xm_dt->display, + xmb->visual, + xmb->depth, + ZPixmap, + NULL, + &xm_dt->shminfo, + width, height); + if (xm_dt->tempImage == NULL) { + xm_dt->shm = 0; return; } @@ -166,27 +170,45 @@ alloc_shm_ximage(struct xm_displaytarget *xm_buffer, mesaXErrorFlag = 0; old_handler = XSetErrorHandler(mesaHandleXError); /* This may trigger the X protocol error we're ready to catch: */ - XShmAttach(xmb->xm_visual->display, &xm_buffer->shminfo); - XSync(xmb->xm_visual->display, False); + XShmAttach(xm_dt->display, &xm_dt->shminfo); + XSync(xm_dt->display, False); if (mesaXErrorFlag) { /* we are on a remote display, this error is normal, don't print it */ - XFlush(xmb->xm_visual->display); + XFlush(xm_dt->display); mesaXErrorFlag = 0; - XDestroyImage(xm_buffer->tempImage); - xm_buffer->tempImage = NULL; - xm_buffer->shm = 0; + XDestroyImage(xm_dt->tempImage); + xm_dt->tempImage = NULL; + xm_dt->shm = 0; (void) XSetErrorHandler(old_handler); return; } - xm_buffer->shm = 1; + xm_dt->shm = 1; } -#endif /* USE_XSHM */ + +static void +alloc_ximage(struct xm_displaytarget *xm_dt, + struct xlib_drawable *xmb, + unsigned width, unsigned height) +{ + if (xm_dt->shm) { + alloc_shm_ximage(xm_dt, xmb, width, height); + return; + } + + xm_dt->tempImage = XCreateImage(xm_dt->display, + xmb->visual, + xmb->depth, + ZPixmap, 0, + NULL, width, height, + 8, 0); +} static boolean -xm_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, +xm_is_displaytarget_format_supported( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format ) { /* TODO: check visuals or other sensible thing here */ @@ -195,8 +217,8 @@ xm_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, static void * -xm_displaytarget_map(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, +xm_displaytarget_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, unsigned flags) { struct xm_displaytarget *xm_dt = xm_displaytarget(dt); @@ -205,21 +227,20 @@ xm_displaytarget_map(struct llvmpipe_winsys *ws, } static void -xm_displaytarget_unmap(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt) +xm_displaytarget_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt) { struct xm_displaytarget *xm_dt = xm_displaytarget(dt); xm_dt->mapped = NULL; } static void -xm_displaytarget_destroy(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt) +xm_displaytarget_destroy(struct sw_winsys *ws, + struct sw_displaytarget *dt) { struct xm_displaytarget *xm_dt = xm_displaytarget(dt); if (xm_dt->data) { -#ifdef USE_XSHM if (xm_dt->shminfo.shmid >= 0) { shmdt(xm_dt->shminfo.shmaddr); shmctl(xm_dt->shminfo.shmid, IPC_RMID, 0); @@ -227,11 +248,17 @@ xm_displaytarget_destroy(struct llvmpipe_winsys *ws, xm_dt->shminfo.shmid = -1; xm_dt->shminfo.shmaddr = (char *) -1; } - else -#endif + else { FREE(xm_dt->data); + } } + if (xm_dt->tempImage) + XDestroyImage(xm_dt->tempImage); + + if (xm_dt->gc) + XFreeGC(xm_dt->display, xm_dt->gc); + FREE(xm_dt); } @@ -241,13 +268,14 @@ xm_displaytarget_destroy(struct llvmpipe_winsys *ws, * by the XMesaBuffer. */ static void -xm_llvmpipe_display(struct xmesa_buffer *xm_buffer, - struct llvmpipe_displaytarget *dt) +xlib_sw_display(struct xlib_drawable *xlib_drawable, + struct sw_displaytarget *dt) { - XImage *ximage; - struct xm_displaytarget *xm_dt = xm_displaytarget(dt); static boolean no_swap = 0; static boolean firsttime = 1; + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + Display *display = xm_dt->display; + XImage *ximage; if (firsttime) { no_swap = getenv("SP_NO_RAST") != NULL; @@ -257,28 +285,45 @@ xm_llvmpipe_display(struct xmesa_buffer *xm_buffer, if (no_swap) return; -#ifdef USE_XSHM - if (xm_dt->shm) - { - if (xm_dt->tempImage == NULL) - { - assert(util_format_get_blockwidth(xm_dt->format) == 1); - assert(util_format_get_blockheight(xm_dt->format) == 1); - alloc_shm_ximage(xm_dt, xm_buffer, - xm_dt->stride / util_format_get_blocksize(xm_dt->format), - xm_dt->height); + if (xm_dt->drawable != xlib_drawable->drawable) { + if (xm_dt->gc) { + XFreeGC( display, xm_dt->gc ); + xm_dt->gc = NULL; } + if (xm_dt->tempImage) { + XDestroyImage( xm_dt->tempImage ); + xm_dt->tempImage = NULL; + } + + xm_dt->drawable = xlib_drawable->drawable; + } + + if (xm_dt->tempImage == NULL) { + assert(util_format_get_blockwidth(xm_dt->format) == 1); + assert(util_format_get_blockheight(xm_dt->format) == 1); + alloc_ximage(xm_dt, xlib_drawable, + xm_dt->stride / util_format_get_blocksize(xm_dt->format), + xm_dt->height); + if (!xm_dt->tempImage) + return; + } + + if (xm_dt->gc == NULL) { + xm_dt->gc = XCreateGC( display, xlib_drawable->drawable, 0, NULL ); + XSetFunction( display, xm_dt->gc, GXcopy ); + } + + if (xm_dt->shm) + { ximage = xm_dt->tempImage; ximage->data = xm_dt->data; /* _debug_printf("XSHM\n"); */ - XShmPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, + XShmPutImage(xm_dt->display, xlib_drawable->drawable, xm_dt->gc, ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height, False); } - else -#endif - { + else { /* display image in Window */ ximage = xm_dt->tempImage; ximage->data = xm_dt->data; @@ -293,7 +338,7 @@ xm_llvmpipe_display(struct xmesa_buffer *xm_buffer, ximage->bytes_per_line = xm_dt->stride; /* _debug_printf("XPUT\n"); */ - XPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, + XPutImage(xm_dt->display, xlib_drawable->drawable, xm_dt->gc, ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height); } } @@ -303,30 +348,31 @@ xm_llvmpipe_display(struct xmesa_buffer *xm_buffer, * by the XMesaBuffer. */ static void -xm_displaytarget_display(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, +xm_displaytarget_display(struct sw_winsys *ws, + struct sw_displaytarget *dt, void *context_private) { - XMesaContext xmctx = (XMesaContext) context_private; - struct xmesa_buffer *xm_buffer = xmctx->xm_buffer; - xm_llvmpipe_display(xm_buffer, dt); + struct xlib_drawable *xlib_drawable = (struct xlib_drawable *)context_private; + xlib_sw_display(xlib_drawable, dt); } -static struct llvmpipe_displaytarget * -xm_displaytarget_create(struct llvmpipe_winsys *winsys, +static struct sw_displaytarget * +xm_displaytarget_create(struct sw_winsys *winsys, + unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, unsigned *stride) { - struct xm_displaytarget *xm_dt = CALLOC_STRUCT(xm_displaytarget); + struct xm_displaytarget *xm_dt; unsigned nblocksy, size; xm_dt = CALLOC_STRUCT(xm_displaytarget); if(!xm_dt) goto no_xm_dt; + xm_dt->display = ((struct xlib_sw_winsys *)winsys)->display; xm_dt->format = format; xm_dt->width = width; xm_dt->height = height; @@ -335,7 +381,6 @@ xm_displaytarget_create(struct llvmpipe_winsys *winsys, xm_dt->stride = align(util_format_get_stride(format, width), alignment); size = xm_dt->stride * nblocksy; -#ifdef USE_XSHM if (!debug_get_bool_option("XLIB_NO_SHM", FALSE)) { xm_dt->shminfo.shmid = -1; @@ -346,7 +391,6 @@ xm_displaytarget_create(struct llvmpipe_winsys *winsys, if(!xm_dt->data) goto no_data; } -#endif if(!xm_dt->data) { xm_dt->data = align_malloc(size, alignment); @@ -355,7 +399,7 @@ xm_displaytarget_create(struct llvmpipe_winsys *winsys, } *stride = xm_dt->stride; - return (struct llvmpipe_displaytarget *)xm_dt; + return (struct sw_displaytarget *)xm_dt; no_data: FREE(xm_dt); @@ -364,27 +408,51 @@ no_xm_dt: } +static struct sw_displaytarget * +xm_displaytarget_from_handle(struct sw_winsys *winsys, + const struct pipe_texture *templet, + struct winsys_handle *whandle, + unsigned *stride) +{ + assert(0); + return NULL; +} + + +static boolean +xm_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + assert(0); + return FALSE; +} + + static void -xm_destroy( struct llvmpipe_winsys *ws ) +xm_destroy( struct sw_winsys *ws ) { FREE(ws); } -static struct llvmpipe_winsys * -xlib_create_llvmpipe_winsys( void ) +struct sw_winsys * +xlib_create_sw_winsys( Display *display ) { - struct xmesa_llvmpipe_winsys *ws; + struct xlib_sw_winsys *ws; - ws = CALLOC_STRUCT(xmesa_llvmpipe_winsys); + ws = CALLOC_STRUCT(xlib_sw_winsys); if (!ws) return NULL; + ws->display = display; ws->base.destroy = xm_destroy; ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported; ws->base.displaytarget_create = xm_displaytarget_create; + ws->base.displaytarget_from_handle = xm_displaytarget_from_handle; + ws->base.displaytarget_get_handle = xm_displaytarget_get_handle; ws->base.displaytarget_map = xm_displaytarget_map; ws->base.displaytarget_unmap = xm_displaytarget_unmap; ws->base.displaytarget_destroy = xm_displaytarget_destroy; @@ -394,49 +462,3 @@ xlib_create_llvmpipe_winsys( void ) return &ws->base; } - -static struct pipe_screen * -xlib_create_llvmpipe_screen( void ) -{ - struct llvmpipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = xlib_create_llvmpipe_winsys(); - if (winsys == NULL) - return NULL; - - screen = llvmpipe_create_screen(winsys); - if (screen == NULL) - goto fail; - - return screen; - -fail: - if (winsys) - winsys->destroy( winsys ); - - return NULL; -} - - -static void -xlib_llvmpipe_display_surface(struct xmesa_buffer *xm_buffer, - struct pipe_surface *surf) -{ - struct llvmpipe_texture *texture = llvmpipe_texture(surf->texture); - - assert(texture->dt); - if (texture->dt) - xm_llvmpipe_display(xm_buffer, texture->dt); -} - - -struct xm_driver xlib_llvmpipe_driver = -{ - .create_pipe_screen = xlib_create_llvmpipe_screen, - .display_surface = xlib_llvmpipe_display_surface -}; - - - -#endif /* GALLIUM_LLVMPIPE */ diff --git a/src/gallium/winsys/xlib/xmesa.h b/src/gallium/winsys/xlib/xmesa.h deleted file mode 100644 index 98139af8336..00000000000 --- a/src/gallium/winsys/xlib/xmesa.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 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. - */ - - -/* - * Mesa/X11 interface. This header file serves as the documentation for - * the Mesa/X11 interface functions. - * - * Note: this interface isn't intended for user programs. It's primarily - * just for implementing the pseudo-GLX interface. - */ - - -/* Sample Usage: - -In addition to the usual X calls to select a visual, create a colormap -and create a window, you must do the following to use the X/Mesa interface: - -1. Call XMesaCreateVisual() to make an XMesaVisual from an XVisualInfo. - -2. Call XMesaCreateContext() to create an X/Mesa rendering context, given - the XMesaVisual. - -3. Call XMesaCreateWindowBuffer() to create an XMesaBuffer from an X window - and XMesaVisual. - -4. Call XMesaMakeCurrent() to bind the XMesaBuffer to an XMesaContext and - to make the context the current one. - -5. Make gl* calls to render your graphics. - -6. Use XMesaSwapBuffers() when double buffering to swap front/back buffers. - -7. Before the X window is destroyed, call XMesaDestroyBuffer(). - -8. Before exiting, call XMesaDestroyVisual and XMesaDestroyContext. - -*/ - - - - -#ifndef XMESA_H -#define XMESA_H - -#ifdef __VMS -#include <GL/vms_x_fix.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef XFree86Server -#include "xmesa_xf86.h" -#else -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include "xmesa_x.h" -#endif -#include "GL/gl.h" - -#ifdef AMIWIN -#include <pragmas/xlib_pragmas.h> -extern struct Library *XLibBase; -#endif - - -#define XMESA_MAJOR_VERSION 6 -#define XMESA_MINOR_VERSION 3 - - - -/* - * Values passed to XMesaGetString: - */ -#define XMESA_VERSION 1 -#define XMESA_EXTENSIONS 2 - - -/* - * Values passed to XMesaSetFXmode: - */ -#define XMESA_FX_WINDOW 1 -#define XMESA_FX_FULLSCREEN 2 - - - -typedef struct xmesa_context *XMesaContext; - -typedef struct xmesa_visual *XMesaVisual; - -typedef struct xmesa_buffer *XMesaBuffer; - - - -/* - * Create a new X/Mesa visual. - * Input: display - X11 display - * visinfo - an XVisualInfo pointer - * rgb_flag - GL_TRUE = RGB mode, - * GL_FALSE = color index mode - * alpha_flag - alpha buffer requested? - * db_flag - GL_TRUE = double-buffered, - * GL_FALSE = single buffered - * stereo_flag - stereo visual? - * ximage_flag - GL_TRUE = use an XImage for back buffer, - * GL_FALSE = use an off-screen pixmap for back buffer - * depth_size - requested bits/depth values, or zero - * stencil_size - requested bits/stencil values, or zero - * accum_red_size - requested bits/red accum values, or zero - * accum_green_size - requested bits/green accum values, or zero - * accum_blue_size - requested bits/blue accum values, or zero - * accum_alpha_size - requested bits/alpha accum values, or zero - * num_samples - number of samples/pixel if multisampling, or zero - * level - visual level, usually 0 - * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT - * Return; a new XMesaVisual or 0 if error. - */ -extern XMesaVisual XMesaCreateVisual( XMesaDisplay *display, - XMesaVisualInfo 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 ); - -/* - * Destroy an XMesaVisual, but not the associated XVisualInfo. - */ -extern void XMesaDestroyVisual( XMesaVisual v ); - - - -/* - * Create a new XMesaContext for rendering into an X11 window. - * - * Input: visual - an XMesaVisual - * share_list - another XMesaContext with which to share display - * lists or NULL if no sharing is wanted. - * Return: an XMesaContext or NULL if error. - */ -extern XMesaContext XMesaCreateContext( XMesaVisual v, - XMesaContext share_list ); - - -/* - * Destroy a rendering context as returned by XMesaCreateContext() - */ -extern void XMesaDestroyContext( XMesaContext c ); - - -#ifdef XFree86Server -/* - * These are the extra routines required for integration with XFree86. - * None of these routines should be user visible. -KEM - */ -extern GLboolean XMesaForceCurrent( XMesaContext c ); - -extern GLboolean XMesaLoseCurrent( XMesaContext c ); - -extern GLboolean XMesaCopyContext( XMesaContext src, - XMesaContext dst, - GLuint mask ); -#endif /* XFree86Server */ - - -/* - * Create an XMesaBuffer from an X window. - */ -extern XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ); - - -/* - * Create an XMesaBuffer from an X pixmap. - */ -extern XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, - XMesaPixmap p, - XMesaColormap cmap ); - - -/* - * Destroy an XMesaBuffer, but not the corresponding window or pixmap. - */ -extern void XMesaDestroyBuffer( XMesaBuffer b ); - - -/* - * Return the XMesaBuffer handle which corresponds to an X drawable, if any. - * - * New in Mesa 2.3. - */ -extern XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, - XMesaDrawable d ); - - - -/* - * Bind a buffer to a context and make the context the current one. - */ -extern GLboolean XMesaMakeCurrent( XMesaContext c, - XMesaBuffer b ); - - -/* - * Bind two buffers (read and draw) to a context and make the - * context the current one. - * New in Mesa 3.3 - */ -extern GLboolean XMesaMakeCurrent2( XMesaContext c, - XMesaBuffer drawBuffer, - XMesaBuffer readBuffer ); - - -/* - * Unbind the current context from its buffer. - */ -extern GLboolean XMesaUnbindContext( XMesaContext c ); - - -/* - * Return a handle to the current context. - */ -extern XMesaContext XMesaGetCurrentContext( void ); - - -/* - * Return handle to the current (draw) buffer. - */ -extern XMesaBuffer XMesaGetCurrentBuffer( void ); - - -/* - * Return handle to the current read buffer. - * New in Mesa 3.3 - */ -extern XMesaBuffer XMesaGetCurrentReadBuffer( void ); - - -/* - * Swap the front and back buffers for the given buffer. No action is - * taken if the buffer is not double buffered. - */ -extern void XMesaSwapBuffers( XMesaBuffer b ); - - -/* - * Copy a sub-region of the back buffer to the front buffer. - * - * New in Mesa 2.6 - */ -extern void XMesaCopySubBuffer( XMesaBuffer b, - int x, - int y, - int width, - int height ); - - -/* - * Return a pointer to the the Pixmap or XImage being used as the back - * color buffer of an XMesaBuffer. This function is a way to get "under - * the hood" of X/Mesa so one can manipulate the back buffer directly. - * Input: b - the XMesaBuffer - * Output: pixmap - pointer to back buffer's Pixmap, or 0 - * ximage - pointer to back buffer's XImage, or NULL - * Return: GL_TRUE = context is double buffered - * GL_FALSE = context is single buffered - */ -extern GLboolean XMesaGetBackBuffer( XMesaBuffer b, - XMesaPixmap *pixmap, - XMesaImage **ximage ); - - - -/* - * Return the depth buffer associated with an XMesaBuffer. - * Input: b - the XMesa buffer handle - * Output: width, height - size of buffer in pixels - * bytesPerValue - bytes per depth value (2 or 4) - * buffer - pointer to depth buffer values - * Return: GL_TRUE or GL_FALSE to indicate success or failure. - * - * New in Mesa 2.4. - */ -extern GLboolean XMesaGetDepthBuffer( XMesaBuffer b, - GLint *width, - GLint *height, - GLint *bytesPerValue, - void **buffer ); - - - -/* - * Flush/sync a context - */ -extern void XMesaFlush( XMesaContext c ); - - - -/* - * Get an X/Mesa-specific string. - * Input: name - either XMESA_VERSION or XMESA_EXTENSIONS - */ -extern const char *XMesaGetString( XMesaContext c, int name ); - - - -/* - * Scan for XMesaBuffers whose window/pixmap has been destroyed, then free - * any memory used by that buffer. - * - * New in Mesa 2.3. - */ -extern void XMesaGarbageCollect( void ); - - - -/* - * Return a dithered pixel value. - * Input: c - XMesaContext - * x, y - window coordinate - * red, green, blue, alpha - color components in [0,1] - * Return: pixel value - * - * New in Mesa 2.3. - */ -extern unsigned long XMesaDitherColor( XMesaContext xmesa, - GLint x, - GLint y, - GLfloat red, - GLfloat green, - GLfloat blue, - GLfloat alpha ); - - - -/* - * 3Dfx Glide driver only! - * Set 3Dfx/Glide full-screen or window rendering mode. - * Input: mode - either XMESA_FX_WINDOW (window rendering mode) or - * XMESA_FX_FULLSCREEN (full-screen rendering mode) - * Return: GL_TRUE if success - * GL_FALSE if invalid mode or if not using 3Dfx driver - * - * New in Mesa 2.6. - */ -extern GLboolean XMesaSetFXmode( GLint mode ); - - - -/* - * Reallocate the back/depth/stencil/accum/etc/ buffers associated with - * buffer <b> if its size has changed. - * - * New in Mesa 4.0.2 - */ -extern void XMesaResizeBuffers( XMesaBuffer b ); - - - -/* - * Create a pbuffer. - * New in Mesa 4.1 - */ -extern XMesaBuffer XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, - unsigned int width, unsigned int height); - - - -/* - * Texture from Pixmap - * New in Mesa 7.1 - */ -extern void -XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer, - const int *attrib_list); - -extern void -XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer); - - -extern XMesaBuffer -XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p, - XMesaColormap cmap, - int format, int target, int mipmap); - - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/src/gallium/winsys/xlib/xmesa_x.h b/src/gallium/winsys/xlib/xmesa_x.h deleted file mode 100644 index 865bab4313b..00000000000 --- a/src/gallium/winsys/xlib/xmesa_x.h +++ /dev/null @@ -1,86 +0,0 @@ - -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -/* - * Authors: - * Kevin E. Martin <[email protected]> - * - * When we're building the XMesa driver for stand-alone Mesa we - * include this file when building the xm_*.c files. - * We need to define some types and macros differently when building - * in the Xserver vs. stand-alone Mesa. - */ - -#ifndef _XMESA_X_H_ -#define _XMESA_X_H_ - -typedef Display XMesaDisplay; -typedef Pixmap XMesaPixmap; -typedef Colormap XMesaColormap; -typedef Drawable XMesaDrawable; -typedef Window XMesaWindow; -typedef GC XMesaGC; -typedef XVisualInfo *XMesaVisualInfo; -typedef XImage XMesaImage; -typedef XPoint XMesaPoint; -typedef XColor XMesaColor; - -#define XMesaDestroyImage XDestroyImage - -#define XMesaPutPixel XPutPixel -#define XMesaGetPixel XGetPixel - -#define XMesaSetForeground XSetForeground -#define XMesaSetBackground XSetBackground -#define XMesaSetPlaneMask XSetPlaneMask -#define XMesaSetFunction XSetFunction -#define XMesaSetFillStyle XSetFillStyle -#define XMesaSetTile XSetTile - -#define XMesaDrawPoint XDrawPoint -#define XMesaDrawPoints XDrawPoints -#define XMesaDrawLine XDrawLine -#define XMesaFillRectangle XFillRectangle -#define XMesaGetImage XGetImage -#define XMesaPutImage XPutImage -#define XMesaCopyArea XCopyArea - -#define XMesaCreatePixmap XCreatePixmap -#define XMesaFreePixmap XFreePixmap -#define XMesaFreeGC XFreeGC - -#define GET_COLORMAP_SIZE(__v) __v->visinfo->colormap_size -#define GET_REDMASK(__v) __v->mesa_visual.redMask -#define GET_GREENMASK(__v) __v->mesa_visual.greenMask -#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask -#define GET_VISUAL_DEPTH(__v) __v->visinfo->depth -#define GET_BLACK_PIXEL(__v) BlackPixel(__v->display, __v->mesa_visual.screen) -#define CHECK_BYTE_ORDER(__v) host_byte_order()==ImageByteOrder(__v->display) -#define CHECK_FOR_HPCR(__v) XInternAtom(__v->display, "_HP_RGB_SMOOTH_MAP_LIST", True) - -#endif diff --git a/src/glx/single2.c b/src/glx/single2.c index 9ecf589ffff..a1461956b99 100644 --- a/src/glx/single2.c +++ b/src/glx/single2.c @@ -44,6 +44,9 @@ #include <X11/Xlib-xcb.h> #endif /* USE_XCB */ +#if !defined(__GNUC__) +# define __builtin_expect(x, y) x +#endif /* Used for GL_ARB_transpose_matrix */ static void diff --git a/src/mesa/SConscript b/src/mesa/SConscript index 0a25dccde56..c85085434e4 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -182,6 +182,7 @@ if env['platform'] != 'winddk': 'state_tracker/st_format.c', 'state_tracker/st_framebuffer.c', 'state_tracker/st_gen_mipmap.c', + 'state_tracker/st_manager.c', 'state_tracker/st_mesa_to_tgsi.c', 'state_tracker/st_program.c', 'state_tracker/st_texture.c', @@ -249,6 +250,8 @@ if env['platform'] != 'winddk': glapi_sources = [ 'glapi/glapi.c', 'glapi/glapi_dispatch.c', + 'glapi/glapi_entrypoint.c', + 'glapi/glapi_execmem.c', 'glapi/glapi_getproc.c', 'glapi/glapi_nop.c', 'glapi/glthread.c', diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c index b97b760f181..84a2a5fcb3a 100644 --- a/src/mesa/drivers/common/meta.c +++ b/src/mesa/drivers/common/meta.c @@ -429,13 +429,15 @@ _mesa_meta_begin(GLcontext *ctx, GLbitfield state) if (state & META_SHADER) { if (ctx->Extensions.ARB_vertex_program) { save->VertexProgramEnabled = ctx->VertexProgram.Enabled; - save->VertexProgram = ctx->VertexProgram.Current; + _mesa_reference_vertprog(ctx, &save->VertexProgram, + ctx->VertexProgram.Current); _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE); } if (ctx->Extensions.ARB_fragment_program) { save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled; - save->FragmentProgram = ctx->FragmentProgram.Current; + _mesa_reference_fragprog(ctx, &save->FragmentProgram, + ctx->FragmentProgram.Current); _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); } @@ -663,6 +665,7 @@ _mesa_meta_end(GLcontext *ctx) save->VertexProgramEnabled); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, save->VertexProgram); + _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL); } if (ctx->Extensions.ARB_fragment_program) { @@ -670,6 +673,7 @@ _mesa_meta_end(GLcontext *ctx) save->FragmentProgramEnabled); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, save->FragmentProgram); + _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); } if (ctx->Extensions.ARB_shader_objects) { @@ -720,6 +724,7 @@ _mesa_meta_end(GLcontext *ctx) for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt], save->CurrentTexture[tgt]); + _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL); } /* Re-enable textures, texgen */ @@ -2062,8 +2067,10 @@ _mesa_meta_Bitmap(GLcontext *ctx, } bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1); - if (!bitmap1) + if (!bitmap1) { + _mesa_meta_end(ctx); return; + } bitmap8 = (GLubyte *) calloc(1, width * height); if (bitmap8) { diff --git a/src/mesa/drivers/dri/common/dri_sw.c b/src/mesa/drivers/dri/common/dri_sw.c new file mode 100644 index 00000000000..b7f9036f473 --- /dev/null +++ b/src/mesa/drivers/dri/common/dri_sw.c @@ -0,0 +1,267 @@ +/* + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <[email protected]> + * + * 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. + */ + +/** + * \file dri_sw.c + * + * DRISW utility functions, i.e. dri_util.c stripped from drm-specific bits. + */ + +#include "dri_sw.h" +#include "utils.h" + + +/** + * Screen functions + */ + +static void +setupLoaderExtensions(__DRIscreen *psp, + const __DRIextension **extensions) +{ + int i; + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) + psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; + } +} + +static __DRIscreen * +driCreateNewScreen(int scrn, const __DRIextension **extensions, + const __DRIconfig ***driver_configs, void *data) +{ + static const __DRIextension *emptyExtensionList[] = { NULL }; + __DRIscreen *psp; + + (void) data; + + psp = CALLOC_STRUCT(__DRIscreenRec); + if (!psp) + return NULL; + + setupLoaderExtensions(psp, extensions); + + psp->extensions = emptyExtensionList; + psp->myNum = scrn; + + *driver_configs = driDriverAPI.InitScreen(psp); + + if (*driver_configs == NULL) { + FREE(psp); + return NULL; + } + + return psp; +} + +static void driDestroyScreen(__DRIscreen *psp) +{ + if (psp) { + driDriverAPI.DestroyScreen(psp); + + FREE(psp); + } +} + +static const __DRIextension **driGetExtensions(__DRIscreen *psp) +{ + return psp->extensions; +} + + +/** + * Context functions + */ + +static __DRIcontext * +driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, + __DRIcontext *shared, void *data) +{ + __DRIcontext *pcp; + void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + + pcp = CALLOC_STRUCT(__DRIcontextRec); + if (!pcp) + return NULL; + + pcp->loaderPrivate = data; + + pcp->driScreenPriv = psp; + pcp->driDrawablePriv = NULL; + pcp->driReadablePriv = NULL; + + if (!driDriverAPI.CreateContext(&config->modes, pcp, shareCtx)) { + FREE(pcp); + return NULL; + } + + return pcp; +} + +static void +driDestroyContext(__DRIcontext *pcp) +{ + if (pcp) { + driDriverAPI.DestroyContext(pcp); + FREE(pcp); + } +} + +static int +driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask) +{ + return GL_FALSE; +} + +static void dri_get_drawable(__DRIdrawable *pdp); +static void dri_put_drawable(__DRIdrawable *pdp); + +static int driBindContext(__DRIcontext *pcp, + __DRIdrawable *pdp, + __DRIdrawable *prp) +{ + /* Bind the drawable to the context */ + if (pcp) { + pcp->driDrawablePriv = pdp; + pcp->driReadablePriv = prp; + if (pdp) { + dri_get_drawable(pdp); + } + if ( prp && pdp != prp ) { + dri_get_drawable(prp); + } + } + + return driDriverAPI.MakeCurrent(pcp, pdp, prp); +} + +static int driUnbindContext(__DRIcontext *pcp) +{ + __DRIdrawable *pdp; + __DRIdrawable *prp; + + if (pcp == NULL) + return GL_FALSE; + + pdp = pcp->driDrawablePriv; + prp = pcp->driReadablePriv; + + /* already unbound */ + if (!pdp && !prp) + return GL_TRUE; + + driDriverAPI.UnbindContext(pcp); + + dri_put_drawable(pdp); + + if (prp != pdp) { + dri_put_drawable(prp); + } + + pcp->driDrawablePriv = NULL; + pcp->driReadablePriv = NULL; + + return GL_TRUE; +} + + +/** + * Drawable functions + */ + +static void dri_get_drawable(__DRIdrawable *pdp) +{ + pdp->refcount++; +} + +static void dri_put_drawable(__DRIdrawable *pdp) +{ + if (pdp) { + pdp->refcount--; + if (pdp->refcount) + return; + + driDriverAPI.DestroyBuffer(pdp); + + FREE(pdp); + } +} + +static __DRIdrawable * +driCreateNewDrawable(__DRIscreen *psp, + const __DRIconfig *config, void *data) +{ + __DRIdrawable *pdp; + + pdp = CALLOC_STRUCT(__DRIdrawableRec); + if (!pdp) + return NULL; + + pdp->loaderPrivate = data; + + pdp->driScreenPriv = psp; + + dri_get_drawable(pdp); + + if (!driDriverAPI.CreateBuffer(psp, pdp, &config->modes, GL_FALSE)) { + FREE(pdp); + return NULL; + } + + return pdp; +} + +static void +driDestroyDrawable(__DRIdrawable *pdp) +{ + dri_put_drawable(pdp); +} + +static void driSwapBuffers(__DRIdrawable *pdp) +{ + driDriverAPI.SwapBuffers(pdp); +} + +const __DRIcoreExtension driCoreExtension = { + { __DRI_CORE, __DRI_CORE_VERSION }, + NULL, /* driCreateNewScreen */ + driDestroyScreen, + driGetExtensions, + driGetConfigAttrib, + driIndexConfigAttrib, + NULL, /* driCreateNewDrawable */ + driDestroyDrawable, + driSwapBuffers, + driCreateNewContext, + driCopyContext, + driDestroyContext, + driBindContext, + driUnbindContext +}; + +const __DRIswrastExtension driSWRastExtension = { + { __DRI_SWRAST, __DRI_SWRAST_VERSION }, + driCreateNewScreen, + driCreateNewDrawable +}; diff --git a/src/mesa/drivers/dri/common/dri_sw.h b/src/mesa/drivers/dri/common/dri_sw.h new file mode 100644 index 00000000000..e353e26b34d --- /dev/null +++ b/src/mesa/drivers/dri/common/dri_sw.h @@ -0,0 +1,112 @@ +/* + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <[email protected]> + * + * 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. + */ + + +#ifndef _DRI_SW_H +#define _DRI_SW_H + +#include <GL/gl.h> +#include <GL/internal/glcore.h> +#include <GL/internal/dri_interface.h> + + +/** + * Extensions + */ +extern const __DRIcoreExtension driCoreExtension; +extern const __DRIswrastExtension driSWRastExtension; + + +/** + * Data types + */ +struct __DRIscreenRec { + int myNum; + + int fd; + + void *private; + + const __DRIextension **extensions; + + const __DRIswrastLoaderExtension *swrast_loader; +}; + +struct __DRIcontextRec { + + void *driverPrivate; + + void *loaderPrivate; + + __DRIdrawable *driDrawablePriv; + + __DRIdrawable *driReadablePriv; + + __DRIscreen *driScreenPriv; +}; + +struct __DRIdrawableRec { + + void *driverPrivate; + + void *loaderPrivate; + + __DRIscreen *driScreenPriv; + + int refcount; +}; + + +/** + * Driver callback functions + */ +struct __DriverAPIRec { + const __DRIconfig **(*InitScreen) (__DRIscreen * priv); + + void (*DestroyScreen)(__DRIscreen *driScrnPriv); + + GLboolean (*CreateContext)(const __GLcontextModes *glVis, + __DRIcontext *driContextPriv, + void *sharedContextPrivate); + + void (*DestroyContext)(__DRIcontext *driContextPriv); + + GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv, + __DRIdrawable *driDrawPriv, + const __GLcontextModes *glVis, + GLboolean pixmapBuffer); + + void (*DestroyBuffer)(__DRIdrawable *driDrawPriv); + + void (*SwapBuffers)(__DRIdrawable *driDrawPriv); + + GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv, + __DRIdrawable *driDrawPriv, + __DRIdrawable *driReadPriv); + + GLboolean (*UnbindContext)(__DRIcontext *driContextPriv); +}; + +extern const struct __DriverAPIRec driDriverAPI; + +#endif /* _DRI_SW_H */ diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 75c98825b79..badbb5ff824 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -47,28 +47,6 @@ const __DRIextension driReadDrawableExtension = { __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION }; -/** - * Print message to \c stderr if the \c LIBGL_DEBUG environment variable - * is set. - * - * Is called from the drivers. - * - * \param f \c printf like format string. - */ -void -__driUtilMessage(const char *f, ...) -{ - va_list args; - - if (getenv("LIBGL_DEBUG")) { - fprintf(stderr, "libGL: "); - va_start(args, f); - vfprintf(stderr, f, args); - va_end(args); - fprintf(stderr, "\n"); - } -} - GLint driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ) { diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index 99c0f1e4422..f63583cebc0 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -552,10 +552,6 @@ struct __DRIscreenRec { }; extern void -__driUtilMessage(const char *f, ...); - - -extern void __driUtilUpdateDrawableInfo(__DRIdrawable *pdp); extern float diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c index b85b364c575..0dd879abc96 100644 --- a/src/mesa/drivers/dri/common/utils.c +++ b/src/mesa/drivers/dri/common/utils.c @@ -37,6 +37,29 @@ #include "utils.h" +/** + * Print message to \c stderr if the \c LIBGL_DEBUG environment variable + * is set. + * + * Is called from the drivers. + * + * \param f \c printf like format string. + */ +void +__driUtilMessage(const char *f, ...) +{ + va_list args; + + if (getenv("LIBGL_DEBUG")) { + fprintf(stderr, "libGL: "); + va_start(args, f); + vfprintf(stderr, f, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + + unsigned driParseDebugString( const char * debug, const struct dri_debug_control * control ) @@ -230,9 +253,6 @@ void driInitSingleExtension( GLcontext * ctx, /** * Utility function used by drivers to test the verions of other components. * - * If one of the version requirements is not met, a message is logged using - * \c __driUtilMessage. - * * \param driver_name Name of the driver. Used in error messages. * \param driActual Actual DRI version supplied __driCreateNewScreen. * \param driExpected Minimum DRI version required by the driver. @@ -244,7 +264,7 @@ void driInitSingleExtension( GLcontext * ctx, * \returns \c GL_TRUE if all version requirements are met. Otherwise, * \c GL_FALSE is returned. * - * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage + * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2 * * \todo * Now that the old \c driCheckDriDdxDrmVersions function is gone, this diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h index 02ca3feb739..de6070c3987 100644 --- a/src/mesa/drivers/dri/common/utils.h +++ b/src/mesa/drivers/dri/common/utils.h @@ -69,6 +69,9 @@ struct __DRIutilversionRec2 { int patch; /**< Patch-level. */ }; +extern void +__driUtilMessage(const char *f, ...); + extern unsigned driParseDebugString( const char * debug, const struct dri_debug_control * control ); diff --git a/src/mesa/drivers/dri/common/xmlconfig.c b/src/mesa/drivers/dri/common/xmlconfig.c index 477259ea7e0..de4500a39b0 100644 --- a/src/mesa/drivers/dri/common/xmlconfig.c +++ b/src/mesa/drivers/dri/common/xmlconfig.c @@ -36,7 +36,7 @@ #include <unistd.h> #include <errno.h> #include "main/imports.h" -#include "dri_util.h" +#include "utils.h" #include "xmlconfig.h" #undef GET_PROGRAM_NAME diff --git a/src/mesa/drivers/dri/i810/Makefile b/src/mesa/drivers/dri/i810/Makefile index 3874faee518..54a837d5ea9 100644 --- a/src/mesa/drivers/dri/i810/Makefile +++ b/src/mesa/drivers/dri/i810/Makefile @@ -5,9 +5,6 @@ include $(TOP)/configs/current LIBNAME = i810_dri.so -# Not yet -# MINIGLX_SOURCES = server/i810_dri.c - DRIVER_SOURCES = \ i810context.c \ i810ioctl.c \ diff --git a/src/mesa/drivers/dri/i810/server/i810_dri.c b/src/mesa/drivers/dri/i810/server/i810_dri.c deleted file mode 100644 index f52797c5ed2..00000000000 --- a/src/mesa/drivers/dri/i810/server/i810_dri.c +++ /dev/null @@ -1,975 +0,0 @@ -/** - * \file server/i810_dri.c - * \brief File to perform the device-specific initialization tasks typically - * done in the X server. - * - * Here they are converted to run in the client (or perhaps a standalone - * process), and to work with the frame buffer device rather than the X - * server infrastructure. - * - * Copyright (C) 2004 Dave Airlie ([email protected]) - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include "driver.h" -#include "drm.h" - -#include "i810.h" -#include "i810_dri.h" -#include "i810_reg.h" - - -static int i810_pitches[] = { - 512, - 1024, - 2048, - 4096, - 0 -}; - -static int i810_pitch_flags[] = { - 0x0, - 0x1, - 0x2, - 0x3, - 0 -}; - -static unsigned int i810_drm_version = 0; - -static int -I810AllocLow(I810MemRange * result, I810MemRange * pool, int size) -{ - if (size > pool->Size) - return 0; - - pool->Size -= size; - result->Size = size; - result->Start = pool->Start; - result->End = pool->Start += size; - - return 1; -} - -static int -I810AllocHigh(I810MemRange * result, I810MemRange * pool, int size) -{ - if (size > pool->Size) - return 0; - - pool->Size -= size; - result->Size = size; - result->End = pool->End; - result->Start = pool->End -= size; - - return 1; -} - - -/** - * \brief Wait for free FIFO entries. - * - * \param ctx display handle. - * \param entries number of free entries to wait. - * - * It polls the free entries from the chip until it reaches the requested value - * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out. - */ -static void I810WaitForFifo( const DRIDriverContext *ctx, - int entries ) -{ -} - -/** - * \brief Reset graphics card to known state. - * - * \param ctx display handle. - * - * Resets the values of several I810 registers. - */ -static void I810EngineReset( const DRIDriverContext *ctx ) -{ - unsigned char *I810MMIO = ctx->MMIOAddress; -} - -/** - * \brief Restore the drawing engine. - * - * \param ctx display handle - * - * Resets the graphics card and sets initial values for several registers of - * the card's drawing engine. - * - * Turns on the i810 command processor engine (i.e., the ringbuffer). - */ -static int I810EngineRestore( const DRIDriverContext *ctx ) -{ - I810Ptr info = ctx->driverPrivate; - unsigned char *I810MMIO = ctx->MMIOAddress; - - fprintf(stderr, "%s\n", __FUNCTION__); - - return 1; -} - - -/** - * \brief Shutdown the drawing engine. - * - * \param ctx display handle - * - * Turns off the command processor engine & restores the graphics card - * to a state that fbdev understands. - */ -static int I810EngineShutdown( const DRIDriverContext *ctx ) -{ - drmI810Init info; - int ret; - - memset(&info, 0, sizeof(drmI810Init)); - info.func = I810_CLEANUP_DMA; - - ret = drmCommandWrite(ctx->drmFD, DRM_I810_INIT, &info, sizeof(drmI810Init)); - if (ret>0) - { - fprintf(stderr,"[dri] I810 DMA Cleanup failed\n"); - return -errno; - } - return 0; -} - -/** - * \brief Compute base 2 logarithm. - * - * \param val value. - * - * \return base 2 logarithm of \p val. - */ -static int I810MinBits(int val) -{ - int bits; - - if (!val) return 1; - for (bits = 0; val; val >>= 1, ++bits); - return bits; -} - -static int I810DRIAgpPreInit( const DRIDriverContext *ctx, I810Ptr info) -{ - - if (drmAgpAcquire(ctx->drmFD) < 0) { - fprintf(stderr, "[gart] AGP not available\n"); - return 0; - } - - - if (drmAgpEnable(ctx->drmFD, 0) < 0) { - fprintf(stderr, "[gart] AGP not enabled\n"); - drmAgpRelease(ctx->drmFD); - return 0; - } -} - -/** - * \brief Initialize the AGP state - * - * \param ctx display handle. - * \param info driver private data. - * - * \return one on success, or zero on failure. - * - * Acquires and enables the AGP device. Reserves memory in the AGP space for - * the ring buffer, vertex buffers and textures. Initialize the I810 - * registers to point to that memory and add client mappings. - */ -static int I810DRIAgpInit( const DRIDriverContext *ctx, I810Ptr info) -{ - unsigned char *I810MMIO = ctx->MMIOAddress; - int ret; - int s, l; - unsigned long dcacheHandle; - unsigned long agpHandle; - int pitch_idx = 0; - int back_size = 0; - int sysmem_size = 0; - int width = ctx->shared.virtualWidth * ctx->cpp; - - - info->backHandle = DRM_AGP_NO_HANDLE; - info->zHandle = DRM_AGP_NO_HANDLE; - info->sysmemHandle = DRM_AGP_NO_HANDLE; - info->dcacheHandle = DRM_AGP_NO_HANDLE; - - memset(&info->DcacheMem, 0, sizeof(I810MemRange)); - memset(&info->BackBuffer, 0, sizeof(I810MemRange)); - memset(&info->DepthBuffer, 0, sizeof(I810MemRange)); - - drmAgpAlloc(ctx->drmFD, 4096 * 1024, 1, NULL, &dcacheHandle); - info->dcacheHandle = dcacheHandle; - - fprintf(stderr, "[agp] dcacheHandle : 0x%x\n", dcacheHandle); - -#define Elements(x) sizeof(x)/sizeof(*x) - for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++) - if (width <= i810_pitches[pitch_idx]) - break; - - if (pitch_idx == Elements(i810_pitches)) { - fprintf(stderr,"[dri] Couldn't find depth/back buffer pitch\n"); - exit(-1); - } - else - { - int lines = (ctx->shared.virtualWidth + 15) / 16 * 16; - back_size = i810_pitches[pitch_idx] * lines; - back_size = ((back_size + 4096 - 1) / 4096) * 4096; - } - - sysmem_size = ctx->shared.fbSize; - fprintf(stderr,"sysmem_size is %lu back_size is %lu\n", sysmem_size, back_size); - if (dcacheHandle != DRM_AGP_NO_HANDLE) { - if (back_size > 4 * 1024 * 1024) { - fprintf(stderr,"[dri] Backsize is larger then 4 meg\n"); - sysmem_size = sysmem_size - 2 * back_size; - drmAgpFree(ctx->drmFD, dcacheHandle); - info->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; - } else { - sysmem_size = sysmem_size - back_size; - } - } else { - sysmem_size = sysmem_size - 2 * back_size; - } - - info->SysMem.Start=0; - info->SysMem.Size = sysmem_size; - info->SysMem.End = sysmem_size; - - if (dcacheHandle != DRM_AGP_NO_HANDLE) { - if (drmAgpBind(ctx->drmFD, dcacheHandle, info->DepthOffset) == 0) { - memset(&info->DcacheMem, 0, sizeof(I810MemRange)); - fprintf(stderr,"[agp] GART: Found 4096K Z buffer memory\n"); - info->DcacheMem.Start = info->DepthOffset; - info->DcacheMem.Size = 1024 * 4096; - info->DcacheMem.End = info->DcacheMem.Start + info->DcacheMem.Size; - } else { - fprintf(stderr, "[agp] GART: dcache bind failed\n"); - drmAgpFree(ctx->drmFD, dcacheHandle); - info->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; - } - } else { - fprintf(stderr, "[agp] GART: no dcache memory found\n"); - } - - drmAgpAlloc(ctx->drmFD, back_size, 0, NULL, &agpHandle); - info->backHandle = agpHandle; - - if (agpHandle != DRM_AGP_NO_HANDLE) { - if (drmAgpBind(ctx->drmFD, agpHandle, info->BackOffset) == 0) { - fprintf(stderr, "[agp] Bound backbuffer memory\n"); - - info->BackBuffer.Start = info->BackOffset; - info->BackBuffer.Size = back_size; - info->BackBuffer.End = (info->BackBuffer.Start + - info->BackBuffer.Size); - } else { - fprintf(stderr,"[agp] Unable to bind backbuffer. Disabling DRI.\n"); - return 0; - } - } else { - fprintf(stderr, "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n"); - return 0; - } - - if (dcacheHandle == DRM_AGP_NO_HANDLE) { - drmAgpAlloc(ctx->drmFD, back_size, 0, NULL, &agpHandle); - - info->zHandle = agpHandle; - - if (agpHandle != DRM_AGP_NO_HANDLE) { - if (drmAgpBind(ctx->drmFD, agpHandle, info->DepthOffset) == 0) { - fprintf(stderr,"[agp] Bound depthbuffer memory\n"); - info->DepthBuffer.Start = info->DepthOffset; - info->DepthBuffer.Size = back_size; - info->DepthBuffer.End = (info->DepthBuffer.Start + - info->DepthBuffer.Size); - } else { - fprintf(stderr,"[agp] Unable to bind depthbuffer. Disabling DRI.\n"); - return 0; - } - } else { - fprintf(stderr,"[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n"); - return 0; - } - } - - /* Now allocate and bind the agp space. This memory will include the - * regular framebuffer as well as texture memory. - */ - drmAgpAlloc(ctx->drmFD, sysmem_size, 0, NULL, &agpHandle); - info->sysmemHandle = agpHandle; - - if (agpHandle != DRM_AGP_NO_HANDLE) { - if (drmAgpBind(ctx->drmFD, agpHandle, 0) == 0) { - fprintf(stderr, "[agp] Bound System Texture Memory\n"); - } else { - fprintf(stderr, "[agp] Unable to bind system texture memory. Disabling DRI.\n"); - return 0; - } - } else { - fprintf(stderr, "[agp] Unable to allocate system texture memory. Disabling DRI.\n"); - return 0; - } - - info->auxPitch = i810_pitches[pitch_idx]; - info->auxPitchBits = i810_pitch_flags[pitch_idx]; - - return 1; -} - - -/** - * \brief Initialize the kernel data structures and enable the CP engine. - * - * \param ctx display handle. - * \param info driver private data. - * - * \return non-zero on success, or zero on failure. - * - * This function is a wrapper around the DRM_I810_CP_INIT command, passing - * all the parameters in a drmI810Init structure. - */ -static int I810DRIKernelInit( const DRIDriverContext *ctx, - I810Ptr info) -{ - int cpp = ctx->bpp / 8; - drmI810Init drmInfo; - int ret; - I810RingBuffer *ring = &(info->LpRing); - - /* This is the struct passed to the kernel module for its initialization */ - memset(&drmInfo, 0, sizeof(drmI810Init)); - - /* make sure we have at least 1.4 */ - drmInfo.func = I810_INIT_DMA_1_4; - - drmInfo.ring_start = ring->mem.Start; - drmInfo.ring_end = ring->mem.End; - drmInfo.ring_size = ring->mem.Size; - - drmInfo.mmio_offset = (unsigned int)info->regs; - drmInfo.buffers_offset = (unsigned int)info->buffer_map; - drmInfo.sarea_priv_offset = sizeof(drm_sarea_t); - - drmInfo.front_offset = 0; - drmInfo.back_offset = info->BackBuffer.Start; - drmInfo.depth_offset = info->DepthBuffer.Start; - - drmInfo.w = ctx->shared.virtualWidth; - drmInfo.h = ctx->shared.virtualHeight; - drmInfo.pitch = info->auxPitch; - drmInfo.pitch_bits = info->auxPitchBits; - - - ret = drmCommandWrite(ctx->drmFD, DRM_I810_INIT, &drmInfo, - sizeof(drmI810Init)); - - return ret >= 0; -} - - -/** - * \brief Add a map for the vertex buffers that will be accessed by any - * DRI-based clients. - * - * \param ctx display handle. - * \param info driver private data. - * - * \return one on success, or zero on failure. - * - * Calls drmAddBufs() with the previously allocated vertex buffers. - */ -static int I810DRIBufInit( const DRIDriverContext *ctx, I810Ptr info ) -{ - /* Initialize vertex buffers */ - info->bufNumBufs = drmAddBufs(ctx->drmFD, - I810_DMA_BUF_NR, - I810_DMA_BUF_SZ, - DRM_AGP_BUFFER, - info->BufferMem.Start); - - if (info->bufNumBufs <= 0) { - fprintf(stderr, - "[drm] Could not create vertex/indirect buffers list\n"); - return 0; - } - fprintf(stderr, - "[drm] Added %d %d byte vertex/indirect buffers\n", - info->bufNumBufs, I810_DMA_BUF_SZ); - - return 1; -} - -/** - * \brief Install an IRQ handler. - * - * \param ctx display handle. - * \param info driver private data. - * - * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to - * IRQ-free operation on failure. - */ -static void I810DRIIrqInit(const DRIDriverContext *ctx, - I810Ptr info) -{ - if (!info->irq) { - info->irq = drmGetInterruptFromBusID(ctx->drmFD, - ctx->pciBus, - ctx->pciDevice, - ctx->pciFunc); - - if ((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) { - fprintf(stderr, - "[drm] failure adding irq handler, " - "there is a device already using that irq\n" - "[drm] falling back to irq-free operation\n"); - info->irq = 0; - } - } - - if (info->irq) - fprintf(stderr, - "[drm] dma control initialized, using IRQ %d\n", - info->irq); -} - -static int I810CheckDRMVersion( const DRIDriverContext *ctx, - I810Ptr info ) -{ - drmVersionPtr version; - - version = drmGetVersion(ctx->drmFD); - if (version) { - int req_minor, req_patch; - - req_minor = 4; - req_patch = 0; - - i810_drm_version = (version->version_major<<16) | version->version_minor; - if (version->version_major != 1 || - version->version_minor < req_minor || - (version->version_minor == req_minor && - version->version_patchlevel < req_patch)) { - /* Incompatible drm version */ - fprintf(stderr, - "[dri] I810DRIScreenInit failed because of a version " - "mismatch.\n" - "[dri] i810.o kernel module version is %d.%d.%d " - "but version 1.%d.%d or newer is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel, - req_minor, - req_patch); - drmFreeVersion(version); - return 0; - } - - info->drmMinor = version->version_minor; - drmFreeVersion(version); - } - - return 1; -} - -static int I810MemoryInit( const DRIDriverContext *ctx, I810Ptr info ) -{ - int width_bytes = ctx->shared.virtualWidth * ctx->cpp; - int cpp = ctx->cpp; - int bufferSize = (ctx->shared.virtualHeight * width_bytes); - int depthSize = (((ctx->shared.virtualHeight+15) & ~15) * width_bytes); - int l; - - if (drmAddMap(ctx->drmFD, (drm_handle_t) info->BackBuffer.Start, - info->BackBuffer.Size, DRM_AGP, 0, - &info->backbuffer) < 0) { - fprintf(stderr, "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n"); - return 0; - } - - if (drmAddMap(ctx->drmFD, (drm_handle_t) info->DepthBuffer.Start, - info->DepthBuffer.Size, DRM_AGP, 0, - &info->depthbuffer) < 0) { - fprintf(stderr, "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n"); - return 0; - } - - if (!I810AllocLow(&(info->FrontBuffer), &(info->SysMem), (((ctx->shared.virtualHeight * width_bytes) + 4095) & ~4095))) - { - fprintf(stderr,"Framebuffer allocation failed\n"); - return 0; - } - else - fprintf(stderr,"Frame buffer at 0x%.8x (%luk, %lu bytes)\n", - info->FrontBuffer.Start, - info->FrontBuffer.Size / 1024, info->FrontBuffer.Size); - - memset(&(info->LpRing), 0, sizeof(I810RingBuffer)); - if (I810AllocLow(&(info->LpRing.mem), &(info->SysMem), 16 * 4096)) { - fprintf(stderr, - "Ring buffer at 0x%.8x (%luk, %lu bytes)\n", - info->LpRing.mem.Start, - info->LpRing.mem.Size / 1024, info->LpRing.mem.Size); - - info->LpRing.tail_mask = info->LpRing.mem.Size - 1; - info->LpRing.virtual_start = info->LpRing.mem.Start; - info->LpRing.head = 0; - info->LpRing.tail = 0; - info->LpRing.space = 0; - } else { - fprintf(stderr, "Ring buffer allocation failed\n"); - return (0); - } - - /* Allocate buffer memory */ - I810AllocHigh(&(info->BufferMem), &(info->SysMem), - I810_DMA_BUF_NR * I810_DMA_BUF_SZ); - - - fprintf(stderr, "[dri] Buffer map : %lx\n", - info->BufferMem.Start); - - if (info->BufferMem.Start == 0 || - info->BufferMem.End - info->BufferMem.Start > - I810_DMA_BUF_NR * I810_DMA_BUF_SZ) { - fprintf(stderr,"[dri] Not enough memory for dma buffers. Disabling DRI.\n"); - return 0; - } - - if (drmAddMap(ctx->drmFD, (drm_handle_t) info->BufferMem.Start, - info->BufferMem.Size, DRM_AGP, 0, &info->buffer_map) < 0) { - fprintf(stderr, "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n"); - return 0; - } - - if (drmAddMap(ctx->drmFD, (drm_handle_t) info->LpRing.mem.Start, - info->LpRing.mem.Size, DRM_AGP, 0, &info->ring_map) < 0) { - fprintf(stderr, "[drm] drmAddMap(ring_map) failed. Disabling DRI. \n"); - return 0; - } - - /* Front, back and depth buffers - everything else texture?? - */ - info->textureSize = info->SysMem.Size; - - if (info->textureSize < 0) - return 0; - - - l = I810MinBits((info->textureSize-1) / I810_NR_TEX_REGIONS); - if (l < I810_LOG_MIN_TEX_REGION_SIZE) l = I810_LOG_MIN_TEX_REGION_SIZE; - - /* Round the texture size up to the nearest whole number of - * texture regions. Again, be greedy about this, don't - * round down. - */ - info->logTextureGranularity = l; - info->textureSize = (info->textureSize >> l) << l; - - /* Set a minimum usable local texture heap size. This will fit - * two 256x256x32bpp textures. - */ - if (info->textureSize < 512 * 1024) { - info->textureOffset = 0; - info->textureSize = 0; - } - - I810AllocLow(&(info->TexMem), &(info->SysMem), info->textureSize); - - if (drmAddMap(ctx->drmFD, (drm_handle_t) info->TexMem.Start, - info->TexMem.Size, DRM_AGP, 0, &info->textures) < 0) { - fprintf(stderr, - "[drm] drmAddMap(textures) failed. Disabling DRI.\n"); - return 0; - } - - /* Reserve space for textures */ - fprintf(stderr, - "Will use back buffer at offset 0x%x\n", - info->BackOffset); - fprintf(stderr, - "Will use depth buffer at offset 0x%x\n", - info->DepthOffset); - fprintf(stderr, - "Will use %d kb for textures at offset 0x%x\n", - info->TexMem.Size/1024, info->TexMem.Start); - - return 1; -} - - - -/** - * Called at the start of each server generation. - * - * \param ctx display handle. - * \param info driver private data. - * - * \return non-zero on success, or zero on failure. - * - * Performs static frame buffer allocation. Opens the DRM device and add maps - * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more - * information. Creates a \e server context to grab the lock for the - * initialization ioctls and calls the other initilization functions in this - * file. Starts the CP engine via the DRM_I810_CP_START command. - * - * Setups a I810DRIRec structure to be passed to i810_dri.so for its - * initialization. - */ -static int I810ScreenInit( DRIDriverContext *ctx, I810Ptr info ) -{ - I810DRIPtr pI810DRI; - int err; - - usleep(100); - /*assert(!ctx->IsClient);*/ - - /* from XFree86 driver */ - info->DepthOffset = 0x3000000; - info->BackOffset = 0x3800000; - { - int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); - int maxy = ctx->shared.fbSize / width_bytes; - - - if (maxy <= ctx->shared.virtualHeight * 3) { - fprintf(stderr, - "Static buffer allocation failed -- " - "need at least %d kB video memory (have %d kB)\n", - (ctx->shared.virtualWidth * ctx->shared.virtualHeight * - ctx->cpp * 3 + 1023) / 1024, - ctx->shared.fbSize / 1024); - return 0; - } - } - - - info->regsSize = ctx->MMIOSize; - ctx->shared.SAREASize = 0x2000; - - /* Note that drmOpen will try to load the kernel module, if needed. */ - ctx->drmFD = drmOpen("i810", NULL ); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - - if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - if (drmAddMap( ctx->drmFD, - 0, - ctx->shared.SAREASize, - DRM_SHM, - DRM_CONTAINS_LOCK, - &ctx->shared.hSAREA) < 0) - { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap( ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - } - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - if (drmAddMap(ctx->drmFD, - ctx->MMIOStart, - ctx->MMIOSize, - DRM_REGISTERS, - DRM_READ_ONLY, - &info->regs) < 0) { - fprintf(stderr, "[drm] drmAddMap mmio failed\n"); - return 0; - } - fprintf(stderr, - "[drm] register handle = 0x%08x\n", info->regs); - - I810DRIAgpPreInit(ctx, info); - /* Need to AddMap the framebuffer and mmio regions here: - */ - if (drmAddMap( ctx->drmFD, - (drm_handle_t)ctx->FBStart, - ctx->FBSize, - DRM_FRAME_BUFFER, -#ifndef _EMBEDDED - 0, -#else - DRM_READ_ONLY, -#endif - &ctx->shared.hFrameBuffer) < 0) - { - fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); - return 0; - } - - fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", - ctx->shared.hFrameBuffer); - - /* Check the i810 DRM version */ - if (!I810CheckDRMVersion(ctx, info)) { - return 0; - } - - /* Initialize AGP */ - if (!I810DRIAgpInit(ctx, info)) { - return 0; - } - - - /* Memory manager setup */ - if (!I810MemoryInit(ctx, info)) { - return 0; - } - - /* Initialize the SAREA private data structure */ - { - I810SAREAPtr pSAREAPriv; - pSAREAPriv = (I810SAREAPtr)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); - // pSAREAPriv->pf_enabled=1; - } - - - /* Create a 'server' context so we can grab the lock for - * initialization ioctls. - */ - if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return 0; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - /* Initialize the vertex buffers list */ - if (!I810DRIBufInit(ctx, info)) { - fprintf(stderr, "I810DRIBufInit failed\n"); - DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); - return 0; - } - - /* Initialize the kernel data structures */ - if (!I810DRIKernelInit(ctx, info)) { - fprintf(stderr, "I810DRIKernelInit failed\n"); - DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); - return 0; - } - - /* Initialize IRQ */ - I810DRIIrqInit(ctx, info); - - /* Quick hack to clear the front & back buffers. Could also use - * the clear ioctl to do this, but would need to setup hw state - * first. - */ -#if 0 - memset((char *)ctx->FBAddress, - 0, - info->auxPitch * ctx->cpp * ctx->shared.virtualHeight ); - - memset((char *)info->backbuffer, - 0, - info->auxPitch * ctx->cpp * ctx->shared.virtualHeight ); -#endif - - /* This is the struct passed to i810_dri.so for its initialization */ - ctx->driverClientMsg = malloc(sizeof(I810DRIRec)); - ctx->driverClientMsgSize = sizeof(I810DRIRec); - pI810DRI = (I810DRIPtr)ctx->driverClientMsg; - - pI810DRI->regs = info->regs; - pI810DRI->regsSize = info->regsSize; - // regsMap is unused - - pI810DRI->backbufferSize = info->BackBuffer.Size; - pI810DRI->backbuffer = info->backbuffer; - - pI810DRI->depthbufferSize = info->DepthBuffer.Size; - pI810DRI->depthbuffer = info->depthbuffer; - - pI810DRI->textures = info->textures; - pI810DRI->textureSize = info->textureSize; - - pI810DRI->agp_buffers = info->buffer_map; - pI810DRI->agp_buf_size = info->BufferMem.Size; - - pI810DRI->deviceID = info->Chipset; - pI810DRI->width = ctx->shared.virtualWidth; - pI810DRI->height = ctx->shared.virtualHeight; - pI810DRI->mem = ctx->shared.fbSize; - pI810DRI->cpp = ctx->bpp / 8; - pI810DRI->bitsPerPixel = ctx->bpp; - pI810DRI->fbOffset = info->FrontBuffer.Start; - pI810DRI->fbStride = info->auxPitch; - - pI810DRI->backOffset = info->BackBuffer.Start; - pI810DRI->depthOffset = info->DepthBuffer.Start; - - pI810DRI->auxPitch = info->auxPitch; - pI810DRI->auxPitchBits = info->auxPitchBits; - - pI810DRI->logTextureGranularity = info->logTextureGranularity; - pI810DRI->textureOffset = info->TexMem.Start; - - pI810DRI->ringOffset = info->LpRing.mem.Start; - pI810DRI->ringSize = info->LpRing.mem.Size; - - // drmBufs looks unused - pI810DRI->irq = info->irq; - pI810DRI->sarea_priv_offset = sizeof(drm_sarea_t); - - /* Don't release the lock now - let the VT switch handler do it. */ - return 1; -} - - -/** - * \brief Validate the fbdev mode. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Saves some registers and returns 1. - * - * \sa i810ValidateMode(). - */ -static int i810ValidateMode( const DRIDriverContext *ctx ) -{ - unsigned char *I810MMIO = ctx->MMIOAddress; - I810Ptr info = ctx->driverPrivate; - - return 1; -} - - -/** - * \brief Examine mode returned by fbdev. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Restores registers that fbdev has clobbered and returns 1. - * - * \sa i810ValidateMode(). - */ -static int i810PostValidateMode( const DRIDriverContext *ctx ) -{ - unsigned char *I810MMIO = ctx->MMIOAddress; - I810Ptr info = ctx->driverPrivate; - - return 1; -} - - -/** - * \brief Initialize the framebuffer device mode - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Fills in \p info with some default values and some information from \p ctx - * and then calls I810ScreenInit() for the screen initialization. - * - * Before exiting clears the framebuffer memory accessing it directly. - */ -static int i810InitFBDev( DRIDriverContext *ctx ) -{ - I810Ptr info = calloc(1, sizeof(*info)); - - { - int dummy = ctx->shared.virtualWidth; - - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; - } - - ctx->shared.virtualWidth = dummy; - } - - ctx->driverPrivate = (void *)info; - - info->Chipset = ctx->chipset; - - if (!I810ScreenInit( ctx, info )) - return 0; - - - return 1; -} - - -/** - * \brief The screen is being closed, so clean up any state and free any - * resources used by the DRI. - * - * \param ctx display handle. - * - * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver - * private data. - */ -static void i810HaltFBDev( DRIDriverContext *ctx ) -{ - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = 0; - } -} - - -extern void i810NotifyFocus( int ); - -/** - * \brief Exported driver interface for Mini GLX. - * - * \sa DRIDriverRec. - */ -const struct DRIDriverRec __driDriver = { - i810ValidateMode, - i810PostValidateMode, - i810InitFBDev, - i810HaltFBDev, - I810EngineShutdown, - I810EngineRestore, -#ifndef _EMBEDDED - 0, -#else - i810NotifyFocus, -#endif -}; diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile index dc15ae425c9..5b49d0c77c6 100644 --- a/src/mesa/drivers/dri/i915/Makefile +++ b/src/mesa/drivers/dri/i915/Makefile @@ -4,8 +4,6 @@ include $(TOP)/configs/current LIBNAME = i915_dri.so -MINIGLX_SOURCES = server/intel_dri.c - DRIVER_SOURCES = \ i830_context.c \ i830_state.c \ diff --git a/src/mesa/drivers/dri/i915/server/intel_dri.c b/src/mesa/drivers/dri/i915/server/intel_dri.c deleted file mode 120000 index effdd26448a..00000000000 --- a/src/mesa/drivers/dri/i915/server/intel_dri.c +++ /dev/null @@ -1 +0,0 @@ -../../intel/server/intel_dri.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile index f98a1a27db2..842d4b7aa10 100644 --- a/src/mesa/drivers/dri/i965/Makefile +++ b/src/mesa/drivers/dri/i965/Makefile @@ -54,6 +54,7 @@ DRIVER_SOURCES = \ brw_gs_emit.c \ brw_gs_state.c \ brw_misc_state.c \ + brw_optimize.c \ brw_program.c \ brw_queryobj.c \ brw_sf.c \ @@ -99,7 +100,6 @@ DRIVER_SOURCES = \ C_SOURCES = \ $(COMMON_SOURCES) \ - $(MINIGLX_SOURCES) \ $(DRIVER_SOURCES) ASM_SOURCES = diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index a512896f315..241193c3579 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -156,6 +156,7 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis, brw->has_surface_tile_offset = GL_TRUE; brw->has_compr4 = GL_TRUE; brw->has_aa_line_parameters = GL_TRUE; + brw->has_pln = GL_TRUE; } else { brw->CMD_VF_STATISTICS = CMD_VF_STATISTICS_965; brw->CMD_PIPELINE_SELECT = CMD_PIPELINE_SELECT_965; diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index d6fc37e4d89..2855c93ea66 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -446,6 +446,7 @@ struct brw_context GLboolean has_compr4; GLboolean has_negative_rhw_bug; GLboolean has_aa_line_parameters; + GLboolean has_pln; ; struct { struct brw_state_flags dirty; diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index bb1b5f5ef03..984e56d00c8 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -550,6 +550,7 @@ #define BRW_OPCODE_DP2 87 #define BRW_OPCODE_DPA2 88 #define BRW_OPCODE_LINE 89 +#define BRW_OPCODE_PLN 90 #define BRW_OPCODE_NOP 126 #define BRW_PREDICATE_NONE 0 diff --git a/src/mesa/drivers/dri/i965/brw_disasm.c b/src/mesa/drivers/dri/i965/brw_disasm.c index a8f6b993ac3..ad61770212c 100644 --- a/src/mesa/drivers/dri/i965/brw_disasm.c +++ b/src/mesa/drivers/dri/i965/brw_disasm.c @@ -50,6 +50,7 @@ struct { [BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 }, [BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 }, [BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_PLN] = { .name = "pln", .nsrc = 2, .ndst = 1 }, [BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 }, [BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 }, [BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 }, @@ -73,10 +74,10 @@ struct { [BRW_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 }, [BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 1, .ndst = 0 }, [BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 }, - [BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 1, .ndst = 01 }, - [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 2, .ndst = 0 }, [BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 }, - [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 2, .ndst = 0 }, [BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 }, [BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 }, [BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 }, diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h index 39eb88d7c2b..4f55158e8f3 100644 --- a/src/mesa/drivers/dri/i965/brw_eu.h +++ b/src/mesa/drivers/dri/i965/brw_eu.h @@ -795,6 +795,7 @@ ALU2(DPH) ALU2(DP3) ALU2(DP2) ALU2(LINE) +ALU2(PLN) #undef ALU1 #undef ALU2 @@ -965,4 +966,9 @@ void brw_math_invert( struct brw_compile *p, void brw_set_src1( struct brw_instruction *insn, struct brw_reg reg ); + + +/* brw_optimize.c */ +void brw_optimize(struct brw_compile *p); + #endif diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c index 82f2fdab2fc..d2395dec288 100644 --- a/src/mesa/drivers/dri/i965/brw_eu_emit.c +++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c @@ -573,7 +573,7 @@ ALU2(DPH) ALU2(DP3) ALU2(DP2) ALU2(LINE) - +ALU2(PLN) diff --git a/src/mesa/drivers/dri/i965/brw_optimize.c b/src/mesa/drivers/dri/i965/brw_optimize.c new file mode 100644 index 00000000000..57df9ea1151 --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_optimize.c @@ -0,0 +1,115 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <[email protected]> + * + */ + +#include "main/macros.h" +#include "shader/program.h" +#include "shader/prog_parameter.h" +#include "shader/prog_print.h" +#include "brw_context.h" +#include "brw_defines.h" +#include "brw_eu.h" + +static GLboolean +is_single_channel_dp4(struct brw_instruction *insn) +{ + if (insn->header.opcode != BRW_OPCODE_DP4 || + insn->header.execution_size != BRW_EXECUTE_8 || + insn->header.access_mode != BRW_ALIGN_16 || + insn->bits1.da1.dest_reg_file != BRW_GENERAL_REGISTER_FILE) + return GL_FALSE; + + if (!is_power_of_two(insn->bits1.da16.dest_writemask)) + return GL_FALSE; + + return GL_TRUE; +} + +/** + * Sets the dependency control fields on DP4 instructions. + * + * The hardware only tracks dependencies on a register basis, so when + * you do: + * + * DP4 dst.x src1 src2 + * DP4 dst.y src1 src3 + * DP4 dst.z src1 src4 + * DP4 dst.w src1 src5 + * + * It will wait to do the DP4 dst.y until the dst.x is resolved, etc. + * We can examine our instruction stream and set the dependency + * control fields to tell the hardware when to do it. + * + * We may want to extend this to other instructions that are used to + * fill in a channel at a time of the destination register. + */ +static void +brw_set_dp4_dependency_control(struct brw_compile *p) +{ + int i; + + for (i = 1; i < p->nr_insn; i++) { + struct brw_instruction *insn = &p->store[i]; + struct brw_instruction *prev = &p->store[i - 1]; + + if (!is_single_channel_dp4(prev)) + continue; + + if (!is_single_channel_dp4(insn)) { + i++; + continue; + } + + /* Only avoid hw dep control if the write masks are different + * channels of one reg. + */ + if (insn->bits1.da16.dest_writemask == prev->bits1.da16.dest_writemask) + continue; + if (insn->bits1.da16.dest_reg_nr != prev->bits1.da16.dest_reg_nr) + continue; + + /* Check if the second instruction depends on the previous one + * for a src. + */ + if (insn->bits1.da1.src0_reg_file == BRW_GENERAL_REGISTER_FILE && + (insn->bits2.da1.src0_address_mode != BRW_ADDRESS_DIRECT || + insn->bits2.da1.src0_reg_nr == insn->bits1.da16.dest_reg_nr)) + continue; + if (insn->bits1.da1.src1_reg_file == BRW_GENERAL_REGISTER_FILE && + (insn->bits3.da1.src1_address_mode != BRW_ADDRESS_DIRECT || + insn->bits3.da1.src1_reg_nr == insn->bits1.da16.dest_reg_nr)) + continue; + + prev->header.dependency_control |= BRW_DEPENDENCY_NOTCLEARED; + insn->header.dependency_control |= BRW_DEPENDENCY_NOTCHECKED; + } +} + +void +brw_optimize(struct brw_compile *p) +{ + brw_set_dp4_dependency_control(p); +} diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index a48804a660f..14c3b936b7e 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -1825,6 +1825,8 @@ void brw_vs_emit(struct brw_vs_compile *c ) post_vs_emit(c, end_inst, last_inst); + brw_optimize(p); + if (INTEL_DEBUG & DEBUG_VS) { int i; diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c index c7d87b9d94c..1869fd06d5a 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_emit.c +++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c @@ -34,6 +34,23 @@ #include "brw_context.h" #include "brw_wm.h" +static GLboolean can_do_pln(struct intel_context *intel, + const struct brw_reg *deltas) +{ + struct brw_context *brw = brw_context(&intel->ctx); + + if (!brw->has_pln) + return GL_FALSE; + + if (deltas[1].nr != deltas[0].nr + 1) + return GL_FALSE; + + if (intel->gen < 6 && ((deltas[0].nr & 1) != 0)) + return GL_FALSE; + + return GL_TRUE; +} + /* Not quite sure how correct this is - need to understand horiz * vs. vertical strides a little better. */ @@ -45,7 +62,13 @@ static INLINE struct brw_reg sechalf( struct brw_reg reg ) } -/* Payload R0: +/** + * Computes the screen-space x,y position of the pixels. + * + * This will be used by emit_delta_xy() or emit_wpos_xy() for + * interpolation of attributes.. + * + * Payload R0: * * R0.0 -- pixel mask, one bit for each of 4 pixels in 4 tiles, * corresponding to each of the 16 execution channels. @@ -60,7 +83,6 @@ static INLINE struct brw_reg sechalf( struct brw_reg reg ) * R1.7 -- ? * R1.8 -- ? */ - void emit_pixel_xy(struct brw_wm_compile *c, const struct brw_reg *dst, GLuint mask) @@ -100,7 +122,14 @@ void emit_pixel_xy(struct brw_wm_compile *c, brw_pop_insn_state(p); } - +/** + * Computes the screen-space x,y distance of the pixels from the start + * vertex. + * + * This will be used in linterp or pinterp with the start vertex value + * and the Cx, Cy, and C0 coefficients passed in from the setup engine + * to produce interpolated attribute values. + */ void emit_delta_xy(struct brw_compile *p, const struct brw_reg *dst, GLuint mask, @@ -108,25 +137,27 @@ void emit_delta_xy(struct brw_compile *p, { struct brw_reg r1 = brw_vec1_grf(1, 0); - /* Calc delta X,Y by subtracting origin in r1 from the pixel - * centers. - */ - if (mask & WRITEMASK_X) { - brw_ADD(p, - dst[0], - retype(arg0[0], BRW_REGISTER_TYPE_UW), - negate(r1)); - } + if (mask == 0) + return; - if (mask & WRITEMASK_Y) { - brw_ADD(p, - dst[1], - retype(arg0[1], BRW_REGISTER_TYPE_UW), - negate(suboffset(r1,1))); + assert(mask == WRITEMASK_XY); - } + /* Calc delta X,Y by subtracting origin in r1 from the pixel + * centers produced by emit_pixel_xy(). + */ + brw_ADD(p, + dst[0], + retype(arg0[0], BRW_REGISTER_TYPE_UW), + negate(r1)); + brw_ADD(p, + dst[1], + retype(arg0[1], BRW_REGISTER_TYPE_UW), + negate(suboffset(r1,1))); } +/** + * Computes the pixel offset from the window origin for gl_FragCoord(). + */ void emit_wpos_xy(struct brw_wm_compile *c, const struct brw_reg *dst, GLuint mask, @@ -134,9 +165,6 @@ void emit_wpos_xy(struct brw_wm_compile *c, { struct brw_compile *p = &c->func; - /* Calculate the pixel offset from window bottom left into destination - * X and Y channels. - */ if (mask & WRITEMASK_X) { if (c->fp->program.PixelCenterInteger) { /* X' = X */ @@ -186,6 +214,7 @@ void emit_pixel_w(struct brw_wm_compile *c, const struct brw_reg *deltas) { struct brw_compile *p = &c->func; + struct intel_context *intel = &p->brw->intel; /* Don't need this if all you are doing is interpolating color, for * instance. @@ -196,8 +225,12 @@ void emit_pixel_w(struct brw_wm_compile *c, /* Calc 1/w - just linterp wpos[3] optimized by putting the * result straight into a message reg. */ - brw_LINE(p, brw_null_reg(), interp3, deltas[0]); - brw_MAC(p, brw_message_reg(2), suboffset(interp3, 1), deltas[1]); + if (can_do_pln(intel, deltas)) { + brw_PLN(p, brw_message_reg(2), interp3, deltas[0]); + } else { + brw_LINE(p, brw_null_reg(), interp3, deltas[0]); + brw_MAC(p, brw_message_reg(2), suboffset(interp3, 1), deltas[1]); + } /* Calc w */ if (c->dispatch_width == 16) { @@ -224,6 +257,7 @@ void emit_linterp(struct brw_compile *p, const struct brw_reg *arg0, const struct brw_reg *deltas) { + struct intel_context *intel = &p->brw->intel; struct brw_reg interp[4]; GLuint nr = arg0[0].nr; GLuint i; @@ -235,8 +269,12 @@ void emit_linterp(struct brw_compile *p, for (i = 0; i < 4; i++) { if (mask & (1<<i)) { - brw_LINE(p, brw_null_reg(), interp[i], deltas[0]); - brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]); + if (can_do_pln(intel, deltas)) { + brw_PLN(p, dst[i], interp[i], deltas[0]); + } else { + brw_LINE(p, brw_null_reg(), interp[i], deltas[0]); + brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]); + } } } } @@ -249,6 +287,7 @@ void emit_pinterp(struct brw_compile *p, const struct brw_reg *deltas, const struct brw_reg *w) { + struct intel_context *intel = &p->brw->intel; struct brw_reg interp[4]; GLuint nr = arg0[0].nr; GLuint i; @@ -260,8 +299,12 @@ void emit_pinterp(struct brw_compile *p, for (i = 0; i < 4; i++) { if (mask & (1<<i)) { - brw_LINE(p, brw_null_reg(), interp[i], deltas[0]); - brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]); + if (can_do_pln(intel, deltas)) { + brw_PLN(p, dst[i], interp[i], deltas[0]); + } else { + brw_LINE(p, brw_null_reg(), interp[i], deltas[0]); + brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]); + } } } for (i = 0; i < 4; i++) { @@ -601,14 +644,10 @@ void emit_max(struct brw_compile *p, for (i = 0; i < 4; i++) { if (mask & (1<<i)) { - brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); - brw_MOV(p, dst[i], arg0[i]); - brw_set_saturate(p, 0); - - brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], arg1[i]); + brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_GE, arg0[i], arg1[i]); brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); - brw_MOV(p, dst[i], arg1[i]); + brw_SEL(p, dst[i], arg0[i], arg1[i]); brw_set_saturate(p, 0); brw_set_predicate_control_flag_value(p, 0xff); } @@ -625,14 +664,10 @@ void emit_min(struct brw_compile *p, for (i = 0; i < 4; i++) { if (mask & (1<<i)) { - brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); - brw_MOV(p, dst[i], arg1[i]); - brw_set_saturate(p, 0); - brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], arg1[i]); brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); - brw_MOV(p, dst[i], arg0[i]); + brw_SEL(p, dst[i], arg0[i], arg1[i]); brw_set_saturate(p, 0); brw_set_predicate_control_flag_value(p, 0xff); } @@ -1086,11 +1121,19 @@ static void emit_kil( struct brw_wm_compile *c, { struct brw_compile *p = &c->func; struct brw_reg r0uw = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW); - GLuint i; - - /* XXX - usually won't need 4 compares! - */ + GLuint i, j; + for (i = 0; i < 4; i++) { + /* Check if we've already done the comparison for this reg + * -- common when someone does KIL TEMP.wwww. + */ + for (j = 0; j < i; j++) { + if (memcmp(&arg0[j], &arg0[i], sizeof(arg0[0])) == 0) + break; + } + if (j != i) + continue; + brw_push_insn_state(p); brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_GE, arg0[i], brw_imm_f(0)); brw_set_predicate_control_flag_value(p, 0xff); diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c index 315b030484f..0b66cc6c9f3 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c +++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c @@ -289,6 +289,7 @@ reclaim_temps(struct brw_wm_compile *c) */ static void prealloc_reg(struct brw_wm_compile *c) { + struct intel_context *intel = &c->func.brw->intel; int i, j; struct brw_reg reg; int urb_read_length = 0; @@ -413,6 +414,43 @@ static void prealloc_reg(struct brw_wm_compile *c) } } + for (i = 0; i < c->nr_fp_insns; i++) { + const struct prog_instruction *inst = &c->prog_instructions[i]; + + switch (inst->Opcode) { + case WM_DELTAXY: + /* Allocate WM_DELTAXY destination on G45/GM45 to an + * even-numbered GRF if possible so that we can use the PLN + * instruction. + */ + if (inst->DstReg.WriteMask == WRITEMASK_XY && + !c->wm_regs[inst->DstReg.File][inst->DstReg.Index][0].inited && + !c->wm_regs[inst->DstReg.File][inst->DstReg.Index][1].inited && + (IS_G4X(intel->intelScreen->deviceID) || intel->gen == 5)) { + int grf; + + for (grf = c->first_free_grf & ~1; + grf < BRW_WM_MAX_GRF; + grf += 2) + { + if (!c->used_grf[grf] && !c->used_grf[grf + 1]) { + c->used_grf[grf] = GL_TRUE; + c->used_grf[grf + 1] = GL_TRUE; + c->first_free_grf = grf + 2; /* a guess */ + + set_reg(c, inst->DstReg.File, inst->DstReg.Index, 0, + brw_vec8_grf(grf, 0)); + set_reg(c, inst->DstReg.File, inst->DstReg.Index, 1, + brw_vec8_grf(grf + 1, 0)); + break; + } + } + } + default: + break; + } + } + /* An instruction may reference up to three constants. * They'll be found in these registers. * XXX alloc these on demand! @@ -2029,8 +2067,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) } break; default: - printf("unsupported IR in fragment shader %d\n", - inst->Opcode); + printf("unsupported opcode %d (%s) in fragment shader\n", + inst->Opcode, inst->Opcode < MAX_OPCODE ? + _mesa_opcode_string(inst->Opcode) : "unknown"); } /* Release temporaries containing any unaliased source regs. */ diff --git a/src/mesa/drivers/dri/i965/server/intel_dri.c b/src/mesa/drivers/dri/i965/server/intel_dri.c deleted file mode 120000 index effdd26448a..00000000000 --- a/src/mesa/drivers/dri/i965/server/intel_dri.c +++ /dev/null @@ -1 +0,0 @@ -../../intel/server/intel_dri.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 4f14946ec72..da17809f16c 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -525,7 +525,8 @@ intel_miptree_image_copy(struct intel_context *intel, intel_miptree_get_image_offset(dst, level, face, i, &dst_x, &dst_y); success = intel_region_copy(intel, dst->region, 0, dst_x, dst_y, - src->region, 0, src_x, src_y, width, height, + src->region, 0, src_x, src_y, + width, height, GL_FALSE, GL_COPY); if (!success) { GLubyte *src_ptr, *dst_ptr; diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c index f4f3fd6d889..8efb7a60c26 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c @@ -116,6 +116,7 @@ do_blit_copypixels(GLcontext * ctx, GLint orig_dsty; GLint orig_srcx; GLint orig_srcy; + GLboolean flip = GL_FALSE; if (type == GL_DEPTH || type == GL_STENCIL) { if (INTEL_DEBUG & DEBUG_FALLBACKS) @@ -140,8 +141,6 @@ do_blit_copypixels(GLcontext * ctx, intel_prepare_render(intel); - /* XXX: We fail to handle different inversion between read and draw framebuffer. */ - /* Clip to destination buffer. */ orig_dstx = dstx; orig_dsty = dsty; @@ -164,23 +163,23 @@ do_blit_copypixels(GLcontext * ctx, dstx += srcx - orig_srcx; dsty += srcy - orig_srcy; - /* Convert from GL to hardware coordinates: */ + /* Flip dest Y if it's a window system framebuffer. */ if (fb->Name == 0) { - /* copypixels to a system framebuffer */ + /* copypixels to a window system framebuffer */ dsty = fb->Height - dsty - height; - } else { - /* copypixels to a user framebuffer object */ - dsty = dsty; + flip = !flip; } - /* Flip source Y if it's a system framebuffer. */ - if (read_fb->Name == 0) - srcy = fb->Height - srcy - height; + /* Flip source Y if it's a window system framebuffer. */ + if (read_fb->Name == 0) { + srcy = read_fb->Height - srcy - height; + flip = !flip; + } if (!intel_region_copy(intel, dst, 0, dstx, dsty, src, 0, srcx, srcy, - width, height, + width, height, flip, ctx->Color.ColorLogicOpEnabled ? ctx->Color.LogicOp : GL_COPY)) { DBG("%s: blit failure\n", __FUNCTION__); diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index f042bcbc28c..f8107bd0615 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -380,8 +380,11 @@ intel_region_copy(struct intel_context *intel, struct intel_region *src, GLuint src_offset, GLuint srcx, GLuint srcy, GLuint width, GLuint height, + GLboolean flip, GLenum logicop) { + uint32_t src_pitch = src->pitch; + _DBG("%s\n", __FUNCTION__); if (intel == NULL) @@ -397,9 +400,12 @@ intel_region_copy(struct intel_context *intel, assert(src->cpp == dst->cpp); + if (flip) + src_pitch = -src_pitch; + return intelEmitCopyBlit(intel, dst->cpp, - src->pitch, src->buffer, src_offset, src->tiling, + src_pitch, src->buffer, src_offset, src->tiling, dst->pitch, dst->buffer, dst_offset, dst->tiling, srcx, srcy, dstx, dsty, width, height, logicop); diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h index 7ee6a988eae..8f32449f345 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.h +++ b/src/mesa/drivers/dri/intel/intel_regions.h @@ -122,6 +122,7 @@ intel_region_copy(struct intel_context *intel, struct intel_region *src, GLuint src_offset, GLuint srcx, GLuint srcy, GLuint width, GLuint height, + GLboolean flip, GLenum logicop); /* Helpers for zerocopy uploads, particularly texture image uploads: diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 6e4bb643651..5e3f40836d0 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -312,18 +312,13 @@ intelCreateBuffer(__DRIscreen * driScrnPriv, } if (mesaVis->depthBits == 24) { - if (mesaVis->stencilBits == 8) { - /* combined depth/stencil buffer */ - struct intel_renderbuffer *depthStencilRb - = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); - /* note: bind RB to two attachment points */ - _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); - _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); - } else { - struct intel_renderbuffer *depthRb - = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); - _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); - } + assert(mesaVis->stencilBits == 8); + /* combined depth/stencil buffer */ + struct intel_renderbuffer *depthStencilRb + = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); + /* note: bind RB to two attachment points */ + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); } else if (mesaVis->depthBits == 16) { /* just 16-bit depth buffer, no hw stencil */ diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index fb5c01bc4dc..377f3a8627e 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -48,11 +48,11 @@ intel_set_span_functions(struct intel_context *intel, #define LOCAL_VARS \ struct intel_renderbuffer *irb = intel_renderbuffer(rb); \ - const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \ - const GLint yBias = ctx->DrawBuffer->Name ? 0 : irb->Base.Height - 1;\ + const GLint yScale = rb->Name ? 1 : -1; \ + const GLint yBias = rb->Name ? 0 : rb->Height - 1; \ int minx = 0, miny = 0; \ - int maxx = ctx->DrawBuffer->Width; \ - int maxy = ctx->DrawBuffer->Height; \ + int maxx = rb->Width; \ + int maxy = rb->Height; \ int pitch = irb->region->pitch * irb->region->cpp; \ void *buf = irb->region->buffer->virtual; \ GLuint p; \ @@ -108,11 +108,11 @@ intel_set_span_functions(struct intel_context *intel, #define LOCAL_DEPTH_VARS \ struct intel_renderbuffer *irb = intel_renderbuffer(rb); \ - const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \ - const GLint yBias = ctx->DrawBuffer->Name ? 0 : irb->Base.Height - 1;\ + const GLint yScale = rb->Name ? 1 : -1; \ + const GLint yBias = rb->Name ? 0 : rb->Height - 1; \ int minx = 0, miny = 0; \ - int maxx = ctx->DrawBuffer->Width; \ - int maxy = ctx->DrawBuffer->Height; \ + int maxx = rb->Width; \ + int maxy = rb->Height; \ int pitch = irb->region->pitch * irb->region->cpp; \ void *buf = irb->region->buffer->virtual; \ (void)buf; (void)pitch; /* unused for non-gttmap. */ \ diff --git a/src/mesa/drivers/dri/intel/server/intel_dri.c b/src/mesa/drivers/dri/intel/server/intel_dri.c deleted file mode 100644 index e49c4214ad4..00000000000 --- a/src/mesa/drivers/dri/intel/server/intel_dri.c +++ /dev/null @@ -1,1306 +0,0 @@ -/** - * \file server/intel_dri.c - * \brief File to perform the device-specific initialization tasks typically - * done in the X server. - * - * Here they are converted to run in the client (or perhaps a standalone - * process), and to work with the frame buffer device rather than the X - * server infrastructure. - * - * Copyright (C) 2006 Dave Airlie ([email protected]) - - 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 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. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include "driver.h" -#include "drm.h" - -#include "intel.h" -#include "i830_dri.h" - -#include "memops.h" -#include "pciaccess.h" - -static size_t drm_page_size; -static int nextTile = 0; -#define xf86DrvMsg(...) do {} while(0) - -static const int pitches[] = { - 128 * 8, - 128 * 16, - 128 * 32, - 128 * 64, - 0 -}; - -static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea); - -static unsigned long -GetBestTileAlignment(unsigned long size) -{ - unsigned long i; - - for (i = KB(512); i < size; i <<= 1) - ; - - if (i > MB(64)) - i = MB(64); - - return i; -} - -static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830) -{ - int i; - unsigned char *MMIO = ctx->MMIOAddress; - - for (i = 0; i < 8; i++) { - OUTREG(FENCE + i * 4, pI830->Fence[i]); - // if (I810_DEBUG & DEBUG_VERBOSE_VGA) - fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]); - } -} - -/* Tiled memory is good... really, really good... - * - * Need to make it less likely that we miss out on this - probably - * need to move the frontbuffer away from the 'guarenteed' alignment - * of the first memory segment, or perhaps allocate a discontigous - * framebuffer to get more alignment 'sweet spots'. - */ -static void -SetFence(const DRIDriverContext *ctx, I830Rec *pI830, - int nr, unsigned int start, unsigned int pitch, - unsigned int size) -{ - unsigned int val; - unsigned int fence_mask = 0; - unsigned int fence_pitch; - - if (nr < 0 || nr > 7) { - fprintf(stderr, - "SetFence: fence %d out of range\n",nr); - return; - } - - pI830->Fence[nr] = 0; - - if (IS_I9XX(pI830)) - fence_mask = ~I915G_FENCE_START_MASK; - else - fence_mask = ~I830_FENCE_START_MASK; - - if (start & fence_mask) { - fprintf(stderr, - "SetFence: %d: start (0x%08x) is not %s aligned\n", - nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k"); - return; - } - - if (start % size) { - fprintf(stderr, - "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n", - nr, start, size / 1024); - return; - } - - if (pitch & 127) { - fprintf(stderr, - "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n", - nr, pitch); - return; - } - - val = (start | FENCE_X_MAJOR | FENCE_VALID); - - if (IS_I9XX(pI830)) { - switch (size) { - case MB(1): - val |= I915G_FENCE_SIZE_1M; - break; - case MB(2): - val |= I915G_FENCE_SIZE_2M; - break; - case MB(4): - val |= I915G_FENCE_SIZE_4M; - break; - case MB(8): - val |= I915G_FENCE_SIZE_8M; - break; - case MB(16): - val |= I915G_FENCE_SIZE_16M; - break; - case MB(32): - val |= I915G_FENCE_SIZE_32M; - break; - case MB(64): - val |= I915G_FENCE_SIZE_64M; - break; - default: - fprintf(stderr, - "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); - return; - } - } else { - switch (size) { - case KB(512): - val |= FENCE_SIZE_512K; - break; - case MB(1): - val |= FENCE_SIZE_1M; - break; - case MB(2): - val |= FENCE_SIZE_2M; - break; - case MB(4): - val |= FENCE_SIZE_4M; - break; - case MB(8): - val |= FENCE_SIZE_8M; - break; - case MB(16): - val |= FENCE_SIZE_16M; - break; - case MB(32): - val |= FENCE_SIZE_32M; - break; - case MB(64): - val |= FENCE_SIZE_64M; - break; - default: - fprintf(stderr, - "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); - return; - } - } - - if (IS_I9XX(pI830)) - fence_pitch = pitch / 512; - else - fence_pitch = pitch / 128; - - switch (fence_pitch) { - case 1: - val |= FENCE_PITCH_1; - break; - case 2: - val |= FENCE_PITCH_2; - break; - case 4: - val |= FENCE_PITCH_4; - break; - case 8: - val |= FENCE_PITCH_8; - break; - case 16: - val |= FENCE_PITCH_16; - break; - case 32: - val |= FENCE_PITCH_32; - break; - case 64: - val |= FENCE_PITCH_64; - break; - default: - fprintf(stderr, - "SetFence: %d: illegal pitch (%d)\n", nr, pitch); - return; - } - - pI830->Fence[nr] = val; -} - -static Bool -MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem) -{ - int pitch, ntiles, i; - - pitch = pMem->Pitch * ctx->cpp; - /* - * Simply try to break the region up into at most four pieces of size - * equal to the alignment. - */ - ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment; - if (ntiles >= 4) { - return FALSE; - } - - for (i = 0; i < ntiles; i++, nextTile++) { - SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment, - pitch, pMem->Alignment); - } - return TRUE; -} - -static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830) -{ - int i; - - /* Clear out */ - for (i = 0; i < 8; i++) - pI830->Fence[i] = 0; - - nextTile = 0; - - if (pI830->BackBuffer.Alignment >= KB(512)) { - if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) { - fprintf(stderr, - "Activating tiled memory for the back buffer.\n"); - } else { - fprintf(stderr, - "MakeTiles failed for the back buffer.\n"); - pI830->allowPageFlip = FALSE; - } - } - - if (pI830->DepthBuffer.Alignment >= KB(512)) { - if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) { - fprintf(stderr, - "Activating tiled memory for the depth buffer.\n"); - } else { - fprintf(stderr, - "MakeTiles failed for the depth buffer.\n"); - } - } - - return; -} - -static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830) -{ - struct pci_device host_bridge, ig_dev; - uint32_t gmch_ctrl; - int memsize = 0; - int range; - uint32_t aper_size; - uint32_t membase2 = 0; - - memset(&host_bridge, 0, sizeof(host_bridge)); - memset(&ig_dev, 0, sizeof(ig_dev)); - - ig_dev.dev = 2; - - pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL); - - if (IS_I830(pI830) || IS_845G(pI830)) { - if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { - aper_size = 0x80000000; - } else { - aper_size = 0x40000000; - } - } else { - if (IS_I9XX(pI830)) { - int ret; - ret = pci_device_cfg_read_u32(&ig_dev, &membase2, 0x18); - if (membase2 & 0x08000000) - aper_size = 0x8000000; - else - aper_size = 0x10000000; - - fprintf(stderr,"aper size is %08X %08x %d\n", aper_size, membase2, ret); - } else - aper_size = 0x8000000; - } - - pI830->aper_size = aper_size; - - - /* We need to reduce the stolen size, by the GTT and the popup. - * The GTT varying according the the FbMapSize and the popup is 4KB */ - range = (ctx->shared.fbSize / (1024*1024)) + 4; - - if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I855_GMCH_GMS_STOLEN_1M: - memsize = MB(1) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_4M: - memsize = MB(4) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_8M: - memsize = MB(8) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_16M: - memsize = MB(16) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_32M: - memsize = MB(32) - KB(range); - break; - case I915G_GMCH_GMS_STOLEN_48M: - if (IS_I9XX(pI830)) - memsize = MB(48) - KB(range); - break; - case I915G_GMCH_GMS_STOLEN_64M: - if (IS_I9XX(pI830)) - memsize = MB(64) - KB(range); - break; - } - } else { - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I830_GMCH_GMS_STOLEN_512: - memsize = KB(512) - KB(range); - break; - case I830_GMCH_GMS_STOLEN_1024: - memsize = MB(1) - KB(range); - break; - case I830_GMCH_GMS_STOLEN_8192: - memsize = MB(8) - KB(range); - break; - case I830_GMCH_GMS_LOCAL: - memsize = 0; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Local memory found, but won't be used.\n"); - break; - } - } - if (memsize > 0) { - fprintf(stderr, - "detected %d kB stolen memory.\n", memsize / 1024); - } else { - fprintf(stderr, - "no video memory detected.\n"); - } - return memsize; -} - -static int AgpInit(const DRIDriverContext *ctx, I830Rec *info) -{ - unsigned long mode = 0x4; - - if (drmAgpAcquire(ctx->drmFD) < 0) { - fprintf(stderr, "[gart] AGP not available\n"); - return 0; - } - - if (drmAgpEnable(ctx->drmFD, mode) < 0) { - fprintf(stderr, "[gart] AGP not enabled\n"); - drmAgpRelease(ctx->drmFD); - return 0; - } - else - fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode); - - return 1; -} - -/* - * Allocate memory from the given pool. Grow the pool if needed and if - * possible. - */ -static unsigned long -AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830, - I830MemRange *result, I830MemPool *pool, - long size, unsigned long alignment, int flags) -{ - long needed, start, end; - - if (!result || !pool || !size) - return 0; - - /* Calculate how much space is needed. */ - if (alignment <= GTT_PAGE_SIZE) - needed = size; - else { - start = ROUND_TO(pool->Free.Start, alignment); - end = ROUND_TO(start + size, alignment); - needed = end - pool->Free.Start; - } - if (needed > pool->Free.Size) { - return 0; - } - - result->Start = ROUND_TO(pool->Free.Start, alignment); - pool->Free.Start += needed; - result->End = pool->Free.Start; - - pool->Free.Size = pool->Free.End - pool->Free.Start; - result->Size = result->End - result->Start; - result->Pool = pool; - result->Alignment = alignment; - return needed; -} - -static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange *result) -{ - unsigned long start, end; - unsigned long newApStart, newApEnd; - int ret; - if (!result || !size) - return 0; - - if (!alignment) - alignment = 4; - - start = ROUND_TO(pI830->MemoryAperture.Start, alignment); - end = ROUND_TO(start + size, alignment); - newApStart = end; - newApEnd = pI830->MemoryAperture.End; - - ret=drmAgpAlloc(ctx->drmFD, size, 0, &(result->Physical), (drm_handle_t *)&(result->Key)); - - if (ret) - { - fprintf(stderr,"drmAgpAlloc failed %d\n", ret); - return 0; - } - pI830->allocatedMemory += size; - pI830->MemoryAperture.Start = newApStart; - pI830->MemoryAperture.End = newApEnd; - pI830->MemoryAperture.Size = newApEnd - newApStart; - // pI830->FreeMemory -= size; - result->Start = start; - result->End = start + size; - result->Size = size; - result->Offset = start; - result->Alignment = alignment; - result->Pool = NULL; - - return size; -} - -unsigned long -I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830, - I830MemRange *result, I830MemPool *pool, long size, - unsigned long alignment, int flags) -{ - unsigned long ret; - - if (!result) - return 0; - - /* Make sure these are initialised. */ - result->Size = 0; - result->Key = -1; - - if (!size) { - return 0; - } - - if (pool->Free.Size < size) { - ret = AllocFromAGP(ctx, pI830, size, alignment, result); - } - else { - ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags); - if (ret == 0) - ret = AllocFromAGP(ctx, pI830, size, alignment, result); - } - return ret; -} - -static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem) -{ - if (!mem) - return FALSE; - - if (mem->Key == -1) - return TRUE; - - return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset); -} - -/* simple memory allocation routines needed */ -/* put ring buffer in low memory */ -/* need to allocate front, back, depth buffers aligned correctly, - allocate ring buffer, -*/ - -/* */ -static Bool -I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) -{ - unsigned long size, ret; - unsigned long lines, lineSize, align; - - /* allocate ring buffer */ - memset(pI830->LpRing, 0, sizeof(I830RingBuffer)); - pI830->LpRing->mem.Key = -1; - - size = PRIMARY_RINGBUFFER_SIZE; - - ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0); - - if (ret != size) - { - fprintf(stderr,"unable to allocate ring buffer %ld\n", ret); - return FALSE; - } - - pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1; - - - /* allocate front buffer */ - memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); - pI830->FrontBuffer.Key = -1; - pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth; - - align = KB(512); - - lineSize = ctx->shared.virtualWidth * ctx->cpp; - lines = (ctx->shared.virtualHeight + 15) / 16 * 16; - size = lineSize * lines; - size = ROUND_TO_PAGE(size); - - align = GetBestTileAlignment(size); - - ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate front buffer %ld\n", ret); - return FALSE; - } - - memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer)); - pI830->BackBuffer.Key = -1; - pI830->BackBuffer.Pitch = ctx->shared.virtualWidth; - - ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate back buffer %ld\n", ret); - return FALSE; - } - - memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer)); - pI830->DepthBuffer.Key = -1; - pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth; - - ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate depth buffer %ld\n", ret); - return FALSE; - } - - memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem)); - pI830->ContextMem.Key = -1; - size = KB(32); - - ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate context buffer %ld\n", ret); - return FALSE; - } - -#if 0 - memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem)); - pI830->TexMem.Key = -1; - - size = 32768 * 1024; - ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem); - if (ret < size) - { - fprintf(stderr,"unable to allocate texture memory %ld\n", ret); - return FALSE; - } -#endif - - return TRUE; -} - -static Bool -I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830) -{ - if (!BindAgpRange(ctx, &pI830->LpRing->mem)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->FrontBuffer)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->BackBuffer)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->DepthBuffer)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->ContextMem)) - return FALSE; -#if 0 - if (!BindAgpRange(ctx, &pI830->TexMem)) - return FALSE; -#endif - return TRUE; -} - -static void SetupDRIMM(const DRIDriverContext *ctx, I830Rec *pI830) -{ - unsigned long aperEnd = ROUND_DOWN_TO(pI830->aper_size, GTT_PAGE_SIZE) / GTT_PAGE_SIZE; - unsigned long aperStart = ROUND_TO(pI830->aper_size - KB(32768), GTT_PAGE_SIZE) / GTT_PAGE_SIZE; - - fprintf(stderr, "aper size is %08X\n", ctx->shared.fbSize); - if (drmMMInit(ctx->drmFD, aperStart, aperEnd - aperStart, DRM_BO_MEM_TT)) { - fprintf(stderr, - "DRM MM Initialization Failed\n"); - } else { - fprintf(stderr, - "DRM MM Initialized at offset 0x%lx length %d page\n", aperStart, aperEnd-aperStart); - } - -} - -static Bool -I830CleanupDma(const DRIDriverContext *ctx) -{ - drmI830Init info; - - memset(&info, 0, sizeof(drmI830Init)); - info.func = I830_CLEANUP_DMA; - - if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT, - &info, sizeof(drmI830Init))) { - fprintf(stderr, "I830 Dma Cleanup Failed\n"); - return FALSE; - } - - return TRUE; -} - -static Bool -I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830) -{ - I830RingBuffer *ring = pI830->LpRing; - drmI830Init info; - - memset(&info, 0, sizeof(drmI830Init)); - info.func = I830_INIT_DMA; - - info.ring_start = ring->mem.Start + pI830->LinearAddr; - info.ring_end = ring->mem.End + pI830->LinearAddr; - info.ring_size = ring->mem.Size; - - info.mmio_offset = (unsigned int)ctx->MMIOStart; - - info.sarea_priv_offset = sizeof(drm_sarea_t); - - info.front_offset = pI830->FrontBuffer.Start; - info.back_offset = pI830->BackBuffer.Start; - info.depth_offset = pI830->DepthBuffer.Start; - info.w = ctx->shared.virtualWidth; - info.h = ctx->shared.virtualHeight; - info.pitch = ctx->shared.virtualWidth; - info.back_pitch = pI830->BackBuffer.Pitch; - info.depth_pitch = pI830->DepthBuffer.Pitch; - info.cpp = ctx->cpp; - - if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT, - &info, sizeof(drmI830Init))) { - fprintf(stderr, - "I830 Dma Initialization Failed\n"); - return FALSE; - } - - return TRUE; -} - -static int I830CheckDRMVersion( const DRIDriverContext *ctx, - I830Rec *pI830 ) -{ - drmVersionPtr version; - - version = drmGetVersion(ctx->drmFD); - - if (version) { - int req_minor, req_patch; - - req_minor = 4; - req_patch = 0; - - if (version->version_major != 1 || - version->version_minor < req_minor || - (version->version_minor == req_minor && - version->version_patchlevel < req_patch)) { - /* Incompatible drm version */ - fprintf(stderr, - "[dri] I830DRIScreenInit failed because of a version " - "mismatch.\n" - "[dri] i915.o kernel module version is %d.%d.%d " - "but version 1.%d.%d or newer is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel, - req_minor, - req_patch); - drmFreeVersion(version); - return 0; - } - - pI830->drmMinor = version->version_minor; - drmFreeVersion(version); - } - return 1; -} - -static void -I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830) -{ - unsigned int itemp; - unsigned char *MMIO = ctx->MMIOAddress; - - OUTREG(LP_RING + RING_LEN, 0); - OUTREG(LP_RING + RING_TAIL, 0); - OUTREG(LP_RING + RING_HEAD, 0); - - if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) != - pI830->LpRing->mem.Start) { - fprintf(stderr, - "I830SetRingRegs: Ring buffer start (%lx) violates its " - "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK); - } - /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK; - OUTREG(LP_RING + RING_START, itemp); - - if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) != - pI830->LpRing->mem.Size - 4096) { - fprintf(stderr, - "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its " - "mask (%x)\n", pI830->LpRing->mem.Size - 4096, - I830_RING_NR_PAGES); - } - /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES; - itemp |= (RING_NO_REPORT | RING_VALID); - OUTREG(LP_RING + RING_LEN, itemp); - - pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; - pI830->LpRing->tail = INREG(LP_RING + RING_TAIL); - pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); - if (pI830->LpRing->space < 0) - pI830->LpRing->space += pI830->LpRing->mem.Size; - - SetFenceRegs(ctx, pI830); - - /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky - hacky hacky */ - OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr); - -} - -static Bool -I830SetParam(const DRIDriverContext *ctx, int param, int value) -{ - drmI830SetParam sp; - - memset(&sp, 0, sizeof(sp)); - sp.param = param; - sp.value = value; - - if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) { - fprintf(stderr, "I830 SetParam Failed\n"); - return FALSE; - } - - return TRUE; -} - -static Bool -I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ - fprintf(stderr, - "[drm] Mapping front buffer\n"); - - if (drmAddMap(ctx->drmFD, - (drm_handle_t)(sarea->front_offset + pI830->LinearAddr), - sarea->front_size, - DRM_FRAME_BUFFER, /*DRM_AGP,*/ - 0, - &sarea->front_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(front_handle) failed. Disabling DRI\n"); - return FALSE; - } - ctx->shared.hFrameBuffer = sarea->front_handle; - ctx->shared.fbSize = sarea->front_size; - fprintf(stderr, "[drm] Front Buffer = 0x%08x\n", - sarea->front_handle); - - if (drmAddMap(ctx->drmFD, - (drm_handle_t)(sarea->back_offset), - sarea->back_size, DRM_AGP, 0, - &sarea->back_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(back_handle) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] Back Buffer = 0x%08x\n", - sarea->back_handle); - - if (drmAddMap(ctx->drmFD, - (drm_handle_t)sarea->depth_offset, - sarea->depth_size, DRM_AGP, 0, - &sarea->depth_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n", - sarea->depth_handle); - -#if 0 - if (drmAddMap(ctx->drmFD, - (drm_handle_t)sarea->tex_offset, - sarea->tex_size, DRM_AGP, 0, - &sarea->tex_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] textures = 0x%08x\n", - sarea->tex_handle); -#endif - return TRUE; -} - - -static void -I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ -#if 1 - if (sarea->front_handle) { - drmRmMap(ctx->drmFD, sarea->front_handle); - sarea->front_handle = 0; - } -#endif - if (sarea->back_handle) { - drmRmMap(ctx->drmFD, sarea->back_handle); - sarea->back_handle = 0; - } - if (sarea->depth_handle) { - drmRmMap(ctx->drmFD, sarea->depth_handle); - sarea->depth_handle = 0; - } - if (sarea->tex_handle) { - drmRmMap(ctx->drmFD, sarea->tex_handle); - sarea->tex_handle = 0; - } -} - -static Bool -I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ - if (drmAddMap(ctx->drmFD, - (drm_handle_t)pI830->LpRing->mem.Start, - pI830->LpRing->mem.Size, DRM_AGP, 0, - &pI830->ring_map) < 0) { - fprintf(stderr, - "[drm] drmAddMap(ring_map) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] ring buffer = 0x%08x\n", - pI830->ring_map); - - if (I830InitDma(ctx, pI830) == FALSE) { - return FALSE; - } - - /* init to zero to be safe */ - - I830DRIMapScreenRegions(ctx, pI830, sarea); - SetupDRIMM(ctx, pI830); - - if (ctx->pciDevice != PCI_CHIP_845_G && - ctx->pciDevice != PCI_CHIP_I830_M) { - I830SetParam(ctx, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 ); - } - - /* Okay now initialize the dma engine */ - { - pI830->irq = drmGetInterruptFromBusID(ctx->drmFD, - ctx->pciBus, - ctx->pciDevice, - ctx->pciFunc); - - if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) { - fprintf(stderr, - "[drm] failure adding irq handler\n"); - pI830->irq = 0; - return FALSE; - } - else - fprintf(stderr, - "[drm] dma control initialized, using IRQ %d\n", - pI830->irq); - } - - fprintf(stderr, "[dri] visual configs initialized\n"); - - return TRUE; -} - -static Bool -I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ - /* need to drmMap front and back buffers and zero them */ - drmAddress map_addr; - int ret; - - ret = drmMap(ctx->drmFD, - sarea->front_handle, - sarea->front_size, - &map_addr); - - if (ret) - { - fprintf(stderr, "Unable to map front buffer\n"); - return FALSE; - } - - drimemsetio((char *)map_addr, - 0, - sarea->front_size); - drmUnmap(map_addr, sarea->front_size); - - - ret = drmMap(ctx->drmFD, - sarea->back_handle, - sarea->back_size, - &map_addr); - - if (ret) - { - fprintf(stderr, "Unable to map back buffer\n"); - return FALSE; - } - - drimemsetio((char *)map_addr, - 0, - sarea->back_size); - drmUnmap(map_addr, sarea->back_size); - - return TRUE; -} - -static Bool -I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830) - -{ - I830DRIPtr pI830DRI; - drmI830Sarea *pSAREAPriv; - int err; - - drm_page_size = getpagesize(); - - pI830->registerSize = ctx->MMIOSize; - /* This is a hack for now. We have to have more than a 4k page here - * because of the size of the state. However, the state should be - * in a per-context mapping. This will be added in the Mesa 3.5 port - * of the I830 driver. - */ - ctx->shared.SAREASize = SAREA_MAX; - - /* Note that drmOpen will try to load the kernel module, if needed. */ - ctx->drmFD = drmOpen("i915", NULL ); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - - if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - if (drmAddMap( ctx->drmFD, - 0, - ctx->shared.SAREASize, - DRM_SHM, - DRM_CONTAINS_LOCK, - &ctx->shared.hSAREA) < 0) - { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap( ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - - } - - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08x to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - - if (drmAddMap(ctx->drmFD, - ctx->MMIOStart, - ctx->MMIOSize, - DRM_REGISTERS, - DRM_READ_ONLY, - &pI830->registerHandle) < 0) { - fprintf(stderr, "[drm] drmAddMap mmio failed\n"); - return 0; - } - fprintf(stderr, - "[drm] register handle = 0x%08x\n", pI830->registerHandle); - - - if (!I830CheckDRMVersion(ctx, pI830)) { - return FALSE; - } - - /* Create a 'server' context so we can grab the lock for - * initialization ioctls. - */ - if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return 0; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - /* Initialize the SAREA private data structure */ - pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); - - pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830); - pI830->StolenMemory.Start = 0; - pI830->StolenMemory.End = pI830->StolenMemory.Size; - - pI830->MemoryAperture.Start = pI830->StolenMemory.End; - pI830->MemoryAperture.End = KB(40000); - pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start; - - pI830->StolenPool.Fixed = pI830->StolenMemory; - pI830->StolenPool.Total = pI830->StolenMemory; - pI830->StolenPool.Free = pI830->StolenPool.Total; - pI830->FreeMemory = pI830->StolenPool.Total.Size; - - if (!AgpInit(ctx, pI830)) - return FALSE; - - if (I830AllocateMemory(ctx, pI830) == FALSE) - { - return FALSE; - } - - if (I830BindMemory(ctx, pI830) == FALSE) - { - return FALSE; - } - - pSAREAPriv->rotated_offset = -1; - pSAREAPriv->rotated_size = 0; - pSAREAPriv->rotated_pitch = ctx->shared.virtualWidth; - - pSAREAPriv->front_offset = pI830->FrontBuffer.Start; - pSAREAPriv->front_size = pI830->FrontBuffer.Size; - pSAREAPriv->width = ctx->shared.virtualWidth; - pSAREAPriv->height = ctx->shared.virtualHeight; - pSAREAPriv->pitch = ctx->shared.virtualWidth; - pSAREAPriv->virtualX = ctx->shared.virtualWidth; - pSAREAPriv->virtualY = ctx->shared.virtualHeight; - pSAREAPriv->back_offset = pI830->BackBuffer.Start; - pSAREAPriv->back_size = pI830->BackBuffer.Size; - pSAREAPriv->depth_offset = pI830->DepthBuffer.Start; - pSAREAPriv->depth_size = pI830->DepthBuffer.Size; -#if 0 - pSAREAPriv->tex_offset = pI830->TexMem.Start; - pSAREAPriv->tex_size = pI830->TexMem.Size; -#endif - pSAREAPriv->log_tex_granularity = pI830->TexGranularity; - - ctx->driverClientMsg = malloc(sizeof(I830DRIRec)); - ctx->driverClientMsgSize = sizeof(I830DRIRec); - pI830DRI = (I830DRIPtr)ctx->driverClientMsg; - pI830DRI->deviceID = pI830->Chipset; - pI830DRI->regsSize = I830_REG_SIZE; - pI830DRI->width = ctx->shared.virtualWidth; - pI830DRI->height = ctx->shared.virtualHeight; - pI830DRI->mem = ctx->shared.fbSize; - pI830DRI->cpp = ctx->cpp; - - pI830DRI->bitsPerPixel = ctx->bpp; - pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t); - - err = I830DRIDoMappings(ctx, pI830, pSAREAPriv); - if (err == FALSE) - return FALSE; - - I830SetupMemoryTiling(ctx, pI830); - - /* Quick hack to clear the front & back buffers. Could also use - * the clear ioctl to do this, but would need to setup hw state - * first. - */ - I830ClearScreen(ctx, pI830, pSAREAPriv); - - I830SetRingRegs(ctx, pI830); - - return TRUE; -} - - -/** - * \brief Validate the fbdev mode. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Saves some registers and returns 1. - * - * \sa radeonValidateMode(). - */ -static int i830ValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - -/** - * \brief Examine mode returned by fbdev. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Restores registers that fbdev has clobbered and returns 1. - * - * \sa i810ValidateMode(). - */ -static int i830PostValidateMode( const DRIDriverContext *ctx ) -{ - I830Rec *pI830 = ctx->driverPrivate; - - I830SetRingRegs(ctx, pI830); - return 1; -} - - -/** - * \brief Initialize the framebuffer device mode - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Fills in \p info with some default values and some information from \p ctx - * and then calls I810ScreenInit() for the screen initialization. - * - * Before exiting clears the framebuffer memory accessing it directly. - */ -static int i830InitFBDev( DRIDriverContext *ctx ) -{ - I830Rec *pI830 = calloc(1, sizeof(I830Rec)); - int i; - - { - int dummy = ctx->shared.virtualWidth; - - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; - } - - ctx->shared.virtualWidth = dummy; - ctx->shared.Width = ctx->shared.virtualWidth; - } - - - for (i = 0; pitches[i] != 0; i++) { - if (pitches[i] >= ctx->shared.virtualWidth) { - ctx->shared.virtualWidth = pitches[i]; - break; - } - } - - ctx->driverPrivate = (void *)pI830; - - pI830->LpRing = calloc(1, sizeof(I830RingBuffer)); - pI830->Chipset = ctx->chipset; - pI830->LinearAddr = ctx->FBStart; - - if (!I830ScreenInit( ctx, pI830 )) - return 0; - - - return 1; -} - - -/** - * \brief The screen is being closed, so clean up any state and free any - * resources used by the DRI. - * - * \param ctx display handle. - * - * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver - * private data. - */ -static void i830HaltFBDev( DRIDriverContext *ctx ) -{ - drmI830Sarea *pSAREAPriv; - I830Rec *pI830 = ctx->driverPrivate; - - if (pI830->irq) { - drmCtlUninstHandler(ctx->drmFD); - pI830->irq = 0; } - - I830CleanupDma(ctx); - - pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - - I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv); - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = 0; - } -} - - -extern void i810NotifyFocus( int ); - -/** - * \brief Exported driver interface for Mini GLX. - * - * \sa DRIDriverRec. - */ -const struct DRIDriverRec __driDriver = { - i830ValidateMode, - i830PostValidateMode, - i830InitFBDev, - i830HaltFBDev, - NULL,//I830EngineShutdown, - NULL, //I830EngineRestore, -#ifndef _EMBEDDED - 0, -#else - i810NotifyFocus, -#endif -}; diff --git a/src/mesa/drivers/dri/mach64/Makefile b/src/mesa/drivers/dri/mach64/Makefile index a8f463e9fd0..c20fdece297 100644 --- a/src/mesa/drivers/dri/mach64/Makefile +++ b/src/mesa/drivers/dri/mach64/Makefile @@ -5,9 +5,6 @@ include $(TOP)/configs/current LIBNAME = mach64_dri.so -# Not yet -# MINIGLX_SOURCES = server/mach64_dri.c - DRIVER_SOURCES = \ mach64_context.c \ mach64_ioctl.c \ diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c index 77e7e53ce04..73b1e08d4b8 100644 --- a/src/mesa/drivers/dri/mach64/mach64_context.c +++ b/src/mesa/drivers/dri/mach64/mach64_context.c @@ -31,6 +31,7 @@ #include "main/glheader.h" #include "main/context.h" +#include "main/extensions.h" #include "main/simple_list.h" #include "main/imports.h" diff --git a/src/mesa/drivers/dri/mga/Makefile b/src/mesa/drivers/dri/mga/Makefile index 0cc329fb22d..92533bccc29 100644 --- a/src/mesa/drivers/dri/mga/Makefile +++ b/src/mesa/drivers/dri/mga/Makefile @@ -5,8 +5,6 @@ include $(TOP)/configs/current LIBNAME = mga_dri.so -MINIGLX_SOURCES = server/mga_dri.c - DRIVER_SOURCES = \ mgadd.c \ mgaioctl.c \ diff --git a/src/mesa/drivers/dri/mga/server/mga_dri.c b/src/mesa/drivers/dri/mga/server/mga_dri.c deleted file mode 100644 index bc575e62ee8..00000000000 --- a/src/mesa/drivers/dri/mga/server/mga_dri.c +++ /dev/null @@ -1,1088 +0,0 @@ - -/* - * Copyright 2000 VA Linux Systems Inc., Fremont, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES - * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <[email protected]> - * Gareth Hughes <[email protected]> - */ - -#include <errno.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <inttypes.h> - -#include "driver.h" -#include "drm.h" -#include "memops.h" - -#include "mga_reg.h" -#include "mga.h" -#include "mga_macros.h" -#include "mga_dri.h" - - -/* Quiescence, locking - */ -#define MGA_TIMEOUT 2048 - -static void MGAWaitForIdleDMA( struct DRIDriverContextRec *ctx, MGAPtr pMga ) -{ - drm_lock_t lock; - int ret; - int i = 0; - - memset( &lock, 0, sizeof(lock) ); - - for (;;) { - do { - /* first ask for quiescent and flush */ - lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH; - do { - ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH, - &lock, sizeof( lock ) ); - } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); - - /* if it's still busy just try quiescent */ - if ( ret == -EBUSY ) { - lock.flags = DRM_LOCK_QUIESCENT; - do { - ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH, - &lock, sizeof( lock ) ); - } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); - } - } while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) ); - - if ( ret == 0 ) - return; - - fprintf( stderr, - "[dri] Idle timed out, resetting engine...\n" ); - - drmCommandNone( ctx->drmFD, DRM_MGA_RESET ); - } -} - -static unsigned int mylog2( unsigned int n ) -{ - unsigned int log2 = 1; - while ( n > 1 ) n >>= 1, log2++; - return log2; -} - -static int MGADRIAgpInit(struct DRIDriverContextRec *ctx, MGAPtr pMga) -{ - unsigned long mode; - unsigned int vendor, device; - int ret, count, i; - - if(pMga->agpSize < 12)pMga->agpSize = 12; - if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */ - - /* FIXME: Make these configurable... - */ - pMga->agp.size = pMga->agpSize * 1024 * 1024; - - pMga->warp.offset = 0; - pMga->warp.size = MGA_WARP_UCODE_SIZE; - - pMga->primary.offset = (pMga->warp.offset + - pMga->warp.size); - pMga->primary.size = 1024 * 1024; - - pMga->buffers.offset = (pMga->primary.offset + - pMga->primary.size); - pMga->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE; - - - pMga->agpTextures.offset = (pMga->buffers.offset + - pMga->buffers.size); - - pMga->agpTextures.size = pMga->agp.size - - pMga->agpTextures.offset; - - if ( drmAgpAcquire( ctx->drmFD ) < 0 ) { - fprintf( stderr, "[agp] AGP not available\n" ); - return 0; - } - - mode = drmAgpGetMode( ctx->drmFD ); /* Default mode */ - vendor = drmAgpVendorId( ctx->drmFD ); - device = drmAgpDeviceId( ctx->drmFD ); - - mode &= ~MGA_AGP_MODE_MASK; - switch ( pMga->agpMode ) { - case 4: - mode |= MGA_AGP_4X_MODE; - case 2: - mode |= MGA_AGP_2X_MODE; - case 1: - default: - mode |= MGA_AGP_1X_MODE; - } - -#if 0 - fprintf( stderr, - "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", - mode, vendor, device, - ctx->pciVendor, - ctx->pciChipType ); -#endif - - if ( drmAgpEnable( ctx->drmFD, mode ) < 0 ) { - fprintf( stderr, "[agp] AGP not enabled\n" ); - drmAgpRelease( ctx->drmFD ); - return 0; - } - - if ( pMga->Chipset == PCI_CHIP_MGAG200 ) { - switch ( pMga->agpMode ) { - case 2: - fprintf( stderr, - "[drm] Enabling AGP 2x PLL encoding\n" ); - OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE ); - break; - - case 1: - default: - fprintf( stderr, - "[drm] Disabling AGP 2x PLL encoding\n" ); - OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE ); - pMga->agpMode = 1; - break; - } - } - - ret = drmAgpAlloc( ctx->drmFD, pMga->agp.size, - 0, NULL, &pMga->agp.handle ); - if ( ret < 0 ) { - fprintf( stderr, "[agp] Out of memory (%d)\n", ret ); - drmAgpRelease( ctx->drmFD ); - return 0; - } - fprintf( stderr, - "[agp] %d kB allocated with handle 0x%08x\n", - pMga->agp.size/1024, (unsigned int)pMga->agp.handle ); - - if ( drmAgpBind( ctx->drmFD, pMga->agp.handle, 0 ) < 0 ) { - fprintf( stderr, "[agp] Could not bind memory\n" ); - drmAgpFree( ctx->drmFD, pMga->agp.handle ); - drmAgpRelease( ctx->drmFD ); - return 0; - } - - /* WARP microcode space - */ - if ( drmAddMap( ctx->drmFD, - pMga->warp.offset, - pMga->warp.size, - DRM_AGP, DRM_READ_ONLY, - &pMga->warp.handle ) < 0 ) { - fprintf( stderr, - "[agp] Could not add WARP microcode mapping\n" ); - return 0; - } - fprintf( stderr, - "[agp] WARP microcode handle = 0x%08x\n", - pMga->warp.handle ); - - if ( drmMap( ctx->drmFD, - pMga->warp.handle, - pMga->warp.size, - &pMga->warp.map ) < 0 ) { - fprintf( stderr, - "[agp] Could not map WARP microcode\n" ); - return 0; - } - fprintf( stderr, - "[agp] WARP microcode mapped at 0x%08lx\n", - (unsigned long)pMga->warp.map ); - - /* Primary DMA space - */ - if ( drmAddMap( ctx->drmFD, - pMga->primary.offset, - pMga->primary.size, - DRM_AGP, DRM_READ_ONLY, - &pMga->primary.handle ) < 0 ) { - fprintf( stderr, - "[agp] Could not add primary DMA mapping\n" ); - return 0; - } - fprintf( stderr, - "[agp] Primary DMA handle = 0x%08x\n", - pMga->primary.handle ); - - if ( drmMap( ctx->drmFD, - pMga->primary.handle, - pMga->primary.size, - &pMga->primary.map ) < 0 ) { - fprintf( stderr, - "[agp] Could not map primary DMA\n" ); - return 0; - } - fprintf( stderr, - "[agp] Primary DMA mapped at 0x%08lx\n", - (unsigned long)pMga->primary.map ); - - /* DMA buffers - */ - if ( drmAddMap( ctx->drmFD, - pMga->buffers.offset, - pMga->buffers.size, - DRM_AGP, 0, - &pMga->buffers.handle ) < 0 ) { - fprintf( stderr, - "[agp] Could not add DMA buffers mapping\n" ); - return 0; - } - fprintf( stderr, - "[agp] DMA buffers handle = 0x%08x\n", - pMga->buffers.handle ); - - if ( drmMap( ctx->drmFD, - pMga->buffers.handle, - pMga->buffers.size, - &pMga->buffers.map ) < 0 ) { - fprintf( stderr, - "[agp] Could not map DMA buffers\n" ); - return 0; - } - fprintf( stderr, - "[agp] DMA buffers mapped at 0x%08lx\n", - (unsigned long)pMga->buffers.map ); - - count = drmAddBufs( ctx->drmFD, - MGA_NUM_BUFFERS, MGA_BUFFER_SIZE, - DRM_AGP_BUFFER, pMga->buffers.offset ); - if ( count <= 0 ) { - fprintf( stderr, - "[drm] failure adding %d %d byte DMA buffers\n", - MGA_NUM_BUFFERS, MGA_BUFFER_SIZE ); - return 0; - } - fprintf( stderr, - "[drm] Added %d %d byte DMA buffers\n", - count, MGA_BUFFER_SIZE ); - - i = mylog2(pMga->agpTextures.size / MGA_NR_TEX_REGIONS); - if(i < MGA_LOG_MIN_TEX_REGION_SIZE) - i = MGA_LOG_MIN_TEX_REGION_SIZE; - pMga->agpTextures.size = (pMga->agpTextures.size >> i) << i; - - if ( drmAddMap( ctx->drmFD, - pMga->agpTextures.offset, - pMga->agpTextures.size, - DRM_AGP, 0, - &pMga->agpTextures.handle ) < 0 ) { - fprintf( stderr, - "[agp] Could not add agpTexture mapping\n" ); - return 0; - } -/* should i map it ? */ - fprintf( stderr, - "[agp] agpTexture handle = 0x%08x\n", - pMga->agpTextures.handle ); - fprintf( stderr, - "[agp] agpTexture size: %d kb\n", pMga->agpTextures.size/1024 ); - - return 1; -} - -static int MGADRIMapInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) -{ - pMga->registers.size = MGAIOMAPSIZE; - - if ( drmAddMap( ctx->drmFD, - (drm_handle_t)pMga->IOAddress, - pMga->registers.size, - DRM_REGISTERS, DRM_READ_ONLY, - &pMga->registers.handle ) < 0 ) { - fprintf( stderr, - "[drm] Could not add MMIO registers mapping\n" ); - return 0; - } - fprintf( stderr, - "[drm] Registers handle = 0x%08lx\n", - pMga->registers.handle ); - - pMga->status.size = SAREA_MAX; - - if ( drmAddMap( ctx->drmFD, 0, pMga->status.size, - DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL, - &pMga->status.handle ) < 0 ) { - fprintf( stderr, - "[drm] Could not add status page mapping\n" ); - return 0; - } - fprintf( stderr, - "[drm] Status handle = 0x%08x\n", - pMga->status.handle ); - - if ( drmMap( ctx->drmFD, - pMga->status.handle, - pMga->status.size, - &pMga->status.map ) < 0 ) { - fprintf( stderr, - "[agp] Could not map status page\n" ); - return 0; - } - fprintf( stderr, - "[agp] Status page mapped at 0x%08lx\n", - (unsigned long)pMga->status.map ); - - return 1; -} - -static int MGADRIKernelInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) -{ - drm_mga_init_t init; - int ret; - - memset( &init, 0, sizeof(init) ); - - init.func = MGA_INIT_DMA; - init.sarea_priv_offset = sizeof(drm_sarea_t); - - switch ( pMga->Chipset ) { - case PCI_CHIP_MGAG550: - case PCI_CHIP_MGAG400: - init.chipset = MGA_CARD_TYPE_G400; - break; - case PCI_CHIP_MGAG200: - case PCI_CHIP_MGAG200_PCI: - init.chipset = MGA_CARD_TYPE_G200; - break; - default: - return 0; - } - - init.sgram = 0; /* FIXME !pMga->HasSDRAM; */ - - - switch (ctx->bpp) - { - case 16: - init.maccess = MGA_MACCESS_PW16; - break; - case 32: - init.maccess = MGA_MACCESS_PW32; - break; - default: - fprintf( stderr, "[mga] invalid bpp (%d)\n", ctx->bpp ); - return 0; - } - - - init.fb_cpp = ctx->bpp / 8; - init.front_offset = pMga->frontOffset; - init.front_pitch = pMga->frontPitch / init.fb_cpp; - init.back_offset = pMga->backOffset; - init.back_pitch = pMga->backPitch / init.fb_cpp; - - init.depth_cpp = ctx->bpp / 8; - init.depth_offset = pMga->depthOffset; - init.depth_pitch = pMga->depthPitch / init.depth_cpp; - - init.texture_offset[0] = pMga->textureOffset; - init.texture_size[0] = pMga->textureSize; - - init.fb_offset = ctx->shared.hFrameBuffer; - init.mmio_offset = pMga->registers.handle; - init.status_offset = pMga->status.handle; - - init.warp_offset = pMga->warp.handle; - init.primary_offset = pMga->primary.handle; - init.buffers_offset = pMga->buffers.handle; - - init.texture_offset[1] = pMga->agpTextures.handle; - init.texture_size[1] = pMga->agpTextures.size; - - ret = drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(init)); - if ( ret < 0 ) { - fprintf( stderr, - "[drm] Failed to initialize DMA! (%d)\n", ret ); - return 0; - } - - return 1; -} - -static void MGADRIIrqInit(struct DRIDriverContextRec *ctx, MGAPtr pMga) -{ - if (!pMga->irq) - { - pMga->irq = drmGetInterruptFromBusID(ctx->drmFD, - ctx->pciBus, - ctx->pciDevice, - ctx->pciFunc); - - fprintf(stderr, "[drm] got IRQ %d\n", pMga->irq); - - if((drmCtlInstHandler(ctx->drmFD, pMga->irq)) != 0) - { - fprintf(stderr, - "[drm] failure adding irq handler, " - "there is a device already using that irq\n" - "[drm] falling back to irq-free operation\n"); - pMga->irq = 0; - } - else - { - pMga->reg_ien = INREG( MGAREG_IEN ); - } - } - - if (pMga->irq) - fprintf(stderr, - "[drm] dma control initialized, using IRQ %d\n", - pMga->irq); -} - -static int MGADRIBuffersInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) -{ - pMga->drmBuffers = drmMapBufs( ctx->drmFD ); - if ( !pMga->drmBuffers ) - { - fprintf( stderr, - "[drm] Failed to map DMA buffers list\n" ); - return 0; - } - - fprintf( stderr, - "[drm] Mapped %d DMA buffers\n", - pMga->drmBuffers->count ); - - return 1; -} - -static int MGAMemoryInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) -{ - int width_bytes = ctx->shared.virtualWidth * ctx->cpp; - int bufferSize = ((ctx->shared.virtualHeight * width_bytes - + MGA_BUFFER_ALIGN) - & ~MGA_BUFFER_ALIGN); - int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes - + MGA_BUFFER_ALIGN) - & ~MGA_BUFFER_ALIGN); - int l; - - pMga->frontOffset = 0; - pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp; - - fprintf(stderr, - "Using %d MB AGP aperture\n", pMga->agpSize); - fprintf(stderr, - "Using %d MB for vertex/indirect buffers\n", pMga->buffers.size>>20); - fprintf(stderr, - "Using %d MB for AGP textures\n", pMga->agpTextures.size>>20); - - /* Front, back and depth buffers - everything else texture?? - */ - pMga->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize; - - if (pMga->textureSize < 0) - return 0; - - l = mylog2( pMga->textureSize / MGA_NR_TEX_REGIONS ); - if ( l < MGA_LOG_MIN_TEX_REGION_SIZE ) - l = MGA_LOG_MIN_TEX_REGION_SIZE; - - /* Round the texture size up to the nearest whole number of - * texture regions. Again, be greedy about this, don't - * round down. - */ - pMga->logTextureGranularity = l; - pMga->textureSize = (pMga->textureSize >> l) << l; - - /* Set a minimum usable local texture heap size. This will fit - * two 256x256x32bpp textures. - */ - if (pMga->textureSize < 512 * 1024) { - pMga->textureOffset = 0; - pMga->textureSize = 0; - } - - /* Reserve space for textures */ - pMga->textureOffset = ((ctx->shared.fbSize - pMga->textureSize + - MGA_BUFFER_ALIGN) & - ~MGA_BUFFER_ALIGN); - - /* Reserve space for the shared depth - * buffer. - */ - pMga->depthOffset = ((pMga->textureOffset - depthSize + - MGA_BUFFER_ALIGN) & - ~MGA_BUFFER_ALIGN); - pMga->depthPitch = ctx->shared.virtualWidth * ctx->cpp; - - pMga->backOffset = ((pMga->depthOffset - bufferSize + - MGA_BUFFER_ALIGN) & - ~MGA_BUFFER_ALIGN); - pMga->backPitch = ctx->shared.virtualWidth * ctx->cpp; - - - fprintf(stderr, - "Will use back buffer at offset 0x%x\n", - pMga->backOffset); - fprintf(stderr, - "Will use depth buffer at offset 0x%x\n", - pMga->depthOffset); - fprintf(stderr, - "Will use %d kb for textures at offset 0x%x\n", - pMga->textureSize/1024, pMga->textureOffset); - - return 1; -} - -static int MGACheckDRMVersion( struct DRIDriverContextRec *ctx, MGAPtr pMga ) -{ - drmVersionPtr version; - - /* Check the MGA DRM version */ - version = drmGetVersion(ctx->drmFD); - if ( version ) { - if ( version->version_major != 3 || - version->version_minor < 0 ) { - /* incompatible drm version */ - fprintf( stderr, - "[dri] MGADRIScreenInit failed because of a version mismatch.\n" - "[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel ); - drmFreeVersion( version ); - return 0; - } - drmFreeVersion( version ); - } - - return 1; -} - -static void print_client_msg( MGADRIPtr pMGADRI ) -{ - fprintf( stderr, "chipset: %d\n", pMGADRI->chipset ); - - fprintf( stderr, "width: %d\n", pMGADRI->width ); - fprintf( stderr, "height: %d\n", pMGADRI->height ); - fprintf( stderr, "mem: %d\n", pMGADRI->mem ); - fprintf( stderr, "cpp: %d\n", pMGADRI->cpp ); - - fprintf( stderr, "agpMode: %d\n", pMGADRI->agpMode ); - - fprintf( stderr, "frontOffset: %d\n", pMGADRI->frontOffset ); - fprintf( stderr, "frontPitch: %d\n", pMGADRI->frontPitch ); - - fprintf( stderr, "backOffset: %d\n", pMGADRI->backOffset ); - fprintf( stderr, "backPitch: %d\n", pMGADRI->backPitch ); - - fprintf( stderr, "depthOffset: %d\n", pMGADRI->depthOffset ); - fprintf( stderr, "depthPitch: %d\n", pMGADRI->depthPitch ); - - fprintf( stderr, "textureOffset: %d\n", pMGADRI->textureOffset ); - fprintf( stderr, "textureSize: %d\n", pMGADRI->textureSize ); - - fprintf( stderr, "logTextureGranularity: %d\n", pMGADRI->logTextureGranularity ); - fprintf( stderr, "logAgpTextureGranularity: %d\n", pMGADRI->logAgpTextureGranularity ); - - fprintf( stderr, "agpTextureHandle: %u\n", (unsigned int)pMGADRI->agpTextureOffset ); - fprintf( stderr, "agpTextureSize: %u\n", (unsigned int)pMGADRI->agpTextureSize ); - -#if 0 - pMGADRI->registers.handle = pMga->registers.handle; - pMGADRI->registers.size = pMga->registers.size; - pMGADRI->status.handle = pMga->status.handle; - pMGADRI->status.size = pMga->status.size; - pMGADRI->primary.handle = pMga->primary.handle; - pMGADRI->primary.size = pMga->primary.size; - pMGADRI->buffers.handle = pMga->buffers.handle; - pMGADRI->buffers.size = pMga->buffers.size; - pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t); -#endif -} - -static int MGAScreenInit( struct DRIDriverContextRec *ctx, MGAPtr pMga ) -{ - int i; - int err; - MGADRIPtr pMGADRI; - - usleep(100); - /*assert(!ctx->IsClient);*/ - - { - int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); - int maxy = ctx->shared.fbSize / width_bytes; - - - if (maxy <= ctx->shared.virtualHeight * 3) { - fprintf(stderr, - "Static buffer allocation failed -- " - "need at least %d kB video memory (have %d kB)\n", - (ctx->shared.virtualWidth * ctx->shared.virtualHeight * - ctx->cpp * 3 + 1023) / 1024, - ctx->shared.fbSize / 1024); - return 0; - } - } - - switch(pMga->Chipset) { - case PCI_CHIP_MGAG550: - case PCI_CHIP_MGAG400: - case PCI_CHIP_MGAG200: -#if 0 - case PCI_CHIP_MGAG200_PCI: -#endif - break; - default: - fprintf(stderr, "[drm] Direct rendering only supported with G200/G400/G550 AGP\n"); - return 0; - } - - fprintf( stderr, - "[drm] bpp: %d depth: %d\n", - ctx->bpp, ctx->bpp /* FIXME: depth */ ); - - if ( (ctx->bpp / 8) != 2 && - (ctx->bpp / 8) != 4 ) { - fprintf( stderr, - "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" ); - return 0; - } - - ctx->shared.SAREASize = SAREA_MAX; - - - /* Note that drmOpen will try to load the kernel module, if needed. */ - ctx->drmFD = drmOpen("mga", NULL ); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - - if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - - if (drmAddMap( ctx->drmFD, - 0, - ctx->shared.SAREASize, - DRM_SHM, - DRM_CONTAINS_LOCK, - &ctx->shared.hSAREA) < 0) - { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap( ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - } - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - /* Need to AddMap the framebuffer and mmio regions here: - */ - if (drmAddMap( ctx->drmFD, - (drm_handle_t)ctx->FBStart, - ctx->FBSize, - DRM_FRAME_BUFFER, - 0, - &ctx->shared.hFrameBuffer) < 0) - { - fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); - return 0; - } - fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", - ctx->shared.hFrameBuffer); - - -#if 0 /* will be done in MGADRIMapInit */ - if (drmAddMap(ctx->drmFD, - ctx->FixedInfo.mmio_start, - ctx->FixedInfo.mmio_len, - DRM_REGISTERS, - DRM_READ_ONLY, - &pMga->registers.handle) < 0) { - fprintf(stderr, "[drm] drmAddMap mmio failed\n"); - return 0; - } - fprintf(stderr, - "[drm] register handle = 0x%08lx\n", pMga->registers.handle); -#endif - - - /* Check the mga DRM version */ - if (!MGACheckDRMVersion(ctx, pMga)) { - return 0; - } - - if ( !MGADRIAgpInit( ctx, pMga ) ) { - return 0; - } - - if ( !MGADRIMapInit( ctx, pMga ) ) { - return 0; - } - - /* Memory manager setup */ - if (!MGAMemoryInit(ctx, pMga)) { - return 0; - } - - - /* Create a 'server' context so we can grab the lock for - * initialization ioctls. - */ - if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return 0; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - /* Initialize the kernel data structures */ - if (!MGADRIKernelInit(ctx, pMga)) { - fprintf(stderr, "MGADRIKernelInit failed\n"); - DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); - return 0; - } - - /* Initialize the vertex buffers list */ - if (!MGADRIBuffersInit(ctx, pMga)) { - fprintf(stderr, "MGADRIBuffersInit failed\n"); - DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); - return 0; - } - - /* Initialize IRQ */ - MGADRIIrqInit(ctx, pMga); - - - /* Initialize the SAREA private data structure */ - { - drm_mga_sarea_t *pSAREAPriv; - pSAREAPriv = (drm_mga_sarea_t *)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); - } - - /* Quick hack to clear the front & back buffers. Could also use - * the clear ioctl to do this, but would need to setup hw state - * first. - */ - drimemsetio((char *)ctx->FBAddress + pMga->frontOffset, - 0, - pMga->frontPitch * ctx->shared.virtualHeight ); - - drimemsetio((char *)ctx->FBAddress + pMga->backOffset, - 0, - pMga->backPitch * ctx->shared.virtualHeight ); - - /* Can release the lock now */ -/* DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);*/ - - /* This is the struct passed to radeon_dri.so for its initialization */ - ctx->driverClientMsg = malloc(sizeof(MGADRIRec)); - ctx->driverClientMsgSize = sizeof(MGADRIRec); - - pMGADRI = (MGADRIPtr)ctx->driverClientMsg; - - - switch(pMga->Chipset) { - case PCI_CHIP_MGAG550: - case PCI_CHIP_MGAG400: - pMGADRI->chipset = MGA_CARD_TYPE_G400; - break; - case PCI_CHIP_MGAG200: - case PCI_CHIP_MGAG200_PCI: - pMGADRI->chipset = MGA_CARD_TYPE_G200; - break; - default: - return 0; - } - pMGADRI->width = ctx->shared.virtualWidth; - pMGADRI->height = ctx->shared.virtualHeight; - pMGADRI->mem = ctx->shared.fbSize; - pMGADRI->cpp = ctx->bpp / 8; - - pMGADRI->agpMode = pMga->agpMode; - - pMGADRI->frontOffset = pMga->frontOffset; - pMGADRI->frontPitch = pMga->frontPitch; - pMGADRI->backOffset = pMga->backOffset; - pMGADRI->backPitch = pMga->backPitch; - pMGADRI->depthOffset = pMga->depthOffset; - pMGADRI->depthPitch = pMga->depthPitch; - pMGADRI->textureOffset = pMga->textureOffset; - pMGADRI->textureSize = pMga->textureSize; - pMGADRI->logTextureGranularity = pMga->logTextureGranularity; - - i = mylog2( pMga->agpTextures.size / MGA_NR_TEX_REGIONS ); - if ( i < MGA_LOG_MIN_TEX_REGION_SIZE ) - i = MGA_LOG_MIN_TEX_REGION_SIZE; - - pMGADRI->logAgpTextureGranularity = i; - pMGADRI->agpTextureOffset = (unsigned int)pMga->agpTextures.handle; - pMGADRI->agpTextureSize = (unsigned int)pMga->agpTextures.size; - - pMGADRI->registers.handle = pMga->registers.handle; - pMGADRI->registers.size = pMga->registers.size; - pMGADRI->status.handle = pMga->status.handle; - pMGADRI->status.size = pMga->status.size; - pMGADRI->primary.handle = pMga->primary.handle; - pMGADRI->primary.size = pMga->primary.size; - pMGADRI->buffers.handle = pMga->buffers.handle; - pMGADRI->buffers.size = pMga->buffers.size; - pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t); - - print_client_msg( pMGADRI ); - - return 1; -} - - -/** - * \brief Validate the fbdev mode. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Saves some registers and returns 1. - * - * \sa mgaValidateMode(). - */ -static int mgaValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - - -/** - * \brief Examine mode returned by fbdev. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Restores registers that fbdev has clobbered and returns 1. - * - * \sa mgaValidateMode(). - */ -static int mgaPostValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - - -/** - * \brief Initialize the framebuffer device mode - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Fills in \p info with some default values and some information from \p ctx - * and then calls MGAScreenInit() for the screen initialization. - * - * Before exiting clears the framebuffer memomry accessing it directly. - */ -static int mgaInitFBDev( struct DRIDriverContextRec *ctx ) -{ - MGAPtr pMga = calloc(1, sizeof(*pMga)); - - { - int dummy = ctx->shared.virtualWidth; - - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; - } - - ctx->shared.virtualWidth = dummy; - } - - ctx->driverPrivate = (void *)pMga; - - pMga->agpMode = MGA_DEFAULT_AGP_MODE; - pMga->agpSize = MGA_DEFAULT_AGP_SIZE; - - pMga->Chipset = ctx->chipset; - - pMga->IOAddress = ctx->MMIOStart; - pMga->IOBase = ctx->MMIOAddress; - - pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp; - - if (!MGAScreenInit( ctx, pMga )) - return 0; - - return 1; -} - - -/** - * \brief The screen is being closed, so clean up any state and free any - * resources used by the DRI. - * - * \param ctx display handle. - * - * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver - * private data. - */ -static void mgaHaltFBDev( struct DRIDriverContextRec *ctx ) -{ - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = NULL; - } -} - - -static int mgaEngineShutdown( const DRIDriverContext *ctx ) -{ - fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__); - - return 1; -} - -static int mgaEngineRestore( const DRIDriverContext *ctx ) -{ - fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__); - - return 1; -} - -/** - * \brief Exported driver interface for Mini GLX. - * - * \sa DRIDriverRec. - */ -struct DRIDriverRec __driDriver = { - mgaValidateMode, - mgaPostValidateMode, - mgaInitFBDev, - mgaHaltFBDev, - mgaEngineShutdown, - mgaEngineRestore, - 0 -}; - - - - -#if 0 -void MGADRICloseScreen( ScreenPtr pScreen ) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - MGAPtr pMga = MGAPTR(pScrn); - MGADRIServerPrivatePtr pMga = pMga->DRIServerInfo; - drmMGAInit init; - - if ( pMga->drmBuffers ) { - drmUnmapBufs( pMga->drmBuffers ); - pMga->drmBuffers = NULL; - } - - if (pMga->irq) { - drmCtlUninstHandler(ctx->drmFD); - pMga->irq = 0; - } - - /* Cleanup DMA */ - memset( &init, 0, sizeof(drmMGAInit) ); - init.func = MGA_CLEANUP_DMA; - drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(drmMGAInit) ); - - if ( pMga->status.map ) { - drmUnmap( pMga->status.map, pMga->status.size ); - pMga->status.map = NULL; - } - if ( pMga->buffers.map ) { - drmUnmap( pMga->buffers.map, pMga->buffers.size ); - pMga->buffers.map = NULL; - } - if ( pMga->primary.map ) { - drmUnmap( pMga->primary.map, pMga->primary.size ); - pMga->primary.map = NULL; - } - if ( pMga->warp.map ) { - drmUnmap( pMga->warp.map, pMga->warp.size ); - pMga->warp.map = NULL; - } - - if ( pMga->agpTextures.map ) { - drmUnmap( pMga->agpTextures.map, pMga->agpTextures.size ); - pMga->agpTextures.map = NULL; - } - - if ( pMga->agp.handle ) { - drmAgpUnbind( ctx->drmFD, pMga->agp.handle ); - drmAgpFree( ctx->drmFD, pMga->agp.handle ); - pMga->agp.handle = 0; - drmAgpRelease( ctx->drmFD ); - } - - DRICloseScreen( pScreen ); - - if ( pMga->pDRIInfo ) { - if ( pMga->pDRIpMga->devPrivate ) { - xfree( pMga->pDRIpMga->devPrivate ); - pMga->pDRIpMga->devPrivate = 0; - } - DRIDestroyInfoRec( pMga->pDRIInfo ); - pMga->pDRIInfo = 0; - } - if ( pMga->DRIServerInfo ) { - xfree( pMga->DRIServerInfo ); - pMga->DRIServerInfo = 0; - } - if ( pMga->pVisualConfigs ) { - xfree( pMga->pVisualConfigs ); - } - if ( pMga->pVisualConfigsPriv ) { - xfree( pMga->pVisualConfigsPriv ); - } -} -#endif diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile index 49e89335614..7be19b26fda 100644 --- a/src/mesa/drivers/dri/nouveau/Makefile +++ b/src/mesa/drivers/dri/nouveau/Makefile @@ -8,8 +8,6 @@ DRI_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs) LIBNAME = nouveau_vieux_dri.so -MINIGLX_SOURCES = - DRIVER_SOURCES = \ nouveau_screen.c \ nouveau_context.c \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index 52185a2fb90..be57d48b8dd 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -43,19 +43,22 @@ #define need_GL_EXT_framebuffer_object #define need_GL_EXT_fog_coord +#define need_GL_EXT_secondary_color #include "main/remap_helper.h" static const struct dri_extension nouveau_extensions[] = { { "GL_ARB_multitexture", NULL }, + { "GL_ARB_texture_env_add", NULL }, { "GL_ARB_texture_env_combine", NULL }, { "GL_ARB_texture_env_dot3", NULL }, - { "GL_ARB_texture_env_add", NULL }, - { "GL_EXT_texture_lod_bias", NULL }, - { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, { "GL_ARB_texture_mirrored_repeat", NULL }, - { "GL_EXT_stencil_wrap", NULL }, { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, + { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { "GL_EXT_stencil_wrap", NULL }, + { "GL_EXT_texture_lod_bias", NULL }, + { "GL_NV_blend_square", NULL }, { "GL_SGIS_generate_mipmap", NULL }, { NULL, NULL } }; @@ -66,8 +69,8 @@ nouveau_channel_flush_notify(struct nouveau_channel *chan) struct nouveau_context *nctx = chan->user_private; GLcontext *ctx = &nctx->base; - if (nctx->fallback < SWRAST && ctx->DrawBuffer) - nouveau_state_emit(&nctx->base); + if (nctx->fallback < SWRAST) + nouveau_bo_state_emit(ctx); } GLboolean diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h index 682f8a414e3..fe64fec930b 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -85,6 +85,8 @@ struct nouveau_context { BITSET_SET(to_nouveau_context(ctx)->dirty, NOUVEAU_STATE_##s) #define context_dirty_i(ctx, s, i) \ BITSET_SET(to_nouveau_context(ctx)->dirty, NOUVEAU_STATE_##s##0 + i) +#define context_emit(ctx, s) \ + context_drv(ctx)->emit[NOUVEAU_STATE_##s](ctx, NOUVEAU_STATE_##s) GLboolean nouveau_context_create(const __GLcontextModes *visual, __DRIcontext *dri_ctx, diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c index e1871db0eb9..bc610451b40 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c @@ -150,6 +150,7 @@ nouveau_enable(GLcontext *ctx, GLenum cap, GLboolean state) break; case GL_COLOR_SUM_EXT: context_dirty(ctx, FRAG); + context_dirty(ctx, LIGHT_MODEL); break; case GL_CULL_FACE: context_dirty(ctx, CULL_FACE); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c index 69a9b96f0ca..a365b977f29 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c @@ -281,14 +281,13 @@ vbo_maybe_split(GLcontext *ctx, const struct gl_client_array **arrays, int stride; /* Try to keep client buffers smaller than the scratch BOs. */ - if (!ib && render->mode == VBO && + if (render->mode == VBO && (stride = get_max_client_stride(ctx))) vert_avail = MIN2(vert_avail, RENDER_SCRATCH_SIZE / stride); - - if ((ib && ib->count > idx_avail) || - (!ib && max_index - min_index > vert_avail)) { + if (max_index - min_index > vert_avail || + (ib && ib->count > idx_avail)) { struct split_limits limits = { .max_verts = vert_avail, .max_indices = idx_avail, diff --git a/src/mesa/drivers/dri/nouveau/nv04_context.c b/src/mesa/drivers/dri/nouveau/nv04_context.c index a442425e448..3624b3af921 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_context.c +++ b/src/mesa/drivers/dri/nouveau/nv04_context.c @@ -75,18 +75,16 @@ nv04_channel_flush_notify(struct nouveau_channel *chan) struct nouveau_context *nctx = chan->user_private; GLcontext *ctx = &nctx->base; - if (nctx->fallback < SWRAST && ctx->DrawBuffer) { - GLcontext *ctx = &nctx->base; - + if (nctx->fallback < SWRAST) { /* Flushing seems to clobber the engine context. */ - context_dirty_i(ctx, TEX_OBJ, 0); - context_dirty_i(ctx, TEX_OBJ, 1); - context_dirty_i(ctx, TEX_ENV, 0); - context_dirty_i(ctx, TEX_ENV, 1); - context_dirty(ctx, CONTROL); - context_dirty(ctx, BLEND); - - nouveau_state_emit(ctx); + context_emit(ctx, TEX_OBJ0); + context_emit(ctx, TEX_OBJ1); + context_emit(ctx, TEX_ENV0); + context_emit(ctx, TEX_ENV1); + context_emit(ctx, CONTROL); + context_emit(ctx, BLEND); + + nouveau_bo_state_emit(ctx); } } @@ -200,9 +198,9 @@ nv04_context_create(struct nouveau_screen *screen, const GLvisual *visual, if (ret) goto fail; + init_dummy_texture(ctx); nv04_hwctx_init(ctx); nv04_render_init(ctx); - init_dummy_texture(ctx); return ctx; diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_fb.c b/src/mesa/drivers/dri/nouveau/nv04_state_fb.c index aad1e491d2f..5e5e0c58742 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv04_state_fb.c @@ -63,7 +63,7 @@ nv04_emit_framebuffer(GLcontext *ctx, int emit) return; /* Render target */ - if (fb->_NumColorDrawBuffers) { + if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_raster.c b/src/mesa/drivers/dri/nouveau/nv04_state_raster.c index 4314fc33cf4..c191571a5f8 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_state_raster.c +++ b/src/mesa/drivers/dri/nouveau/nv04_state_raster.c @@ -275,6 +275,10 @@ nv04_emit_blend(GLcontext *ctx, int emit) else blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_FLAT; + /* Secondary color */ + if (NEED_SECONDARY_COLOR(ctx)) + blend |= NV04_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE; + /* Fog. */ if (ctx->Fog.Enabled) blend |= NV04_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE; @@ -309,6 +313,10 @@ nv04_emit_blend(GLcontext *ctx, int emit) else blend |= get_texenv_mode(GL_MODULATE); + /* Secondary color */ + if (NEED_SECONDARY_COLOR(ctx)) + blend |= NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE; + /* Fog. */ if (ctx->Fog.Enabled) blend |= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE; diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_fb.c b/src/mesa/drivers/dri/nouveau/nv10_state_fb.c index 05c36b4f8f5..6bd383ebcd3 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_fb.c @@ -111,7 +111,7 @@ nv10_emit_framebuffer(GLcontext *ctx, int emit) } /* Render target */ - if (fb->_NumColorDrawBuffers) { + if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c index 6db14d83b83..406e24c455d 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c @@ -201,8 +201,10 @@ nv10_emit_light_model(GLcontext *ctx, int emit) BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL, 1); OUT_RING(chan, ((m->LocalViewer ? NV10TCL_LIGHT_MODEL_LOCAL_VIEWER : 0) | - (m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ? - NV10TCL_LIGHT_MODEL_SEPARATE_SPECULAR : 0))); + (NEED_SECONDARY_COLOR(ctx) ? + NV10TCL_LIGHT_MODEL_SEPARATE_SPECULAR : 0) | + (!ctx->Light.Enabled && ctx->Fog.ColorSumEnabled ? + NV10TCL_LIGHT_MODEL_VERTEX_SPECULAR : 0))); } static float diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_fb.c b/src/mesa/drivers/dri/nouveau/nv20_state_fb.c index 869acd6e317..d638541df9e 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_fb.c @@ -67,7 +67,7 @@ nv20_emit_framebuffer(GLcontext *ctx, int emit) return; /* Render target */ - if (fb->_NumColorDrawBuffers) { + if (fb->_ColorDrawBuffers[0]) { s = &to_nouveau_renderbuffer( fb->_ColorDrawBuffers[0])->surface; diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c index 0d566064f67..43f8c723122 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c @@ -158,7 +158,7 @@ nv20_emit_light_model(GLcontext *ctx, int emit) OUT_RING(chan, ((m->LocalViewer ? NV20TCL_LIGHT_MODEL_VIEWER_LOCAL : NV20TCL_LIGHT_MODEL_VIEWER_NONLOCAL) | - (m->ColorControl == GL_SEPARATE_SPECULAR_COLOR ? + (NEED_SECONDARY_COLOR(ctx) ? NV20TCL_LIGHT_MODEL_SEPARATE_SPECULAR : 0))); diff --git a/src/mesa/drivers/dri/r128/Makefile b/src/mesa/drivers/dri/r128/Makefile index 52c5a38a705..8144c9b43ff 100644 --- a/src/mesa/drivers/dri/r128/Makefile +++ b/src/mesa/drivers/dri/r128/Makefile @@ -5,8 +5,6 @@ include $(TOP)/configs/current LIBNAME = r128_dri.so -MINIGLX_SOURCES = server/r128_dri.c - DRIVER_SOURCES = \ r128_context.c \ r128_lock.c \ diff --git a/src/mesa/drivers/dri/r128/server/r128_dri.c b/src/mesa/drivers/dri/r128/server/r128_dri.c deleted file mode 100644 index 6e3db948af7..00000000000 --- a/src/mesa/drivers/dri/r128/server/r128_dri.c +++ /dev/null @@ -1,1112 +0,0 @@ -/* - * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, - * Precision Insight, Inc., Cedar Park, Texas, and - * VA Linux Systems Inc., Fremont, California. - * - * 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, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX - * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Authors: - * Kevin E. Martin <[email protected]> - * Rickard E. Faith <[email protected]> - * Daryll Strauss <[email protected]> - * Gareth Hughes <[email protected]> - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -// Fix this to use kernel pci_ids.h when all of these IDs make it into the kernel -#include "pci_ids.h" - -#include "driver.h" -#include "drm.h" -#include "memops.h" - -#include "r128.h" -#include "r128_dri.h" -#include "r128_macros.h" -#include "r128_reg.h" -#include "r128_version.h" -#include "r128_drm.h" - -static size_t r128_drm_page_size; - -/* Compute log base 2 of val. */ -static int R128MinBits(int val) -{ - int bits; - - if (!val) return 1; - for (bits = 0; val; val >>= 1, ++bits); - return bits; -} - -/* Initialize the AGP state. Request memory for use in AGP space, and - initialize the Rage 128 registers to point to that memory. */ -static GLboolean R128DRIAgpInit(const DRIDriverContext *ctx) -{ - unsigned char *R128MMIO = ctx->MMIOAddress; - R128InfoPtr info = ctx->driverPrivate; - unsigned long mode; - unsigned int vendor, device; - int ret; - unsigned long cntl, chunk; - int s, l; - int flags; - unsigned long agpBase; - - if (drmAgpAcquire(ctx->drmFD) < 0) { - fprintf(stderr, "[agp] AGP not available\n"); - return GL_FALSE; - } - - /* Modify the mode if the default mode is - not appropriate for this particular - combination of graphics card and AGP - chipset. */ - - mode = drmAgpGetMode(ctx->drmFD); /* Default mode */ - vendor = drmAgpVendorId(ctx->drmFD); - device = drmAgpDeviceId(ctx->drmFD); - - mode &= ~R128_AGP_MODE_MASK; - switch (info->agpMode) { - case 4: mode |= R128_AGP_4X_MODE; - case 2: mode |= R128_AGP_2X_MODE; - case 1: default: mode |= R128_AGP_1X_MODE; - } - - fprintf(stderr, - "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", - mode, vendor, device, - 0x1002, - info->Chipset); - - if (drmAgpEnable(ctx->drmFD, mode) < 0) { - fprintf(stderr, "[agp] AGP not enabled\n"); - drmAgpRelease(ctx->drmFD); - return GL_FALSE; - } - - info->agpOffset = 0; - - if ((ret = drmAgpAlloc(ctx->drmFD, info->agpSize*1024*1024, 0, NULL, - &info->agpMemHandle)) < 0) { - fprintf(stderr, "[agp] Out of memory (%d)\n", ret); - drmAgpRelease(ctx->drmFD); - return GL_FALSE; - } - fprintf(stderr, - "[agp] %d kB allocated with handle 0x%08x\n", - info->agpSize*1024, info->agpMemHandle); - - if (drmAgpBind(ctx->drmFD, info->agpMemHandle, info->agpOffset) < 0) { - fprintf(stderr, "[agp] Could not bind\n"); - drmAgpFree(ctx->drmFD, info->agpMemHandle); - drmAgpRelease(ctx->drmFD); - return GL_FALSE; - } - - /* Initialize the CCE ring buffer data */ - info->ringStart = info->agpOffset; - info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size; - info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1; - - info->ringReadOffset = info->ringStart + info->ringMapSize; - info->ringReadMapSize = r128_drm_page_size; - - /* Reserve space for vertex/indirect buffers */ - info->bufStart = info->ringReadOffset + info->ringReadMapSize; - info->bufMapSize = info->bufSize*1024*1024; - - /* Reserve the rest for AGP textures */ - info->agpTexStart = info->bufStart + info->bufMapSize; - s = (info->agpSize*1024*1024 - info->agpTexStart); - l = R128MinBits((s-1) / R128_NR_TEX_REGIONS); - if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; - info->agpTexMapSize = (s >> l) << l; - info->log2AGPTexGran = l; - - if (info->CCESecure) flags = DRM_READ_ONLY; - else flags = 0; - - if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize, - DRM_AGP, flags, &info->ringHandle) < 0) { - fprintf(stderr, - "[agp] Could not add ring mapping\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] ring handle = 0x%08x\n", info->ringHandle); - - if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize, - (drmAddressPtr)&info->ring) < 0) { - fprintf(stderr, "[agp] Could not map ring\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] Ring mapped at 0x%08lx\n", - (unsigned long)info->ring); - - if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize, - DRM_AGP, flags, &info->ringReadPtrHandle) < 0) { - fprintf(stderr, - "[agp] Could not add ring read ptr mapping\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] ring read ptr handle = 0x%08x\n", - info->ringReadPtrHandle); - - if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, - (drmAddressPtr)&info->ringReadPtr) < 0) { - fprintf(stderr, - "[agp] Could not map ring read ptr\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] Ring read ptr mapped at 0x%08lx\n", - (unsigned long)info->ringReadPtr); - - if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize, - DRM_AGP, 0, &info->bufHandle) < 0) { - fprintf(stderr, - "[agp] Could not add vertex/indirect buffers mapping\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] vertex/indirect buffers handle = 0x%08lx\n", - info->bufHandle); - - if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize, - (drmAddressPtr)&info->buf) < 0) { - fprintf(stderr, - "[agp] Could not map vertex/indirect buffers\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] Vertex/indirect buffers mapped at 0x%08lx\n", - (unsigned long)info->buf); - - if (drmAddMap(ctx->drmFD, info->agpTexStart, info->agpTexMapSize, - DRM_AGP, 0, &info->agpTexHandle) < 0) { - fprintf(stderr, - "[agp] Could not add AGP texture map mapping\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] AGP texture map handle = 0x%08lx\n", - info->agpTexHandle); - - if (drmMap(ctx->drmFD, info->agpTexHandle, info->agpTexMapSize, - (drmAddressPtr)&info->agpTex) < 0) { - fprintf(stderr, - "[agp] Could not map AGP texture map\n"); - return GL_FALSE; - } - fprintf(stderr, - "[agp] AGP Texture map mapped at 0x%08lx\n", - (unsigned long)info->agpTex); - - /* Initialize Rage 128's AGP registers */ - cntl = INREG(R128_AGP_CNTL); - cntl &= ~R128_AGP_APER_SIZE_MASK; - switch (info->agpSize) { - case 256: cntl |= R128_AGP_APER_SIZE_256MB; break; - case 128: cntl |= R128_AGP_APER_SIZE_128MB; break; - case 64: cntl |= R128_AGP_APER_SIZE_64MB; break; - case 32: cntl |= R128_AGP_APER_SIZE_32MB; break; - case 16: cntl |= R128_AGP_APER_SIZE_16MB; break; - case 8: cntl |= R128_AGP_APER_SIZE_8MB; break; - case 4: cntl |= R128_AGP_APER_SIZE_4MB; break; - default: - fprintf(stderr, - "[agp] Illegal aperture size %d kB\n", - info->agpSize*1024); - return GL_FALSE; - } - agpBase = drmAgpBase(ctx->drmFD); - OUTREG(R128_AGP_BASE, agpBase); - OUTREG(R128_AGP_CNTL, cntl); - - /* Disable Rage 128's PCIGART registers */ - chunk = INREG(R128_BM_CHUNK_0_VAL); - chunk &= ~(R128_BM_PTR_FORCE_TO_PCI | - R128_BM_PM4_RD_FORCE_TO_PCI | - R128_BM_GLOBAL_FORCE_TO_PCI); - OUTREG(R128_BM_CHUNK_0_VAL, chunk); - - OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */ - - return GL_TRUE; -} - -static GLboolean R128DRIPciInit(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - unsigned char *R128MMIO = ctx->MMIOAddress; - uint32_t chunk; - int ret; - int flags; - - info->agpOffset = 0; - - ret = drmScatterGatherAlloc(ctx->drmFD, info->agpSize*1024*1024, - &info->pciMemHandle); - if (ret < 0) { - fprintf(stderr, "[pci] Out of memory (%d)\n", ret); - return GL_FALSE; - } - fprintf(stderr, - "[pci] %d kB allocated with handle 0x%08x\n", - info->agpSize*1024, info->pciMemHandle); - - /* Initialize the CCE ring buffer data */ - info->ringStart = info->agpOffset; - info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size; - info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1; - - info->ringReadOffset = info->ringStart + info->ringMapSize; - info->ringReadMapSize = r128_drm_page_size; - - /* Reserve space for vertex/indirect buffers */ - info->bufStart = info->ringReadOffset + info->ringReadMapSize; - info->bufMapSize = info->bufSize*1024*1024; - - flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; - - if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize, - DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) { - fprintf(stderr, - "[pci] Could not add ring mapping\n"); - return GL_FALSE; - } - fprintf(stderr, - "[pci] ring handle = 0x%08lx\n", info->ringHandle); - - if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize, - (drmAddressPtr)&info->ring) < 0) { - fprintf(stderr, "[pci] Could not map ring\n"); - return GL_FALSE; - } - fprintf(stderr, - "[pci] Ring mapped at 0x%08lx\n", - (unsigned long)info->ring); - fprintf(stderr, - "[pci] Ring contents 0x%08lx\n", - *(unsigned long *)info->ring); - - if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize, - DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) { - fprintf(stderr, - "[pci] Could not add ring read ptr mapping\n"); - return GL_FALSE; - } - fprintf(stderr, - "[pci] ring read ptr handle = 0x%08lx\n", - info->ringReadPtrHandle); - - if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, - (drmAddressPtr)&info->ringReadPtr) < 0) { - fprintf(stderr, - "[pci] Could not map ring read ptr\n"); - return GL_FALSE; - } - fprintf(stderr, - "[pci] Ring read ptr mapped at 0x%08lx\n", - (unsigned long)info->ringReadPtr); - fprintf(stderr, - "[pci] Ring read ptr contents 0x%08lx\n", - *(unsigned long *)info->ringReadPtr); - - if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize, - DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) { - fprintf(stderr, - "[pci] Could not add vertex/indirect buffers mapping\n"); - return GL_FALSE; - } - fprintf(stderr, - "[pci] vertex/indirect buffers handle = 0x%08lx\n", - info->bufHandle); - - if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize, - (drmAddressPtr)&info->buf) < 0) { - fprintf(stderr, - "[pci] Could not map vertex/indirect buffers\n"); - return GL_FALSE; - } - fprintf(stderr, - "[pci] Vertex/indirect buffers mapped at 0x%08lx\n", - (unsigned long)info->buf); - fprintf(stderr, - "[pci] Vertex/indirect buffers contents 0x%08lx\n", - *(unsigned long *)info->buf); - - if (!info->IsPCI) { - /* This is really an AGP card, force PCI GART mode */ - chunk = INREG(R128_BM_CHUNK_0_VAL); - chunk |= (R128_BM_PTR_FORCE_TO_PCI | - R128_BM_PM4_RD_FORCE_TO_PCI | - R128_BM_GLOBAL_FORCE_TO_PCI); - OUTREG(R128_BM_CHUNK_0_VAL, chunk); - OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */ - } - - return GL_TRUE; -} - -/* Add a map for the MMIO registers that will be accessed by any - DRI-based clients. */ -static GLboolean R128DRIMapInit(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - int flags; - - if (info->CCESecure) flags = DRM_READ_ONLY; - else flags = 0; - - /* Map registers */ - if (drmAddMap(ctx->drmFD, ctx->MMIOStart, ctx->MMIOSize, - DRM_REGISTERS, flags, &info->registerHandle) < 0) { - return GL_FALSE; - } - fprintf(stderr, - "[drm] register handle = 0x%08x\n", info->registerHandle); - - return GL_TRUE; -} - -/* Initialize the kernel data structures. */ -static int R128DRIKernelInit(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - drm_r128_init_t drmInfo; - - memset( &drmInfo, 0, sizeof(&drmInfo) ); - - drmInfo.func = R128_INIT_CCE; - drmInfo.sarea_priv_offset = sizeof(drm_sarea_t); - drmInfo.is_pci = info->IsPCI; - drmInfo.cce_mode = info->CCEMode; - drmInfo.cce_secure = info->CCESecure; - drmInfo.ring_size = info->ringSize*1024*1024; - drmInfo.usec_timeout = info->CCEusecTimeout; - - drmInfo.fb_bpp = ctx->bpp; - drmInfo.depth_bpp = ctx->bpp; - - drmInfo.front_offset = info->frontOffset; - drmInfo.front_pitch = info->frontPitch; - - drmInfo.back_offset = info->backOffset; - drmInfo.back_pitch = info->backPitch; - - drmInfo.depth_offset = info->depthOffset; - drmInfo.depth_pitch = info->depthPitch; - drmInfo.span_offset = info->spanOffset; - - drmInfo.fb_offset = info->LinearAddr; - drmInfo.mmio_offset = info->registerHandle; - drmInfo.ring_offset = info->ringHandle; - drmInfo.ring_rptr_offset = info->ringReadPtrHandle; - drmInfo.buffers_offset = info->bufHandle; - drmInfo.agp_textures_offset = info->agpTexHandle; - - if (drmCommandWrite(ctx->drmFD, DRM_R128_INIT, - &drmInfo, sizeof(drmInfo)) < 0) - return GL_FALSE; - - return GL_TRUE; -} - -/* Add a map for the vertex buffers that will be accessed by any - DRI-based clients. */ -static GLboolean R128DRIBufInit(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - /* Initialize vertex buffers */ - if (info->IsPCI) { - info->bufNumBufs = drmAddBufs(ctx->drmFD, - info->bufMapSize / R128_BUFFER_SIZE, - R128_BUFFER_SIZE, - DRM_SG_BUFFER, - info->bufStart); - } else { - info->bufNumBufs = drmAddBufs(ctx->drmFD, - info->bufMapSize / R128_BUFFER_SIZE, - R128_BUFFER_SIZE, - DRM_AGP_BUFFER, - info->bufStart); - } - if (info->bufNumBufs <= 0) { - fprintf(stderr, - "[drm] Could not create vertex/indirect buffers list\n"); - return GL_FALSE; - } - fprintf(stderr, - "[drm] Added %d %d byte vertex/indirect buffers\n", - info->bufNumBufs, R128_BUFFER_SIZE); - - if (!(info->buffers = drmMapBufs(ctx->drmFD))) { - fprintf(stderr, - "[drm] Failed to map vertex/indirect buffers list\n"); - return GL_FALSE; - } - fprintf(stderr, - "[drm] Mapped %d vertex/indirect buffers\n", - info->buffers->count); - - return GL_TRUE; -} - -static void R128DRIIrqInit(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - unsigned char *R128MMIO = ctx->MMIOAddress; - - if (!info->irq) { - info->irq = drmGetInterruptFromBusID( - ctx->drmFD, - ctx->pciBus, - ctx->pciDevice, - ctx->pciFunc); - - if((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) { - fprintf(stderr, - "[drm] failure adding irq handler, " - "there is a device already using that irq\n" - "[drm] falling back to irq-free operation\n"); - info->irq = 0; - } else { - info->gen_int_cntl = INREG( R128_GEN_INT_CNTL ); - } - } - - if (info->irq) - fprintf(stderr, - "[drm] dma control initialized, using IRQ %d\n", - info->irq); -} - -static int R128CCEStop(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - drm_r128_cce_stop_t stop; - int ret, i; - - stop.flush = 1; - stop.idle = 1; - - ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP, - &stop, sizeof(stop) ); - - if ( ret == 0 ) { - return 0; - } else if ( errno != EBUSY ) { - return -errno; - } - - stop.flush = 0; - - i = 0; - do { - ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP, - &stop, sizeof(stop) ); - } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); - - if ( ret == 0 ) { - return 0; - } else if ( errno != EBUSY ) { - return -errno; - } - - stop.idle = 0; - - if ( drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP, - &stop, sizeof(stop) )) { - return -errno; - } else { - return 0; - } -} - -/* Initialize the CCE state, and start the CCE (if used by the X server) */ -static void R128DRICCEInit(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - - /* Turn on bus mastering */ - info->BusCntl &= ~R128_BUS_MASTER_DIS; - - /* CCEMode is initialized in r128_driver.c */ - switch (info->CCEMode) { - case R128_PM4_NONPM4: info->CCEFifoSize = 0; break; - case R128_PM4_192PIO: info->CCEFifoSize = 192; break; - case R128_PM4_192BM: info->CCEFifoSize = 192; break; - case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break; - case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break; - case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break; - case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break; - case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break; - case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break; - case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break; - } - - /* Make sure the CCE is on for the X server */ - R128CCE_START(ctx, info); -} - - -static int R128MemoryInit(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - int width_bytes = ctx->shared.virtualWidth * ctx->cpp; - int cpp = ctx->cpp; - int bufferSize = ((ctx->shared.virtualHeight * width_bytes - + R128_BUFFER_ALIGN) - & ~R128_BUFFER_ALIGN); - int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes - + R128_BUFFER_ALIGN) - & ~R128_BUFFER_ALIGN); - int l; - - info->frontOffset = 0; - info->frontPitch = ctx->shared.virtualWidth; - - fprintf(stderr, - "Using %d MB AGP aperture\n", info->agpSize); - fprintf(stderr, - "Using %d MB for the ring buffer\n", info->ringSize); - fprintf(stderr, - "Using %d MB for vertex/indirect buffers\n", info->bufSize); - fprintf(stderr, - "Using %d MB for AGP textures\n", info->agpTexSize); - - /* Front, back and depth buffers - everything else texture?? - */ - info->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize; - - if (info->textureSize < 0) - return 0; - - l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS); - if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; - - /* Round the texture size up to the nearest whole number of - * texture regions. Again, be greedy about this, don't - * round down. - */ - info->log2TexGran = l; - info->textureSize = (info->textureSize >> l) << l; - - /* Set a minimum usable local texture heap size. This will fit - * two 256x256x32bpp textures. - */ - if (info->textureSize < 512 * 1024) { - info->textureOffset = 0; - info->textureSize = 0; - } - - /* Reserve space for textures */ - info->textureOffset = ((ctx->shared.fbSize - info->textureSize + - R128_BUFFER_ALIGN) & - ~R128_BUFFER_ALIGN); - - /* Reserve space for the shared depth - * buffer. - */ - info->depthOffset = ((info->textureOffset - depthSize + - R128_BUFFER_ALIGN) & - ~R128_BUFFER_ALIGN); - info->depthPitch = ctx->shared.virtualWidth; - - info->backOffset = ((info->depthOffset - bufferSize + - R128_BUFFER_ALIGN) & - ~R128_BUFFER_ALIGN); - info->backPitch = ctx->shared.virtualWidth; - - - fprintf(stderr, - "Will use back buffer at offset 0x%x\n", - info->backOffset); - fprintf(stderr, - "Will use depth buffer at offset 0x%x\n", - info->depthOffset); - fprintf(stderr, - "Will use %d kb for textures at offset 0x%x\n", - info->textureSize/1024, info->textureOffset); - - return 1; -} - - -/* Initialize the screen-specific data structures for the DRI and the - Rage 128. This is the main entry point to the device-specific - initialization code. It calls device-independent DRI functions to - create the DRI data structures and initialize the DRI state. */ -static GLboolean R128DRIScreenInit(DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - R128DRIPtr pR128DRI; - int err, major, minor, patch; - drmVersionPtr version; - drm_r128_sarea_t *pSAREAPriv; - - switch (ctx->bpp) { - case 8: - /* These modes are not supported (yet). */ - case 15: - case 24: - fprintf(stderr, - "[dri] R128DRIScreenInit failed (depth %d not supported). " - "[dri] Disabling DRI.\n", ctx->bpp); - return GL_FALSE; - - /* Only 16 and 32 color depths are supports currently. */ - case 16: - case 32: - break; - } - r128_drm_page_size = getpagesize(); - - info->registerSize = ctx->MMIOSize; - ctx->shared.SAREASize = SAREA_MAX; - - /* Note that drmOpen will try to load the kernel module, if needed. */ - ctx->drmFD = drmOpen("r128", NULL ); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - - /* Check the r128 DRM version */ - version = drmGetVersion(ctx->drmFD); - if (version) { - if (version->version_major != 2 || - version->version_minor < 2) { - /* incompatible drm version */ - fprintf(stderr, - "[dri] R128DRIScreenInit failed because of a version mismatch.\n" - "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n" - "[dri] Disabling the DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel); - drmFreeVersion(version); - return GL_FALSE; - } - info->drmMinor = version->version_minor; - drmFreeVersion(version); - } - - if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - if (drmAddMap( ctx->drmFD, - 0, - ctx->shared.SAREASize, - DRM_SHM, - DRM_CONTAINS_LOCK, - &ctx->shared.hSAREA) < 0) - { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap( ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - } - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - /* Need to AddMap the framebuffer and mmio regions here: - */ - if (drmAddMap( ctx->drmFD, - (drm_handle_t)ctx->FBStart, - ctx->FBSize, - DRM_FRAME_BUFFER, - 0, - &ctx->shared.hFrameBuffer) < 0) - { - fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); - return 0; - } - - fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", - ctx->shared.hFrameBuffer); - - if (!R128MemoryInit(ctx)) - return GL_FALSE; - - /* Initialize AGP */ - if (!info->IsPCI && !R128DRIAgpInit(ctx)) { - info->IsPCI = GL_TRUE; - fprintf(stderr, - "[agp] AGP failed to initialize -- falling back to PCI mode.\n"); - fprintf(stderr, - "[agp] Make sure you have the agpgart kernel module loaded.\n"); - } - - /* Initialize PCIGART */ - if (info->IsPCI && !R128DRIPciInit(ctx)) { - return GL_FALSE; - } - - /* DRIScreenInit doesn't add all the - common mappings. Add additional - mappings here. */ - if (!R128DRIMapInit(ctx)) { - return GL_FALSE; - } - - /* Create a 'server' context so we can grab the lock for - * initialization ioctls. - */ - if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return 0; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - /* Initialize the kernel data structures */ - if (!R128DRIKernelInit(ctx)) { - return GL_FALSE; - } - - /* Initialize the vertex buffers list */ - if (!R128DRIBufInit(ctx)) { - return GL_FALSE; - } - - /* Initialize IRQ */ - R128DRIIrqInit(ctx); - - /* Initialize and start the CCE if required */ - R128DRICCEInit(ctx); - - /* Quick hack to clear the front & back buffers. Could also use - * the clear ioctl to do this, but would need to setup hw state - * first. - */ - drimemsetio((char *)ctx->FBAddress + info->frontOffset, - 0, - info->frontPitch * ctx->cpp * ctx->shared.virtualHeight ); - - drimemsetio((char *)ctx->FBAddress + info->backOffset, - 0, - info->backPitch * ctx->cpp * ctx->shared.virtualHeight ); - - pSAREAPriv = (drm_r128_sarea_t *)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); - - /* This is the struct passed to radeon_dri.so for its initialization */ - ctx->driverClientMsg = malloc(sizeof(R128DRIRec)); - ctx->driverClientMsgSize = sizeof(R128DRIRec); - - pR128DRI = (R128DRIPtr)ctx->driverClientMsg; - pR128DRI->deviceID = info->Chipset; - pR128DRI->width = ctx->shared.virtualWidth; - pR128DRI->height = ctx->shared.virtualHeight; - pR128DRI->depth = ctx->bpp; - pR128DRI->bpp = ctx->bpp; - - pR128DRI->IsPCI = info->IsPCI; - pR128DRI->AGPMode = info->agpMode; - - pR128DRI->frontOffset = info->frontOffset; - pR128DRI->frontPitch = info->frontPitch; - pR128DRI->backOffset = info->backOffset; - pR128DRI->backPitch = info->backPitch; - pR128DRI->depthOffset = info->depthOffset; - pR128DRI->depthPitch = info->depthPitch; - pR128DRI->spanOffset = info->spanOffset; - pR128DRI->textureOffset = info->textureOffset; - pR128DRI->textureSize = info->textureSize; - pR128DRI->log2TexGran = info->log2TexGran; - - pR128DRI->registerHandle = info->registerHandle; - pR128DRI->registerSize = info->registerSize; - - pR128DRI->agpTexHandle = info->agpTexHandle; - pR128DRI->agpTexMapSize = info->agpTexMapSize; - pR128DRI->log2AGPTexGran = info->log2AGPTexGran; - pR128DRI->agpTexOffset = info->agpTexStart; - pR128DRI->sarea_priv_offset = sizeof(drm_sarea_t); - - return GL_TRUE; -} - -/* The screen is being closed, so clean up any state and free any - resources used by the DRI. */ -void R128DRICloseScreen(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - drm_r128_init_t drmInfo; - - /* Stop the CCE if it is still in use */ - R128CCE_STOP(ctx, info); - - if (info->irq) { - drmCtlUninstHandler(ctx->drmFD); - info->irq = 0; - } - - /* De-allocate vertex buffers */ - if (info->buffers) { - drmUnmapBufs(info->buffers); - info->buffers = NULL; - } - - /* De-allocate all kernel resources */ - memset(&drmInfo, 0, sizeof(drmInfo)); - drmInfo.func = R128_CLEANUP_CCE; - drmCommandWrite(ctx->drmFD, DRM_R128_INIT, - &drmInfo, sizeof(drmInfo)); - - /* De-allocate all AGP resources */ - if (info->agpTex) { - drmUnmap(info->agpTex, info->agpTexMapSize); - info->agpTex = NULL; - } - if (info->buf) { - drmUnmap(info->buf, info->bufMapSize); - info->buf = NULL; - } - if (info->ringReadPtr) { - drmUnmap(info->ringReadPtr, info->ringReadMapSize); - info->ringReadPtr = NULL; - } - if (info->ring) { - drmUnmap(info->ring, info->ringMapSize); - info->ring = NULL; - } - if (info->agpMemHandle != DRM_AGP_NO_HANDLE) { - drmAgpUnbind(ctx->drmFD, info->agpMemHandle); - drmAgpFree(ctx->drmFD, info->agpMemHandle); - info->agpMemHandle = 0; - drmAgpRelease(ctx->drmFD); - } - if (info->pciMemHandle) { - drmScatterGatherFree(ctx->drmFD, info->pciMemHandle); - info->pciMemHandle = 0; - } -} - -static GLboolean R128PreInitDRI(const DRIDriverContext *ctx) -{ - R128InfoPtr info = ctx->driverPrivate; - - /*info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;*/ - info->CCEMode = R128_DEFAULT_CCE_BM_MODE; - info->CCESecure = GL_TRUE; - - info->agpMode = R128_DEFAULT_AGP_MODE; - info->agpSize = R128_DEFAULT_AGP_SIZE; - info->ringSize = R128_DEFAULT_RING_SIZE; - info->bufSize = R128_DEFAULT_BUFFER_SIZE; - info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE; - - info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT; - - return GL_TRUE; -} - -/** - * \brief Initialize the framebuffer device mode - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Fills in \p info with some default values and some information from \p ctx - * and then calls R128ScreenInit() for the screen initialization. - * - * Before exiting clears the framebuffer memory accessing it directly. - */ -static int R128InitFBDev( DRIDriverContext *ctx ) -{ - R128InfoPtr info = calloc(1, sizeof(*info)); - - { - int dummy = ctx->shared.virtualWidth; - - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; - } - - ctx->shared.virtualWidth = dummy; - } - - ctx->driverPrivate = (void *)info; - - info->Chipset = ctx->chipset; - - switch (info->Chipset) { - case PCI_DEVICE_ID_ATI_RAGE128_LE: - case PCI_DEVICE_ID_ATI_RAGE128_RE: - case PCI_DEVICE_ID_ATI_RAGE128_RK: - case PCI_DEVICE_ID_ATI_RAGE128_PD: - case PCI_DEVICE_ID_ATI_RAGE128_PP: - case PCI_DEVICE_ID_ATI_RAGE128_PR: - /* This is a PCI card */ - info->IsPCI = GL_TRUE; - break; - default: - /* This is an AGP card */ - info->IsPCI = GL_FALSE; - break; - } - - info->frontPitch = ctx->shared.virtualWidth; - info->LinearAddr = ctx->FBStart & 0xfc000000; - - if (!R128PreInitDRI(ctx)) - return 0; - - if (!R128DRIScreenInit(ctx)) - return 0; - - return 1; -} - - -/** - * \brief The screen is being closed, so clean up any state and free any - * resources used by the DRI. - * - * \param ctx display handle. - * - * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver - * private data. - */ -static void R128HaltFBDev( DRIDriverContext *ctx ) -{ - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = 0; - } -} - - -/** - * \brief Validate the fbdev mode. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Saves some registers and returns 1. - * - * \sa R128PostValidateMode(). - */ -static int R128ValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - - -/** - * \brief Examine mode returned by fbdev. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Restores registers that fbdev has clobbered and returns 1. - * - * \sa R128ValidateMode(). - */ -static int R128PostValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - - -/** - * \brief Shutdown the drawing engine. - * - * \param ctx display handle - * - * Turns off the command processor engine & restores the graphics card - * to a state that fbdev understands. - */ -static int R128EngineShutdown( const DRIDriverContext *ctx ) -{ - return 1; -} - -/** - * \brief Restore the drawing engine. - * - * \param ctx display handle - * - * Resets the graphics card and sets initial values for several registers of - * the card's drawing engine. - * - * Turns on the R128 command processor engine (i.e., the ringbuffer). - */ -static int R128EngineRestore( const DRIDriverContext *ctx ) -{ - return 1; -} - - -/** - * \brief Exported driver interface for Mini GLX. - * - * \sa DRIDriverRec. - */ -const struct DRIDriverRec __driDriver = { - R128ValidateMode, - R128PostValidateMode, - R128InitFBDev, - R128HaltFBDev, - R128EngineShutdown, - R128EngineRestore, - 0, -}; diff --git a/src/mesa/drivers/dri/r200/Makefile b/src/mesa/drivers/dri/r200/Makefile index 14eb96c1bab..c9c1346c3a2 100644 --- a/src/mesa/drivers/dri/r200/Makefile +++ b/src/mesa/drivers/dri/r200/Makefile @@ -7,8 +7,6 @@ CFLAGS += $(RADEON_CFLAGS) LIBNAME = r200_dri.so -MINIGLX_SOURCES = server/radeon_dri.c - ifeq ($(RADEON_LDFLAGS),) CS_SOURCES = radeon_cs_space_drm.c radeon_bo.c radeon_cs.c endif @@ -23,17 +21,19 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ + radeon_pixel_read.c \ radeon_queryobj.c \ radeon_span.c \ radeon_texture.c \ - radeon_tex_copy.c + radeon_tex_copy.c \ + radeon_tex_getimage.c \ + radeon_tile.c DRIVER_SOURCES = r200_context.c \ r200_ioctl.c \ r200_state.c \ r200_state_init.c \ r200_cmdbuf.c \ - r200_pixel.c \ r200_tex.c \ r200_texstate.c \ r200_tcl.c \ diff --git a/src/mesa/drivers/dri/r200/r200_blit.c b/src/mesa/drivers/dri/r200/r200_blit.c index 30757600934..e187fc0f61e 100644 --- a/src/mesa/drivers/dri/r200/r200_blit.c +++ b/src/mesa/drivers/dri/r200/r200_blit.c @@ -48,6 +48,11 @@ unsigned r200_check_blit(gl_format mesa_format) case MESA_FORMAT_ARGB4444: case MESA_FORMAT_ARGB1555: case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + /* swizzled */ + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: break; default: return 0; @@ -86,7 +91,8 @@ static inline void emit_vtx_state(struct r200_context *r200) } static void inline emit_tx_setup(struct r200_context *r200, - gl_format mesa_format, + gl_format src_mesa_format, + gl_format dst_mesa_format, struct radeon_bo *bo, intptr_t offset, unsigned width, @@ -101,10 +107,16 @@ static void inline emit_tx_setup(struct r200_context *r200, assert(offset % 32 == 0); /* XXX others? BE/LE? */ - switch (mesa_format) { + switch (src_mesa_format) { case MESA_FORMAT_ARGB8888: txformat |= R200_TXFORMAT_ARGB8888 | R200_TXFORMAT_ALPHA_IN_MAP; break; + case MESA_FORMAT_RGBA8888: + txformat |= R200_TXFORMAT_RGBA8888 | R200_TXFORMAT_ALPHA_IN_MAP; + break; + case MESA_FORMAT_RGBA8888_REV: + txformat |= R200_TXFORMAT_ABGR8888 | R200_TXFORMAT_ALPHA_IN_MAP; + break; case MESA_FORMAT_XRGB8888: txformat |= R200_TXFORMAT_ARGB8888; break; @@ -118,26 +130,143 @@ static void inline emit_tx_setup(struct r200_context *r200, txformat |= R200_TXFORMAT_ARGB1555 | R200_TXFORMAT_ALPHA_IN_MAP; break; case MESA_FORMAT_A8: + case MESA_FORMAT_I8: txformat |= R200_TXFORMAT_I8 | R200_TXFORMAT_ALPHA_IN_MAP; break; + case MESA_FORMAT_L8: + txformat |= R200_TXFORMAT_I8; + break; + case MESA_FORMAT_AL88: + txformat |= R200_TXFORMAT_AI88 | R200_TXFORMAT_ALPHA_IN_MAP; + break; + default: + break; + } + + switch (dst_mesa_format) { + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_RGB565: + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: default: + /* no swizzle required */ + BEGIN_BATCH(10); + OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | + RADEON_TEX_BLEND_0_ENABLE)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | + R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_R0_COLOR | + R200_TXC_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | + R200_TXC_OUTPUT_REG_R0)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | + R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_R0_ALPHA | + R200_TXA_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | + R200_TXA_OUTPUT_REG_R0)); + END_BATCH(); + break; + case MESA_FORMAT_RGBA8888: + BEGIN_BATCH(10); + OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | + RADEON_TEX_BLEND_0_ENABLE)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | + R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_R0_COLOR | + R200_TXC_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | + R200_TXC_OUTPUT_ROTATE_GBA | + R200_TXC_OUTPUT_REG_R0)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | + R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_R0_ALPHA | + R200_TXA_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | + (R200_TXA_REPL_RED << R200_TXA_REPL_ARG_C_SHIFT) | + R200_TXA_OUTPUT_REG_R0)); + END_BATCH(); + break; + case MESA_FORMAT_RGBA8888_REV: + BEGIN_BATCH(34); + OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | + RADEON_TEX_BLEND_0_ENABLE | + RADEON_TEX_BLEND_1_ENABLE | + RADEON_TEX_BLEND_2_ENABLE | + RADEON_TEX_BLEND_3_ENABLE)); + /* r1.r = r0.b */ + OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | + R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_R0_COLOR | + R200_TXC_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | + R200_TXC_OUTPUT_MASK_R | + (R200_TXC_REPL_BLUE << R200_TXC_REPL_ARG_C_SHIFT) | + R200_TXC_OUTPUT_REG_R1)); + /* r1.a = r0.a */ + OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | + R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_R0_ALPHA | + R200_TXA_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | + R200_TXA_OUTPUT_REG_R1)); + /* r1.g = r0.g */ + OUT_BATCH_REGVAL(R200_PP_TXCBLEND_1, (R200_TXC_ARG_A_ZERO | + R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_R0_COLOR | + R200_TXC_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_1, (R200_TXC_CLAMP_0_1 | + R200_TXC_OUTPUT_MASK_G | + (R200_TXC_REPL_GREEN << R200_TXC_REPL_ARG_C_SHIFT) | + R200_TXC_OUTPUT_REG_R1)); + /* r1.a = r0.a */ + OUT_BATCH_REGVAL(R200_PP_TXABLEND_1, (R200_TXA_ARG_A_ZERO | + R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_R0_ALPHA | + R200_TXA_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND2_1, (R200_TXA_CLAMP_0_1 | + R200_TXA_OUTPUT_REG_R1)); + /* r1.b = r0.r */ + OUT_BATCH_REGVAL(R200_PP_TXCBLEND_2, (R200_TXC_ARG_A_ZERO | + R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_R0_COLOR | + R200_TXC_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_2, (R200_TXC_CLAMP_0_1 | + R200_TXC_OUTPUT_MASK_B | + (R200_TXC_REPL_RED << R200_TXC_REPL_ARG_C_SHIFT) | + R200_TXC_OUTPUT_REG_R1)); + /* r1.a = r0.a */ + OUT_BATCH_REGVAL(R200_PP_TXABLEND_2, (R200_TXA_ARG_A_ZERO | + R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_R0_ALPHA | + R200_TXA_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND2_2, (R200_TXA_CLAMP_0_1 | + R200_TXA_OUTPUT_REG_R1)); + /* r0.rgb = r1.rgb */ + OUT_BATCH_REGVAL(R200_PP_TXCBLEND_3, (R200_TXC_ARG_A_ZERO | + R200_TXC_ARG_B_ZERO | + R200_TXC_ARG_C_R1_COLOR | + R200_TXC_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_3, (R200_TXC_CLAMP_0_1 | + R200_TXC_OUTPUT_REG_R0)); + /* r0.a = r1.a */ + OUT_BATCH_REGVAL(R200_PP_TXABLEND_3, (R200_TXA_ARG_A_ZERO | + R200_TXA_ARG_B_ZERO | + R200_TXA_ARG_C_R1_ALPHA | + R200_TXA_OP_MADD)); + OUT_BATCH_REGVAL(R200_PP_TXABLEND2_3, (R200_TXA_CLAMP_0_1 | + R200_TXA_OUTPUT_REG_R0)); + END_BATCH(); break; } - BEGIN_BATCH(28); - OUT_BATCH_REGVAL(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); + BEGIN_BATCH(18); OUT_BATCH_REGVAL(R200_PP_CNTL_X, 0); OUT_BATCH_REGVAL(R200_PP_TXMULTI_CTL_0, 0); - OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | - R200_TXC_ARG_B_ZERO | - R200_TXC_ARG_C_R0_COLOR | - R200_TXC_OP_MADD)); - OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0); - OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | - R200_TXA_ARG_B_ZERO | - R200_TXA_ARG_C_R0_ALPHA | - R200_TXA_OP_MADD)); - OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0); OUT_BATCH_REGVAL(R200_PP_TXFILTER_0, (R200_CLAMP_S_CLAMP_LAST | R200_CLAMP_T_CLAMP_LAST | R200_MAG_FILTER_NEAREST | @@ -146,7 +275,7 @@ static void inline emit_tx_setup(struct r200_context *r200, OUT_BATCH_REGVAL(R200_PP_TXFORMAT_X_0, 0); OUT_BATCH_REGVAL(R200_PP_TXSIZE_0, ((width - 1) | ((height - 1) << RADEON_TEX_VSIZE_SHIFT))); - OUT_BATCH_REGVAL(R200_PP_TXPITCH_0, pitch * _mesa_get_format_bytes(mesa_format) - 32); + OUT_BATCH_REGVAL(R200_PP_TXPITCH_0, pitch * _mesa_get_format_bytes(src_mesa_format) - 32); OUT_BATCH_REGSEQ(R200_PP_TXOFFSET_0, 1); OUT_BATCH_RELOC(0, bo, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); @@ -170,6 +299,8 @@ static inline void emit_cb_setup(struct r200_context *r200, switch (mesa_format) { case MESA_FORMAT_ARGB8888: case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: dst_format = RADEON_COLOR_FORMAT_ARGB8888; break; case MESA_FORMAT_RGB565: @@ -182,6 +313,8 @@ static inline void emit_cb_setup(struct r200_context *r200, dst_format = RADEON_COLOR_FORMAT_ARGB1555; break; case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: dst_format = RADEON_COLOR_FORMAT_RGB8; break; default: @@ -384,15 +517,15 @@ unsigned r200_blit(GLcontext *ctx, /* Flush is needed to make sure that source buffer has correct data */ radeonFlush(r200->radeon.glCtx); - rcommonEnsureCmdBufSpace(&r200->radeon, 78, __FUNCTION__); + rcommonEnsureCmdBufSpace(&r200->radeon, 102, __FUNCTION__); if (!validate_buffers(r200, src_bo, dst_bo)) return GL_FALSE; /* 14 */ emit_vtx_state(r200); - /* 28 */ - emit_tx_setup(r200, src_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch); + /* 52 */ + emit_tx_setup(r200, src_mesaformat, dst_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch); /* 22 */ emit_cb_setup(r200, dst_bo, dst_offset, dst_mesaformat, dst_pitch, dst_width, dst_height); /* 14 */ diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c index dad2580e08b..36a29350ccc 100644 --- a/src/mesa/drivers/dri/r200/r200_context.c +++ b/src/mesa/drivers/dri/r200/r200_context.c @@ -51,7 +51,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r200_context.h" #include "r200_ioctl.h" #include "r200_state.h" -#include "r200_pixel.h" #include "r200_tex.h" #include "r200_swtcl.h" #include "r200_tcl.h" @@ -266,6 +265,7 @@ static void r200_init_vtbl(radeonContextPtr radeon) radeon->vtbl.emit_query_finish = r200_emit_query_finish; radeon->vtbl.check_blit = r200_check_blit; radeon->vtbl.blit = r200_blit; + radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; } @@ -324,7 +324,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual, _mesa_init_driver_functions(&functions); r200InitDriverFuncs(&functions); r200InitIoctlFuncs(&functions); - r200InitStateFuncs(&functions); + r200InitStateFuncs(&rmesa->radeon, &functions); r200InitTextureFuncs(&rmesa->radeon, &functions); r200InitShaderFuncs(&functions); radeonInitQueryObjFunctions(&functions); @@ -473,7 +473,6 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual, /* XXX these should really go right after _mesa_init_driver_functions() */ radeon_fbo_init(&rmesa->radeon); radeonInitSpanFuncs( ctx ); - r200InitPixelFuncs( ctx ); r200InitTnlFuncs( ctx ); r200InitState( rmesa ); r200InitSwtcl( ctx ); diff --git a/src/mesa/drivers/dri/r200/r200_pixel.c b/src/mesa/drivers/dri/r200/r200_pixel.c deleted file mode 100644 index bfb7e2a2ed3..00000000000 --- a/src/mesa/drivers/dri/r200/r200_pixel.c +++ /dev/null @@ -1,494 +0,0 @@ -/* -Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. - -The Weather Channel (TM) funded Tungsten Graphics to develop the -initial release of the Radeon 8500 driver under the XFree86 license. -This notice must be preserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* - * Authors: - * Keith Whitwell <[email protected]> - */ - -#include "main/glheader.h" -#include "main/enums.h" -#include "main/mtypes.h" -#include "main/macros.h" -#include "swrast/swrast.h" - -#include "r200_context.h" -#include "r200_ioctl.h" -#include "r200_pixel.h" -#include "r200_swtcl.h" - -#include "drirenderbuffer.h" - - -static GLboolean -check_color( const GLcontext *ctx, GLenum type, GLenum format, - const struct gl_pixelstore_attrib *packing, - const void *pixels, GLint sz, GLint pitch ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint cpp = rmesa->radeon.radeonScreen->cpp; - - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s\n", __FUNCTION__); - - if ( (pitch & 63) || - ctx->_ImageTransferState || - packing->SwapBytes || - packing->LsbFirst) { - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s: failed 1\n", __FUNCTION__); - return GL_FALSE; - } - - if ( type == GL_UNSIGNED_INT_8_8_8_8_REV && - cpp == 4 && - format == GL_BGRA ) { - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s: passed 2\n", __FUNCTION__); - return GL_TRUE; - } - - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s: failed\n", __FUNCTION__); - - return GL_FALSE; -} - -static GLboolean -check_color_per_fragment_ops( const GLcontext *ctx ) -{ - int result; - result = (!( ctx->Color.AlphaEnabled || - ctx->Depth.Test || - ctx->Fog.Enabled || - ctx->Scissor.Enabled || - ctx->Stencil._Enabled || - !ctx->Color.ColorMask[0][0] || - !ctx->Color.ColorMask[0][1] || - !ctx->Color.ColorMask[0][2] || - !ctx->Color.ColorMask[0][3] || - ctx->Color.ColorLogicOpEnabled || - ctx->Texture._EnabledUnits - ) && - ctx->Current.RasterPosValid); - - return result; -} - - -#if 0 -static GLboolean -clip_pixelrect( const GLcontext *ctx, - const GLframebuffer *buffer, - GLint *x, GLint *y, - GLsizei *width, GLsizei *height, - GLint *size ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - - /* left clipping */ - if (*x < buffer->_Xmin) { - *width -= (buffer->_Xmin - *x); - *x = buffer->_Xmin; - } - - /* right clipping */ - if (*x + *width > buffer->_Xmax) - *width -= (*x + *width - buffer->_Xmax - 1); - - if (*width <= 0) - return GL_FALSE; - - /* bottom clipping */ - if (*y < buffer->_Ymin) { - *height -= (buffer->_Ymin - *y); - *y = buffer->_Ymin; - } - - /* top clipping */ - if (*y + *height > buffer->_Ymax) - *height -= (*y + *height - buffer->_Ymax - 1); - - if (*height <= 0) - return GL_FALSE; - - *size = ((*y + *height - 1) * rmesa->radeon.radeonScreen->frontPitch + - (*x + *width - 1) * rmesa->radeon.radeonScreen->cpp); - - return GL_TRUE; -} -#endif - -static GLboolean -r200TryReadPixels( GLcontext *ctx, - GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, - const struct gl_pixelstore_attrib *pack, - GLvoid *pixels ) -{ - return GL_FALSE; -#if 0 - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLint pitch = pack->RowLength ? pack->RowLength : width; - GLint blit_format; - GLuint cpp = rmesa->radeon.radeonScreen->cpp; - GLint size = width * height * cpp; - - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s\n", __FUNCTION__); - - /* Only accelerate reading to GART buffers. - */ - if ( !r200IsGartMemory(rmesa, pixels, - pitch * height * rmesa->radeon.radeonScreen->cpp ) ) { - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s: dest not GART\n", __FUNCTION__); - } - - /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from - * blitter: - */ - if (!pack->Invert) { - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); - return GL_FALSE; - } - - if (!check_color(ctx, type, format, pack, pixels, size, pitch)) - return GL_FALSE; - - switch ( rmesa->radeon.radeonScreen->cpp ) { - case 4: - blit_format = R200_CP_COLOR_FORMAT_ARGB8888; - break; - default: - return GL_FALSE; - } - - - /* Although the blits go on the command buffer, need to do this and - * fire with lock held to guarentee cliprects and drawOffset are - * correct. - * - * This is an unusual situation however, as the code which flushes - * a full command buffer expects to be called unlocked. As a - * workaround, immediately flush the buffer on aquiring the lock. - */ - LOCK_HARDWARE( &rmesa->radeon ); - - if (rmesa->store.cmd_used) - rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ ); - - if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, - &size)) { - UNLOCK_HARDWARE( &rmesa->radeon ); - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s totally clipped -- nothing to do\n", - __FUNCTION__); - return GL_TRUE; - } - - { - __DRIdrawable *dPriv = rmesa->radeon.dri.drawable; - driRenderbuffer *drb = (driRenderbuffer *) ctx->ReadBuffer->_ColorReadBuffer; - int nbox = dPriv->numClipRects; - int src_offset = drb->offset - + rmesa->radeon.radeonScreen->fbLocation; - int src_pitch = drb->pitch * drb->cpp; - int dst_offset = r200GartOffsetFromVirtual( rmesa, pixels ); - int dst_pitch = pitch * rmesa->radeon.radeonScreen->cpp; - drm_clip_rect_t *box = dPriv->pClipRects; - int i; - - r200EmitWait( rmesa, RADEON_WAIT_3D ); - - y = dPriv->h - y - height; - x += dPriv->x; - y += dPriv->y; - - - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", - src_pitch, dst_pitch); - - for (i = 0 ; i < nbox ; i++) - { - GLint bx = box[i].x1; - GLint by = box[i].y1; - GLint bw = box[i].x2 - bx; - GLint bh = box[i].y2 - by; - - if (bx < x) bw -= x - bx, bx = x; - if (by < y) bh -= y - by, by = y; - if (bx + bw > x + width) bw = x + width - bx; - if (by + bh > y + height) bh = y + height - by; - if (bw <= 0) continue; - if (bh <= 0) continue; - - r200EmitBlit( rmesa, - blit_format, - src_pitch, src_offset, - dst_pitch, dst_offset, - bx, by, - bx - x, by - y, - bw, bh ); - } - - rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ ); - } - UNLOCK_HARDWARE( &rmesa->radeon ); - - radeonFinish( ctx ); /* required by GL */ -#endif - return GL_TRUE; -} - -static void -r200ReadPixels( GLcontext *ctx, - GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, - const struct gl_pixelstore_attrib *pack, - GLvoid *pixels ) -{ - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s\n", __FUNCTION__); - - if (!r200TryReadPixels( ctx, x, y, width, height, format, type, pack, - pixels)) - _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, - pixels); -} - - - - -static void do_draw_pix( GLcontext *ctx, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint pitch, - const void *pixels, - GLuint planemask) -{ - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s\n", __FUNCTION__); - -#if 0 - r200ContextPtr rmesa = R200_CONTEXT(ctx); - __DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon); - drm_clip_rect_t *box = dPriv->pClipRects; - struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorDrawBuffers[0]; - driRenderbuffer *drb = (driRenderbuffer *) rb; - int nbox = dPriv->numClipRects; - int i; - int blit_format; - int size; - int src_offset = r200GartOffsetFromVirtual( rmesa, pixels ); - int src_pitch = pitch * rmesa->radeon.radeonScreen->cpp; - - switch ( rmesa->radeon.radeonScreen->cpp ) { - case 2: - blit_format = R200_CP_COLOR_FORMAT_RGB565; - break; - case 4: - blit_format = R200_CP_COLOR_FORMAT_ARGB8888; - break; - default: - return; - } - - - LOCK_HARDWARE( &rmesa->radeon ); - - if (rmesa->store.cmd_used) - rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ ); - - y -= height; /* cope with pixel zoom */ - - if (!clip_pixelrect(ctx, ctx->DrawBuffer, - &x, &y, &width, &height, - &size)) { - UNLOCK_HARDWARE( &rmesa->radeon ); - return; - } - - y = dPriv->h - y - height; /* convert from gl to hardware coords */ - x += dPriv->x; - y += dPriv->y; - - - r200EmitWait( rmesa, RADEON_WAIT_3D ); - - for (i = 0 ; i < nbox ; i++ ) - { - GLint bx = box[i].x1; - GLint by = box[i].y1; - GLint bw = box[i].x2 - bx; - GLint bh = box[i].y2 - by; - - if (bx < x) bw -= x - bx, bx = x; - if (by < y) bh -= y - by, by = y; - if (bx + bw > x + width) bw = x + width - bx; - if (by + bh > y + height) bh = y + height - by; - if (bw <= 0) continue; - if (bh <= 0) continue; - - r200EmitBlit( rmesa, - blit_format, - src_pitch, src_offset, - drb->pitch * drb->cpp, - drb->offset + rmesa->radeon.radeonScreen->fbLocation, - bx - x, by - y, - bx, by, - bw, bh ); - } - - rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ ); - radeonWaitForIdleLocked( &rmesa->radeon ); /* required by GL */ - UNLOCK_HARDWARE( &rmesa->radeon ); -#endif -} - - - - -static GLboolean -r200TryDrawPixels( GLcontext *ctx, - GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, - const struct gl_pixelstore_attrib *unpack, - const GLvoid *pixels ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLint pitch = unpack->RowLength ? unpack->RowLength : width; - GLuint planemask; - GLuint cpp = rmesa->radeon.radeonScreen->cpp; - GLint size = height * pitch * cpp; - - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s\n", __FUNCTION__); - - /* check that we're drawing to exactly one color buffer */ - if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) - return GL_FALSE; - - switch (format) { - case GL_RGB: - case GL_RGBA: - case GL_BGRA: - planemask = radeonPackColor(cpp, - ctx->Color.ColorMask[0][RCOMP], - ctx->Color.ColorMask[0][GCOMP], - ctx->Color.ColorMask[0][BCOMP], - ctx->Color.ColorMask[0][ACOMP]); - - if (cpp == 2) - planemask |= planemask << 16; - - if (planemask != ~0) - return GL_FALSE; /* fix me -- should be possible */ - - /* Can't do conversions on GART reads/draws. - */ - if ( !r200IsGartMemory( rmesa, pixels, size ) ) { - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s: not GART memory\n", __FUNCTION__); - return GL_FALSE; - } - - if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { - return GL_FALSE; - } - if (!check_color_per_fragment_ops(ctx)) { - return GL_FALSE; - } - - if (ctx->Pixel.ZoomX != 1.0F || - ctx->Pixel.ZoomY != -1.0F) - return GL_FALSE; - break; - - default: - return GL_FALSE; - } - - if (0)// r200IsGartMemory(rmesa, pixels, size) ) - { - do_draw_pix( ctx, x, y, width, height, pitch, pixels, planemask ); - return GL_TRUE; - } - else if (0) - { - /* Pixels is in regular memory -- get dma buffers and perform - * upload through them. - */ - } - else - return GL_FALSE; -} - -static void -r200DrawPixels( GLcontext *ctx, - GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, - const struct gl_pixelstore_attrib *unpack, - const GLvoid *pixels ) -{ - if (R200_DEBUG & RADEON_PIXEL) - fprintf(stderr, "%s\n", __FUNCTION__); - - if (!r200TryDrawPixels( ctx, x, y, width, height, format, type, - unpack, pixels )) - _swrast_DrawPixels( ctx, x, y, width, height, format, type, - unpack, pixels ); -} - - -static void -r200Bitmap( GLcontext *ctx, GLint px, GLint py, - GLsizei width, GLsizei height, - const struct gl_pixelstore_attrib *unpack, - const GLubyte *bitmap ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - - if (rmesa->radeon.Fallback) - _swrast_Bitmap( ctx, px, py, width, height, unpack, bitmap ); - else - r200PointsBitmap( ctx, px, py, width, height, unpack, bitmap ); -} - - - -void r200InitPixelFuncs( GLcontext *ctx ) -{ - if (!getenv("R200_NO_BLITS")) { - ctx->Driver.ReadPixels = r200ReadPixels; - ctx->Driver.DrawPixels = r200DrawPixels; - if (getenv("R200_HW_BITMAP")) - ctx->Driver.Bitmap = r200Bitmap; - } -} diff --git a/src/mesa/drivers/dri/r200/r200_pixel.h b/src/mesa/drivers/dri/r200/r200_pixel.h deleted file mode 100644 index e62aa05d749..00000000000 --- a/src/mesa/drivers/dri/r200/r200_pixel.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. - -The Weather Channel (TM) funded Tungsten Graphics to develop the -initial release of the Radeon 8500 driver under the XFree86 license. -This notice must be preserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* - * Authors: - * Keith Whitwell <[email protected]> - */ - -#ifndef __R200_PIXEL_H__ -#define __R200_PIXEL_H__ - -extern void r200InitPixelFuncs( GLcontext *ctx ); - -#endif diff --git a/src/mesa/drivers/dri/r200/r200_reg.h b/src/mesa/drivers/dri/r200/r200_reg.h index b3a4940a7ad..e331be223b8 100644 --- a/src/mesa/drivers/dri/r200/r200_reg.h +++ b/src/mesa/drivers/dri/r200/r200_reg.h @@ -1265,6 +1265,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_TXC_OUTPUT_MASK_G (5 << 20) #define R200_TXC_OUTPUT_MASK_B (6 << 20) #define R200_TXC_OUTPUT_MASK_NONE (7 << 20) +#define R200_TXC_OUTPUT_ROTATE_RGB (0 << 24) +#define R200_TXC_OUTPUT_ROTATE_ARG (1 << 24) +#define R200_TXC_OUTPUT_ROTATE_GBA (2 << 24) +#define R200_TXC_OUTPUT_ROTATE_RGA (3 << 24) #define R200_TXC_REPL_NORMAL 0 #define R200_TXC_REPL_RED 1 #define R200_TXC_REPL_GREEN 2 diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c index 050e5aa8770..9c2ac05ad6c 100644 --- a/src/mesa/drivers/dri/r200/r200_state.c +++ b/src/mesa/drivers/dri/r200/r200_state.c @@ -46,6 +46,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tnl/tnl.h" #include "tnl/t_pipeline.h" #include "swrast_setup/swrast_setup.h" +#include "drivers/common/meta.h" #include "radeon_common.h" #include "radeon_mipmap_tree.h" @@ -2487,7 +2488,7 @@ static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask ) } /* Initialize the driver's state functions. */ -void r200InitStateFuncs( struct dd_function_table *functions ) +void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions ) { functions->UpdateState = r200InvalidateState; functions->LightingSpaceChange = r200LightingSpaceChange; @@ -2495,6 +2496,12 @@ void r200InitStateFuncs( struct dd_function_table *functions ) functions->DrawBuffer = radeonDrawBuffer; functions->ReadBuffer = radeonReadBuffer; + if (radeon->radeonScreen->kernel_mm) { + functions->CopyPixels = _mesa_meta_CopyPixels; + functions->DrawPixels = _mesa_meta_DrawPixels; + functions->ReadPixels = radeonReadPixels; + } + functions->AlphaFunc = r200AlphaFunc; functions->BlendColor = r200BlendColor; functions->BlendEquationSeparate = r200BlendEquationSeparate; diff --git a/src/mesa/drivers/dri/r200/r200_state.h b/src/mesa/drivers/dri/r200/r200_state.h index 7b9b0c106aa..327ba837e25 100644 --- a/src/mesa/drivers/dri/r200/r200_state.h +++ b/src/mesa/drivers/dri/r200/r200_state.h @@ -38,7 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r200_context.h" extern void r200InitState( r200ContextPtr rmesa ); -extern void r200InitStateFuncs( struct dd_function_table *functions ); +extern void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions ); extern void r200InitTnlFuncs( GLcontext *ctx ); extern void r200UpdateMaterial( GLcontext *ctx ); diff --git a/src/mesa/drivers/dri/r200/radeon_pixel_read.c b/src/mesa/drivers/dri/r200/radeon_pixel_read.c new file mode 120000 index 00000000000..3b03803126f --- /dev/null +++ b/src/mesa/drivers/dri/r200/radeon_pixel_read.c @@ -0,0 +1 @@ +../radeon/radeon_pixel_read.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r200/radeon_tex_getimage.c b/src/mesa/drivers/dri/r200/radeon_tex_getimage.c new file mode 120000 index 00000000000..d9836d7326e --- /dev/null +++ b/src/mesa/drivers/dri/r200/radeon_tex_getimage.c @@ -0,0 +1 @@ +../radeon/radeon_tex_getimage.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r200/radeon_tile.c b/src/mesa/drivers/dri/r200/radeon_tile.c new file mode 120000 index 00000000000..d4bfe27da64 --- /dev/null +++ b/src/mesa/drivers/dri/r200/radeon_tile.c @@ -0,0 +1 @@ +../radeon/radeon_tile.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r200/radeon_tile.h b/src/mesa/drivers/dri/r200/radeon_tile.h new file mode 120000 index 00000000000..31074c581ea --- /dev/null +++ b/src/mesa/drivers/dri/r200/radeon_tile.h @@ -0,0 +1 @@ +../radeon/radeon_tile.h
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r200/server/radeon_dri.c b/src/mesa/drivers/dri/r200/server/radeon_dri.c deleted file mode 120000 index d05847d650f..00000000000 --- a/src/mesa/drivers/dri/r200/server/radeon_dri.c +++ /dev/null @@ -1 +0,0 @@ -../../radeon/server/radeon_dri.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile index 04459c2ddfa..2245998c952 100644 --- a/src/mesa/drivers/dri/r300/Makefile +++ b/src/mesa/drivers/dri/r300/Makefile @@ -7,8 +7,6 @@ CFLAGS += $(RADEON_CFLAGS) LIBNAME = r300_dri.so -MINIGLX_SOURCES = server/radeon_dri.c - ifeq ($(RADEON_LDFLAGS),) CS_SOURCES = radeon_cs_space_drm.c radeon_bo.c radeon_cs.c endif @@ -33,10 +31,13 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ - radeon_span.c \ + radeon_pixel_read.c \ radeon_queryobj.c \ + radeon_span.c \ radeon_texture.c \ - radeon_tex_copy.c + radeon_tex_copy.c \ + radeon_tex_getimage.c \ + radeon_tile.c DRIVER_SOURCES = \ radeon_screen.c \ diff --git a/src/mesa/drivers/dri/r300/r300_blit.c b/src/mesa/drivers/dri/r300/r300_blit.c index d870c7f852a..fa60628a5e0 100644 --- a/src/mesa/drivers/dri/r300/r300_blit.c +++ b/src/mesa/drivers/dri/r300/r300_blit.c @@ -582,12 +582,6 @@ unsigned r300_blit(GLcontext *ctx, if (dst_pitch % 2 > 0) ++dst_pitch; - /* Rendering to small buffer doesn't work. - * Looks like a hw limitation. - */ - if (dst_pitch < 32) - return 0; - /* Need to clamp the region size to make sure * we don't read outside of the source buffer * or write outside of the destination buffer. diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index 6cfa5686f4a..e2dbb1dbf40 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -332,36 +332,37 @@ void r300_emit_cb_setup(struct r300_context *r300, assert(offset % 32 == 0); switch (format) { - case MESA_FORMAT_RGB565: - assert(_mesa_little_endian()); - cbpitch |= R300_COLOR_FORMAT_RGB565; + case MESA_FORMAT_SL8: + case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + cbpitch |= R300_COLOR_FORMAT_I8; break; + case MESA_FORMAT_RGB565: case MESA_FORMAT_RGB565_REV: - assert(!_mesa_little_endian()); cbpitch |= R300_COLOR_FORMAT_RGB565; break; case MESA_FORMAT_ARGB4444: - assert(_mesa_little_endian()); - cbpitch |= R300_COLOR_FORMAT_ARGB4444; - break; case MESA_FORMAT_ARGB4444_REV: - assert(!_mesa_little_endian()); cbpitch |= R300_COLOR_FORMAT_ARGB4444; break; + case MESA_FORMAT_RGBA5551: case MESA_FORMAT_ARGB1555: - assert(_mesa_little_endian()); - cbpitch |= R300_COLOR_FORMAT_ARGB1555; - break; case MESA_FORMAT_ARGB1555_REV: - assert(!_mesa_little_endian()); cbpitch |= R300_COLOR_FORMAT_ARGB1555; break; + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_ARGB8888_REV: + case MESA_FORMAT_SRGBA8: + case MESA_FORMAT_SARGB8: + cbpitch |= R300_COLOR_FORMAT_ARGB8888; + break; default: - if (cpp == 4) { - cbpitch |= R300_COLOR_FORMAT_ARGB8888; - } else { - _mesa_problem(r300->radeon.glCtx, "unexpected format in emit_cb_offset()");; - } + _mesa_problem(r300->radeon.glCtx, "unexpected format in emit_cb_offset()"); break; } diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c index ff35cd52753..cfeb5407e91 100644 --- a/src/mesa/drivers/dri/r300/r300_context.c +++ b/src/mesa/drivers/dri/r300/r300_context.c @@ -321,6 +321,12 @@ static void r300_init_vtbl(radeonContextPtr radeon) radeon->vtbl.check_blit = r300_check_blit; radeon->vtbl.blit = r300_blit; + + if (radeon->radeonScreen->chip_family >= CHIP_FAMILY_RV515) { + radeon->vtbl.is_format_renderable = r500IsFormatRenderable; + } else { + radeon->vtbl.is_format_renderable = r300IsFormatRenderable; + } } static void r300InitConstValues(GLcontext *ctx, radeonScreenPtr screen) @@ -494,7 +500,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, _mesa_init_driver_functions(&functions); r300InitIoctlFuncs(&functions); - r300InitStateFuncs(&functions); + r300InitStateFuncs(&r300->radeon, &functions); r300InitTextureFuncs(&r300->radeon, &functions); r300InitShaderFuncs(&functions); radeonInitQueryObjFunctions(&functions); diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index 5979dedac4f..749a2464e7c 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -46,6 +46,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/simple_list.h" #include "main/api_arrayelt.h" +#include "drivers/common/meta.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "shader/prog_parameter.h" @@ -589,7 +590,7 @@ static void r300SetDepthState(GLcontext * ctx) R500_STENCIL_REFMASK_FRONT_BACK); r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_Z_FUNC_SHIFT); - if (ctx->Depth.Test) { + if (ctx->Depth.Test && ctx->DrawBuffer->_DepthBuffer) { r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_Z_ENABLE; if (ctx->Depth.Mask) r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_Z_WRITE_ENABLE; @@ -2237,6 +2238,68 @@ void r300UpdateShaderStates(r300ContextPtr rmesa) } } +#define EASY_US_OUT_FMT(comps, c0, c1, c2, c3) \ + (R500_OUT_FMT_##comps | R500_C0_SEL_##c0 | R500_C1_SEL_##c1 | \ + R500_C2_SEL_##c2 | R500_C3_SEL_##c3) +static void r300SetupUsOutputFormat(GLcontext *ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + uint32_t hw_format; + struct radeon_renderbuffer *rrb = radeon_get_colorbuffer(&rmesa->radeon); + + if (!rrb) { + return; + } + + switch (rrb->base.Format) + { + case MESA_FORMAT_RGBA5551: + case MESA_FORMAT_RGBA8888: + hw_format = EASY_US_OUT_FMT(C4_8, A, B, G, R); + break; + case MESA_FORMAT_RGB565_REV: + case MESA_FORMAT_RGBA8888_REV: + hw_format = EASY_US_OUT_FMT(C4_8, R, G, B, A); + break; + case MESA_FORMAT_RGB565: + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_ARGB8888: + hw_format = EASY_US_OUT_FMT(C4_8, B, G, R, A); + break; + case MESA_FORMAT_ARGB4444_REV: + case MESA_FORMAT_ARGB1555_REV: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_ARGB8888_REV: + hw_format = EASY_US_OUT_FMT(C4_8, A, R, G, B); + break; + case MESA_FORMAT_SRGBA8: + hw_format = EASY_US_OUT_FMT(C4_10_GAMMA, A, B, G, R); + break; + case MESA_FORMAT_SARGB8: + hw_format = EASY_US_OUT_FMT(C4_10_GAMMA, B, G, R, A); + break; + case MESA_FORMAT_SL8: + hw_format = EASY_US_OUT_FMT(C4_10_GAMMA, A, A, R, A); + break; + case MESA_FORMAT_A8: + hw_format = EASY_US_OUT_FMT(C4_8, A, A, A, A); + break; + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + hw_format = EASY_US_OUT_FMT(C4_8, A, A, R, A); + break; + default: + assert(!"Unsupported format"); + break; + } + + R300_STATECHANGE(rmesa, us_out_fmt); + rmesa->hw.us_out_fmt.cmd[1] = hw_format; +} +#undef EASY_US_OUT_FMT + /** * Called by Mesa after an internal state update. */ @@ -2266,6 +2329,10 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state) r300->hw.shade2.cmd[1] &= ~R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; } + if (new_state & _NEW_BUFFERS) { + r300SetupUsOutputFormat(ctx); + } + r300->radeon.NewGLState |= new_state; } @@ -2287,7 +2354,7 @@ static void r300RenderMode(GLcontext * ctx, GLenum mode) /** * Initialize driver's state callback functions */ -void r300InitStateFuncs(struct dd_function_table *functions) +void r300InitStateFuncs(radeonContextPtr radeon, struct dd_function_table *functions) { functions->UpdateState = r300InvalidateState; @@ -2326,8 +2393,14 @@ void r300InitStateFuncs(struct dd_function_table *functions) functions->ClipPlane = r300ClipPlane; functions->Scissor = radeonScissor; - functions->DrawBuffer = radeonDrawBuffer; - functions->ReadBuffer = radeonReadBuffer; + functions->DrawBuffer = radeonDrawBuffer; + functions->ReadBuffer = radeonReadBuffer; + + if (radeon->radeonScreen->kernel_mm) { + functions->CopyPixels = _mesa_meta_CopyPixels; + functions->DrawPixels = _mesa_meta_DrawPixels; + functions->ReadPixels = radeonReadPixels; + } } void r300InitShaderFunctions(r300ContextPtr r300) diff --git a/src/mesa/drivers/dri/r300/r300_state.h b/src/mesa/drivers/dri/r300/r300_state.h index d46bf9f1796..e70f84f4e4b 100644 --- a/src/mesa/drivers/dri/r300/r300_state.h +++ b/src/mesa/drivers/dri/r300/r300_state.h @@ -55,7 +55,7 @@ void r300UpdateDrawBuffer (GLcontext * ctx); void r300UpdateShaders (r300ContextPtr rmesa); void r300UpdateShaderStates (r300ContextPtr rmesa); void r300InitState (r300ContextPtr r300); -void r300InitStateFuncs (struct dd_function_table *functions); +void r300InitStateFuncs (radeonContextPtr radeon, struct dd_function_table *functions); void r300VapCntl(r300ContextPtr rmesa, GLuint input_count, GLuint output_count, GLuint temp_count); void r300SetupVAP(GLcontext *ctx, GLuint InputsRead, GLuint OutputsWritten); diff --git a/src/mesa/drivers/dri/r300/r300_tex.c b/src/mesa/drivers/dri/r300/r300_tex.c index 8dd85073954..baef206bc26 100644 --- a/src/mesa/drivers/dri/r300/r300_tex.c +++ b/src/mesa/drivers/dri/r300/r300_tex.c @@ -308,6 +308,45 @@ static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx, return &t->base; } +unsigned r300IsFormatRenderable(gl_format mesa_format) +{ + switch (mesa_format) + { + case MESA_FORMAT_RGB565: + case MESA_FORMAT_RGBA5551: + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGB565_REV: + case MESA_FORMAT_RGBA8888_REV: + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_ARGB4444_REV: + case MESA_FORMAT_ARGB1555_REV: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_ARGB8888_REV: + case MESA_FORMAT_SRGBA8: + case MESA_FORMAT_SARGB8: + case MESA_FORMAT_SL8: + case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + case MESA_FORMAT_Z16: + return 1; + default: + return 0; + } +} + +unsigned r500IsFormatRenderable(gl_format mesa_format) +{ + if (mesa_format == MESA_FORMAT_S8_Z24) { + return 1; + } else { + return r300IsFormatRenderable(mesa_format); + } +} + void r300InitTextureFuncs(radeonContextPtr radeon, struct dd_function_table *functions) { /* Note: we only plug in the functions we implement in the driver diff --git a/src/mesa/drivers/dri/r300/r300_tex.h b/src/mesa/drivers/dri/r300/r300_tex.h index 9694e703b83..aca44cd7669 100644 --- a/src/mesa/drivers/dri/r300/r300_tex.h +++ b/src/mesa/drivers/dri/r300/r300_tex.h @@ -53,4 +53,7 @@ extern void r300InitTextureFuncs(radeonContextPtr radeon, struct dd_function_tab int32_t r300TranslateTexFormat(gl_format mesaFormat); +unsigned r300IsFormatRenderable(gl_format mesaFormat); +unsigned r500IsFormatRenderable(gl_format mesaFormat); + #endif /* __r300_TEX_H__ */ diff --git a/src/mesa/drivers/dri/r300/radeon_pixel_read.c b/src/mesa/drivers/dri/r300/radeon_pixel_read.c new file mode 120000 index 00000000000..3b03803126f --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_pixel_read.c @@ -0,0 +1 @@ +../radeon/radeon_pixel_read.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/radeon_tex_getimage.c b/src/mesa/drivers/dri/r300/radeon_tex_getimage.c new file mode 120000 index 00000000000..d9836d7326e --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_tex_getimage.c @@ -0,0 +1 @@ +../radeon/radeon_tex_getimage.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/radeon_tile.c b/src/mesa/drivers/dri/r300/radeon_tile.c new file mode 120000 index 00000000000..d4bfe27da64 --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_tile.c @@ -0,0 +1 @@ +../radeon/radeon_tile.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/radeon_tile.h b/src/mesa/drivers/dri/r300/radeon_tile.h new file mode 120000 index 00000000000..31074c581ea --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_tile.h @@ -0,0 +1 @@ +../radeon/radeon_tile.h
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r300/server/radeon_dri.c b/src/mesa/drivers/dri/r300/server/radeon_dri.c deleted file mode 120000 index d05847d650f..00000000000 --- a/src/mesa/drivers/dri/r300/server/radeon_dri.c +++ /dev/null @@ -1 +0,0 @@ -../../radeon/server/radeon_dri.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r600/Makefile b/src/mesa/drivers/dri/r600/Makefile index 5d509415393..17915621ee4 100644 --- a/src/mesa/drivers/dri/r600/Makefile +++ b/src/mesa/drivers/dri/r600/Makefile @@ -7,8 +7,6 @@ CFLAGS += $(RADEON_CFLAGS) LIBNAME = r600_dri.so -MINIGLX_SOURCES = server/radeon_dri.c - ifeq ($(RADEON_LDFLAGS),) CS_SOURCES = radeon_cs_space_drm.c radeon_bo.c radeon_cs.c endif @@ -33,10 +31,13 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ + radeon_pixel_read.c \ + radeon_queryobj.c \ radeon_span.c \ radeon_texture.c \ - radeon_queryobj.c \ - radeon_tex_copy.c + radeon_tex_copy.c \ + radeon_tex_getimage.c \ + radeon_tile.c DRIVER_SOURCES = \ radeon_screen.c \ diff --git a/src/mesa/drivers/dri/r600/r600_context.c b/src/mesa/drivers/dri/r600/r600_context.c index 134e97e7c33..fddac2f9bdc 100644 --- a/src/mesa/drivers/dri/r600/r600_context.c +++ b/src/mesa/drivers/dri/r600/r600_context.c @@ -239,6 +239,7 @@ static void r600_init_vtbl(radeonContextPtr radeon) radeon->vtbl.emit_query_finish = r600_emit_query_finish; radeon->vtbl.check_blit = r600_check_blit; radeon->vtbl.blit = r600_blit; + radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; } static void r600InitConstValues(GLcontext *ctx, radeonScreenPtr screen) @@ -383,7 +384,7 @@ GLboolean r600CreateContext(const __GLcontextModes * glVisual, */ _mesa_init_driver_functions(&functions); - r700InitStateFuncs(&functions); + r700InitStateFuncs(&r600->radeon, &functions); r600InitTextureFuncs(&r600->radeon, &functions); r700InitShaderFuncs(&functions); radeonInitQueryObjFunctions(&functions); diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c index 12eaebbc16b..1ff233d91ee 100644 --- a/src/mesa/drivers/dri/r600/r700_state.c +++ b/src/mesa/drivers/dri/r600/r700_state.c @@ -39,6 +39,7 @@ #include "swrast_setup/swrast_setup.h" #include "main/api_arrayelt.h" #include "main/framebuffer.h" +#include "drivers/common/meta.h" #include "shader/prog_parameter.h" #include "shader/prog_statevars.h" @@ -1816,7 +1817,7 @@ void r700InitState(GLcontext * ctx) //------------------- } -void r700InitStateFuncs(struct dd_function_table *functions) //----------------- +void r700InitStateFuncs(radeonContextPtr radeon, struct dd_function_table *functions) { functions->UpdateState = r700InvalidateState; functions->AlphaFunc = r700AlphaFunc; @@ -1857,8 +1858,13 @@ void r700InitStateFuncs(struct dd_function_table *functions) //----------------- functions->Scissor = radeonScissor; - functions->DrawBuffer = radeonDrawBuffer; - functions->ReadBuffer = radeonReadBuffer; + functions->DrawBuffer = radeonDrawBuffer; + functions->ReadBuffer = radeonReadBuffer; + if (radeon->radeonScreen->kernel_mm) { + functions->CopyPixels = _mesa_meta_CopyPixels; + functions->DrawPixels = _mesa_meta_DrawPixels; + functions->ReadPixels = radeonReadPixels; + } } diff --git a/src/mesa/drivers/dri/r600/r700_state.h b/src/mesa/drivers/dri/r600/r700_state.h index 60c6a7f23ca..56885e0b154 100644 --- a/src/mesa/drivers/dri/r600/r700_state.h +++ b/src/mesa/drivers/dri/r600/r700_state.h @@ -40,7 +40,7 @@ extern void r700UpdateShaderStates(GLcontext * ctx); extern void r700UpdateViewportOffset(GLcontext * ctx); extern void r700InitState (GLcontext * ctx); -extern void r700InitStateFuncs (struct dd_function_table *functions); +extern void r700InitStateFuncs (radeonContextPtr radeon, struct dd_function_table *functions); extern void r700SetScissor(context_t *context); diff --git a/src/mesa/drivers/dri/r600/radeon_pixel_read.c b/src/mesa/drivers/dri/r600/radeon_pixel_read.c new file mode 120000 index 00000000000..3b03803126f --- /dev/null +++ b/src/mesa/drivers/dri/r600/radeon_pixel_read.c @@ -0,0 +1 @@ +../radeon/radeon_pixel_read.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r600/radeon_tex_getimage.c b/src/mesa/drivers/dri/r600/radeon_tex_getimage.c new file mode 120000 index 00000000000..d9836d7326e --- /dev/null +++ b/src/mesa/drivers/dri/r600/radeon_tex_getimage.c @@ -0,0 +1 @@ +../radeon/radeon_tex_getimage.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r600/radeon_tile.c b/src/mesa/drivers/dri/r600/radeon_tile.c new file mode 120000 index 00000000000..d4bfe27da64 --- /dev/null +++ b/src/mesa/drivers/dri/r600/radeon_tile.c @@ -0,0 +1 @@ +../radeon/radeon_tile.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r600/radeon_tile.h b/src/mesa/drivers/dri/r600/radeon_tile.h new file mode 120000 index 00000000000..31074c581ea --- /dev/null +++ b/src/mesa/drivers/dri/r600/radeon_tile.h @@ -0,0 +1 @@ +../radeon/radeon_tile.h
\ No newline at end of file diff --git a/src/mesa/drivers/dri/r600/server/radeon_dri.c b/src/mesa/drivers/dri/r600/server/radeon_dri.c deleted file mode 120000 index d05847d650f..00000000000 --- a/src/mesa/drivers/dri/r600/server/radeon_dri.c +++ /dev/null @@ -1 +0,0 @@ -../../radeon/server/radeon_dri.c
\ No newline at end of file diff --git a/src/mesa/drivers/dri/radeon/Makefile b/src/mesa/drivers/dri/radeon/Makefile index a54ea16ec63..19df62742ec 100644 --- a/src/mesa/drivers/dri/radeon/Makefile +++ b/src/mesa/drivers/dri/radeon/Makefile @@ -8,8 +8,6 @@ CFLAGS += $(RADEON_CFLAGS) LIBNAME = radeon_dri.so -MINIGLX_SOURCES = server/radeon_dri.c - ifeq ($(RADEON_LDFLAGS),) CS_SOURCES = radeon_cs_space_drm.c radeon_bo.c radeon_cs.c endif @@ -24,10 +22,13 @@ RADEON_COMMON_SOURCES = \ radeon_fbo.c \ radeon_lock.c \ radeon_mipmap_tree.c \ + radeon_pixel_read.c \ radeon_queryobj.c \ radeon_span.c \ radeon_texture.c \ - radeon_tex_copy.c + radeon_tex_copy.c \ + radeon_tex_getimage.c \ + radeon_tile.c DRIVER_SOURCES = \ radeon_context.c \ diff --git a/src/mesa/drivers/dri/radeon/radeon_blit.c b/src/mesa/drivers/dri/radeon/radeon_blit.c index e1e1f215508..143822361e1 100644 --- a/src/mesa/drivers/dri/radeon/radeon_blit.c +++ b/src/mesa/drivers/dri/radeon/radeon_blit.c @@ -48,6 +48,8 @@ unsigned r100_check_blit(gl_format mesa_format) case MESA_FORMAT_ARGB4444: case MESA_FORMAT_ARGB1555: case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: break; default: return 0; @@ -103,6 +105,9 @@ static void inline emit_tx_setup(struct r100_context *r100, case MESA_FORMAT_ARGB8888: txformat |= RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP; break; + case MESA_FORMAT_RGBA8888: + txformat |= RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP; + break; case MESA_FORMAT_XRGB8888: txformat |= RADEON_TXFORMAT_ARGB8888; break; @@ -116,8 +121,15 @@ static void inline emit_tx_setup(struct r100_context *r100, txformat |= RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP; break; case MESA_FORMAT_A8: + case MESA_FORMAT_I8: txformat |= RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP; break; + case MESA_FORMAT_L8: + txformat |= RADEON_TXFORMAT_I8; + break; + case MESA_FORMAT_AL88: + txformat |= RADEON_TXFORMAT_AI88 | RADEON_TXFORMAT_ALPHA_IN_MAP; + break; default: break; } @@ -177,6 +189,8 @@ static inline void emit_cb_setup(struct r100_context *r100, dst_format = RADEON_COLOR_FORMAT_ARGB1555; break; case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: dst_format = RADEON_COLOR_FORMAT_RGB8; break; default: diff --git a/src/mesa/drivers/dri/radeon/radeon_common.h b/src/mesa/drivers/dri/radeon/radeon_common.h index cd01c9984e3..35b3f08fff9 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common.h +++ b/src/mesa/drivers/dri/radeon/radeon_common.h @@ -44,6 +44,12 @@ radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb, struct radeon_renderbuffer * radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv); +void +radeonReadPixels(GLcontext * ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, GLvoid * pixels); + void radeon_check_front_buffer_rendering(GLcontext *ctx); static inline struct radeon_renderbuffer *radeon_renderbuffer(struct gl_renderbuffer *rb) { diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index d1a24e265f2..5156c5d0d0a 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -539,6 +539,7 @@ struct radeon_context { unsigned reg_width, unsigned reg_height, unsigned flip_y); + unsigned (*is_format_renderable)(gl_format mesa_format); } vtbl; }; diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c index 878a453bd53..56aba16e9e0 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_context.c @@ -200,6 +200,7 @@ static void r100_init_vtbl(radeonContextPtr radeon) radeon->vtbl.emit_query_finish = r100_emit_query_finish; radeon->vtbl.check_blit = r100_check_blit; radeon->vtbl.blit = r100_blit; + radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; } /* Create the device specific context. diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c index 46664a17556..63986058356 100644 --- a/src/mesa/drivers/dri/radeon/radeon_fbo.c +++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c @@ -409,82 +409,51 @@ radeon_framebuffer_renderbuffer(GLcontext * ctx, radeon_draw_buffer(ctx, fb); } - -/* TODO: According to EXT_fbo spec internal format of texture image - * once set during glTexImage call, should be preserved when - * attaching image to renderbuffer. When HW doesn't support - * rendering to format of attached image, set framebuffer - * completeness accordingly in radeon_validate_framebuffer (issue #79). - */ static GLboolean radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb, struct gl_texture_image *texImage) { - int retry = 0; - gl_format texFormat; - radeon_print(RADEON_TEXTURE, RADEON_TRACE, - "%s(%p, rrb %p, texImage %p) \n", - __func__, ctx, rrb, texImage); - -restart: - if (texImage->TexFormat == _dri_texformat_argb8888) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to RGBA8 texture OK\n"); + "%s(%p, rrb %p, texImage %p, texFormat %s) \n", + __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat)); + + switch (texImage->TexFormat) { + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_ARGB8888_REV: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_XRGB8888_REV: + case MESA_FORMAT_RGB565: + case MESA_FORMAT_RGB565_REV: + case MESA_FORMAT_RGBA5551: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_ARGB1555_REV: + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB4444_REV: + rrb->base.DataType = GL_UNSIGNED_BYTE; + break; + case MESA_FORMAT_Z16: + rrb->base.DataType = GL_UNSIGNED_SHORT; + break; + case MESA_FORMAT_X8_Z24: + rrb->base.DataType = GL_UNSIGNED_INT; + break; + case MESA_FORMAT_S8_Z24: + rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; + break; } - else if (texImage->TexFormat == _dri_texformat_rgb565) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to RGB5 texture OK\n"); - } - else if (texImage->TexFormat == _dri_texformat_argb1555) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to ARGB1555 texture OK\n"); - } - else if (texImage->TexFormat == _dri_texformat_argb4444) { - rrb->base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to ARGB4444 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_Z16) { - rrb->base.DataType = GL_UNSIGNED_SHORT; - DBG("Render to DEPTH16 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_S8_Z24) { - rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; - DBG("Render to DEPTH_STENCIL texture OK\n"); - } - else { - /* try redoing the FBO */ - if (retry == 1) { - DBG("Render to texture BAD FORMAT %d\n", - texImage->TexFormat); - return GL_FALSE; - } - /* XXX why is the tex format being set here? - * I think this can be removed. - */ - texImage->TexFormat = radeonChooseTextureFormat(ctx, texImage->InternalFormat, 0, - _mesa_get_format_datatype(texImage->TexFormat), - 1); - - retry++; - goto restart; - } - - texFormat = texImage->TexFormat; - - rrb->base.Format = texFormat; - - rrb->cpp = _mesa_get_format_bytes(texFormat); + + rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); rrb->pitch = texImage->Width * rrb->cpp; + rrb->base.Format = texImage->TexFormat; rrb->base.InternalFormat = texImage->InternalFormat; - rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat); - + rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat); rrb->base.Width = texImage->Width; rrb->base.Height = texImage->Height; - rrb->base.Delete = radeon_delete_renderbuffer; rrb->base.AllocStorage = radeon_nop_alloc_storage; - + return GL_TRUE; } @@ -607,6 +576,35 @@ radeon_finish_render_texture(GLcontext * ctx, static void radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) { + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + gl_format mesa_format; + int i; + + for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { + struct gl_renderbuffer_attachment *att; + if (i == -2) { + att = &fb->Attachment[BUFFER_DEPTH]; + } else if (i == -1) { + att = &fb->Attachment[BUFFER_STENCIL]; + } else { + att = &fb->Attachment[BUFFER_COLOR0 + i]; + } + + if (att->Type == GL_TEXTURE) { + mesa_format = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->TexFormat; + } else { + /* All renderbuffer formats are renderable, but not sampable */ + continue; + } + + if (!radeon->vtbl.is_format_renderable(mesa_format)){ + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; + radeon_print(RADEON_TEXTURE, RADEON_TRACE, + "%s: HW doesn't support format %s as output format of attachment %d\n", + __FUNCTION__, _mesa_get_format_name(mesa_format), i); + return; + } + } } void radeon_fbo_init(struct radeon_context *radeon) diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c index e0e271b7711..7f5fb99fa4f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c +++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c @@ -36,6 +36,7 @@ #include "main/texobj.h" #include "main/enums.h" #include "radeon_texture.h" +#include "radeon_tile.h" static unsigned get_aligned_compressed_row_stride( gl_format format, @@ -69,16 +70,51 @@ static unsigned get_aligned_compressed_row_stride( return stride; } -static unsigned get_compressed_image_size( +unsigned get_texture_image_size( gl_format format, unsigned rowStride, - unsigned height) + unsigned height, + unsigned depth, + unsigned tiling) { - unsigned blockWidth, blockHeight; + if (_mesa_is_format_compressed(format)) { + unsigned blockWidth, blockHeight; - _mesa_get_format_block_size(format, &blockWidth, &blockHeight); + _mesa_get_format_block_size(format, &blockWidth, &blockHeight); + + return rowStride * ((height + blockHeight - 1) / blockHeight) * depth; + } else if (tiling) { + /* Need to align height to tile height */ + unsigned tileWidth, tileHeight; - return rowStride * ((height + blockHeight - 1) / blockHeight); + get_tile_size(format, &tileWidth, &tileHeight); + tileHeight--; + + height = (height + tileHeight) & ~tileHeight; + } + + return rowStride * height * depth; +} + +unsigned get_texture_image_row_stride(radeonContextPtr rmesa, gl_format format, unsigned width, unsigned tiling) +{ + if (_mesa_is_format_compressed(format)) { + return get_aligned_compressed_row_stride(format, width, rmesa->texture_compressed_row_align); + } else { + unsigned row_align; + + if (!_mesa_is_pow_two(width)) { + row_align = rmesa->texture_rect_row_align - 1; + } else if (tiling) { + unsigned tileWidth, tileHeight; + get_tile_size(format, &tileWidth, &tileHeight); + row_align = tileWidth * _mesa_get_format_bytes(format) - 1; + } else { + row_align = rmesa->texture_row_align - 1; + } + + return (_mesa_format_row_stride(format, width) + row_align) & ~row_align; + } } /** @@ -92,34 +128,15 @@ static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree GLuint face, GLuint level, GLuint* curOffset) { radeon_mipmap_level *lvl = &mt->levels[level]; - uint32_t row_align; GLuint height; height = _mesa_next_pow_two_32(lvl->height); - /* Find image size in bytes */ - if (_mesa_is_format_compressed(mt->mesaFormat)) { - lvl->rowstride = get_aligned_compressed_row_stride(mt->mesaFormat, lvl->width, rmesa->texture_compressed_row_align); - lvl->size = get_compressed_image_size(mt->mesaFormat, lvl->rowstride, height); - } else if (mt->target == GL_TEXTURE_RECTANGLE_NV) { - row_align = rmesa->texture_rect_row_align - 1; - lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align; - lvl->size = lvl->rowstride * height; - } else if (mt->tilebits & RADEON_TXO_MICRO_TILE) { - /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned, - * though the actual offset may be different (if texture is less than - * 32 bytes width) to the untiled case */ - lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) * 2 + 31) & ~31; - lvl->size = lvl->rowstride * ((height + 1) / 2) * lvl->depth; - } else { - row_align = rmesa->texture_row_align - 1; - lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align; - lvl->size = lvl->rowstride * height * lvl->depth; - } + lvl->rowstride = get_texture_image_row_stride(rmesa, mt->mesaFormat, lvl->width, mt->tilebits); + lvl->size = get_texture_image_size(mt->mesaFormat, lvl->rowstride, lvl->height, lvl->depth, mt->tilebits); + assert(lvl->size > 0); - /* All images are aligned to a 32-byte offset */ - *curOffset = (*curOffset + 0x1f) & ~0x1f; lvl->faces[face].offset = *curOffset; *curOffset += lvl->size; @@ -451,12 +468,9 @@ static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel]; - /* TODO: bring back these assertions once the FBOs are fixed */ -#if 0 assert(image->mtlevel == level); assert(srclvl->size == dstlvl->size); assert(srclvl->rowstride == dstlvl->rowstride); -#endif radeon_bo_map(image->mt->bo, GL_FALSE); diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h index c911688c1a5..088f9701722 100644 --- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h +++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h @@ -89,4 +89,13 @@ void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t); GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt, GLuint face, GLuint level); uint32_t get_base_teximage_offset(radeonTexObj *texObj); + +unsigned get_texture_image_row_stride(radeonContextPtr rmesa, gl_format format, unsigned width, unsigned tiling); + +unsigned get_texture_image_size( + gl_format format, + unsigned rowStride, + unsigned height, + unsigned depth, + unsigned tiling); #endif /* __RADEON_MIPMAP_TREE_H_ */ diff --git a/src/mesa/drivers/dri/radeon/radeon_pixel_read.c b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c new file mode 100644 index 00000000000..dadb8002c7d --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_pixel_read.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2010 Maciej Cencora <[email protected]> + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "stdint.h" +#include "main/bufferobj.h" +#include "main/enums.h" +#include "main/image.h" +#include "main/state.h" +#include "swrast/swrast.h" + +#include "radeon_common_context.h" +#include "radeon_debug.h" +#include "radeon_mipmap_tree.h" + +static gl_format gl_format_and_type_to_mesa_format(GLenum format, GLenum type) +{ + switch (format) + { + case GL_RGB: + switch (type) { + case GL_UNSIGNED_SHORT_5_6_5: + return MESA_FORMAT_RGB565; + case GL_UNSIGNED_SHORT_5_6_5_REV: + return MESA_FORMAT_RGB565_REV; + } + break; + case GL_RGBA: + switch (type) { + case GL_FLOAT: + return MESA_FORMAT_RGBA_FLOAT32; + case GL_UNSIGNED_SHORT_5_5_5_1: + return MESA_FORMAT_RGBA5551; + case GL_UNSIGNED_INT_8_8_8_8: + return MESA_FORMAT_RGBA8888; + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_INT_8_8_8_8_REV: + return MESA_FORMAT_RGBA8888_REV; + } + break; + case GL_BGRA: + switch (type) { + case GL_UNSIGNED_SHORT_4_4_4_4: + return MESA_FORMAT_ARGB4444_REV; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return MESA_FORMAT_ARGB4444; + case GL_UNSIGNED_SHORT_5_5_5_1: + return MESA_FORMAT_ARGB1555_REV; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return MESA_FORMAT_ARGB1555; + case GL_UNSIGNED_INT_8_8_8_8: + return MESA_FORMAT_ARGB8888_REV; + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_INT_8_8_8_8_REV: + return MESA_FORMAT_ARGB8888; + + } + break; + } + + return MESA_FORMAT_NONE; +} + +static GLboolean +do_blit_readpixels(GLcontext * ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, GLvoid * pixels) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + const struct radeon_renderbuffer *rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); + const gl_format dst_format = gl_format_and_type_to_mesa_format(format, type); + unsigned dst_rowstride, dst_imagesize, aligned_rowstride, flip_y; + struct radeon_bo *dst_buffer; + GLint dst_x = 0, dst_y = 0; + + /* It's not worth if number of pixels to copy is really small */ + if (width * height < 100) { + return GL_FALSE; + } + + if (dst_format == MESA_FORMAT_NONE || + !radeon->vtbl.check_blit(dst_format) || !radeon->vtbl.blit) { + return GL_FALSE; + } + + if (ctx->_ImageTransferState || ctx->Color._LogicOpEnabled) { + return GL_FALSE; + } + + if (pack->SwapBytes || pack->LsbFirst) { + return GL_FALSE; + } + + if (pack->RowLength > 0) { + dst_rowstride = pack->RowLength; + } else { + dst_rowstride = width; + } + + if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) { + return GL_TRUE; + } + assert(x >= 0 && y >= 0); + + aligned_rowstride = get_texture_image_row_stride(radeon, dst_format, dst_rowstride, 0); + dst_imagesize = get_texture_image_size(dst_format, + aligned_rowstride, + height, 1, 0); + dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0); + + /* Disable source Y flipping for FBOs */ + flip_y = (ctx->ReadBuffer->Name == 0); + if (pack->Invert) { + y = rrb->base.Height - height - y; + flip_y = !flip_y; + } + + if (radeon->vtbl.blit(ctx, + rrb->bo, + rrb->draw_offset, + rrb->base.Format, + rrb->pitch / rrb->cpp, + rrb->base.Width, + rrb->base.Height, + x, + y, + dst_buffer, + 0, /* dst_offset */ + dst_format, + aligned_rowstride / _mesa_get_format_bytes(dst_format), + width, + height, + 0, /* dst_x */ + 0, /* dst_y */ + width, + height, + flip_y)) + { + radeon_bo_map(dst_buffer, 0); + dst_rowstride *= _mesa_get_format_bytes(dst_format); + copy_rows(pixels, dst_rowstride, dst_buffer->ptr, + aligned_rowstride, height, dst_rowstride); + radeon_bo_unmap(dst_buffer); + radeon_bo_unref(dst_buffer); + return GL_TRUE; + } else { + radeon_bo_unref(dst_buffer); + return GL_FALSE; + } +} + +void +radeonReadPixels(GLcontext * ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, GLvoid * pixels) +{ + if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels)) + return; + + /* Update Mesa state before calling down into _swrast_ReadPixels, as + * the spans code requires the computed buffer states to be up to date, + * but _swrast_ReadPixels only updates Mesa state after setting up + * the spans code. + */ + + radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, + "Falling back to sw for ReadPixels (format %s, type %s)\n", + _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); + + if (ctx->NewState) + _mesa_update_state(ctx); + + _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels); +} diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c index 583751d64df..0afbc19c127 100644 --- a/src/mesa/drivers/dri/radeon/radeon_state.c +++ b/src/mesa/drivers/dri/radeon/radeon_state.c @@ -45,6 +45,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tnl/tnl.h" #include "tnl/t_pipeline.h" #include "swrast_setup/swrast_setup.h" +#include "drivers/common/meta.h" #include "radeon_context.h" #include "radeon_mipmap_tree.h" @@ -2248,6 +2249,11 @@ void radeonInitStateFuncs( GLcontext *ctx , GLboolean dri2 ) ctx->Driver.DrawBuffer = radeonDrawBuffer; ctx->Driver.ReadBuffer = radeonReadBuffer; + if (dri2) { + ctx->Driver.CopyPixels = _mesa_meta_CopyPixels; + ctx->Driver.DrawPixels = _mesa_meta_DrawPixels; + ctx->Driver.ReadPixels = radeonReadPixels; + } ctx->Driver.AlphaFunc = radeonAlphaFunc; ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate; diff --git a/src/mesa/drivers/dri/radeon/radeon_tex_copy.c b/src/mesa/drivers/dri/radeon/radeon_tex_copy.c index 5cfad6fc3c8..29fd31ac23f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_tex_copy.c +++ b/src/mesa/drivers/dri/radeon/radeon_tex_copy.c @@ -28,6 +28,7 @@ #include "radeon_common.h" #include "radeon_texture.h" +#include "main/enums.h" #include "main/image.h" #include "main/teximage.h" #include "main/texstate.h" @@ -52,22 +53,34 @@ do_copy_texsubimage(GLcontext *ctx, gl_format dst_mesaformat; unsigned src_width; unsigned dst_width; + unsigned flip_y; if (!radeon->vtbl.blit) { return GL_FALSE; } if (_mesa_get_format_bits(timg->base.TexFormat, GL_DEPTH_BITS) > 0) { - rrb = radeon_get_depthbuffer(radeon); + if (ctx->ReadBuffer->_DepthBuffer && ctx->ReadBuffer->_DepthBuffer->Wrapped) { + rrb = radeon_renderbuffer(ctx->ReadBuffer->_DepthBuffer->Wrapped); + } else { + rrb = radeon_renderbuffer(ctx->ReadBuffer->_DepthBuffer); + } + flip_y = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Type == GL_NONE; } else { - rrb = radeon_get_colorbuffer(radeon); + rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); + flip_y = ctx->ReadBuffer->Attachment[BUFFER_COLOR0].Type == GL_NONE; + } + + // This is software renderbuffer, fallback to swrast + if (!rrb) { + return GL_FALSE; } if (!timg->mt) { radeon_validate_texture_miptree(ctx, &tobj->base); } - assert(rrb && rrb->bo); + assert(rrb->bo); assert(timg->mt); assert(timg->mt->bo); assert(timg->base.Width >= dstx + width); @@ -124,7 +137,7 @@ do_copy_texsubimage(GLcontext *ctx, timg->mt->bo, dst_offset, dst_mesaformat, timg->mt->levels[level].rowstride / dst_bpp, dst_width, timg->base.Height, - dstx, dsty, width, height, 1); + dstx, dsty, width, height, flip_y); } void @@ -171,6 +184,10 @@ radeonCopyTexImage2D(GLcontext *ctx, GLenum target, GLint level, return; fail: + radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, + "Falling back to sw for glCopyTexImage2D (internalFormat %s, border %d)\n", + _mesa_lookup_enum_by_nr(internalFormat), border); + _mesa_meta_CopyTexImage2D(ctx, target, level, internalFormat, x, y, width, height, border); } @@ -189,7 +206,8 @@ radeonCopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, radeon_tex_obj(texObj), (radeon_texture_image *)texImage, xoffset, yoffset, x, y, width, height)) { - //DEBUG_FALLBACKS + radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, + "Falling back to sw for glCopyTexSubImage2D\n"); _mesa_meta_CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, x, y, width, height); diff --git a/src/mesa/drivers/dri/radeon/radeon_tex_getimage.c b/src/mesa/drivers/dri/radeon/radeon_tex_getimage.c new file mode 100644 index 00000000000..7bf6dcc2e32 --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_tex_getimage.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2009 Maciej Cencora. + * Copyright (C) 2008 Nicolai Haehnle. + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "radeon_common_context.h" +#include "radeon_texture.h" +#include "radeon_mipmap_tree.h" + +#include "main/texgetimage.h" + +/** + * Need to map texture image into memory before copying image data, + * then unmap it. + */ +static void +radeon_get_tex_image(GLcontext * ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid * pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, int compressed) +{ + radeon_texture_image *image = get_radeon_texture_image(texImage); + + radeon_print(RADEON_TEXTURE, RADEON_NORMAL, + "%s(%p, tex %p, image %p) compressed %d.\n", + __func__, ctx, texObj, image, compressed); + + if (image->mt) { + /* Map the texture image read-only */ + radeon_teximage_map(image, GL_FALSE); + } else { + /* Image hasn't been uploaded to a miptree yet */ + assert(image->base.Data); + } + + if (compressed) { + /* FIXME: this can't work for small textures (mips) which + use different hw stride */ + _mesa_get_compressed_teximage(ctx, target, level, pixels, + texObj, texImage); + } else { + _mesa_get_teximage(ctx, target, level, format, type, pixels, + texObj, texImage); + } + + if (image->mt) { + radeon_teximage_unmap(image); + } +} + +void +radeonGetTexImage(GLcontext * ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid * pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + radeon_get_tex_image(ctx, target, level, format, type, pixels, + texObj, texImage, 0); +} + +void +radeonGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, + GLvoid *pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + radeon_get_tex_image(ctx, target, level, 0, 0, pixels, + texObj, texImage, 1); +} diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c index ff37fd3e86e..2b655fbd953 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texture.c +++ b/src/mesa/drivers/dri/radeon/radeon_texture.c @@ -39,7 +39,6 @@ #include "main/texstore.h" #include "main/teximage.h" #include "main/texobj.h" -#include "main/texgetimage.h" #include "xmlpool.h" /* for symbolic values of enum-type options */ @@ -559,6 +558,15 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx, case GL_COMPRESSED_SLUMINANCE_ALPHA: return MESA_FORMAT_SLA8; + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + return MESA_FORMAT_SRGB_DXT1; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + return MESA_FORMAT_SRGBA_DXT1; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + return MESA_FORMAT_SRGBA_DXT3; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + return MESA_FORMAT_SRGBA_DXT5; + default: _mesa_problem(ctx, "unexpected internalFormat 0x%x in %s", @@ -664,6 +672,7 @@ static void radeon_store_teximage(GLcontext* ctx, int dims, struct gl_texture_image *texImage, int compressed) { + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObj *t = radeon_tex_obj(texObj); radeon_texture_image* image = get_radeon_texture_image(texImage); @@ -678,8 +687,7 @@ static void radeon_store_teximage(GLcontext* ctx, int dims, dstRowStride = image->mt->levels[image->mtlevel].rowstride; } else if (t->bo) { /* TFP case */ - /* TODO */ - assert(0); + dstRowStride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0); } else { dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width); } @@ -999,61 +1007,18 @@ void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level, format, type, pixels, packing, texObj, texImage, 0); } -/** - * Need to map texture image into memory before copying image data, - * then unmap it. - */ -static void -radeon_get_tex_image(GLcontext * ctx, GLenum target, GLint level, - GLenum format, GLenum type, GLvoid * pixels, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, int compressed) +unsigned radeonIsFormatRenderable(gl_format mesa_format) { - radeon_texture_image *image = get_radeon_texture_image(texImage); - - radeon_print(RADEON_TEXTURE, RADEON_NORMAL, - "%s(%p, tex %p, image %p) compressed %d.\n", - __func__, ctx, texObj, image, compressed); + if (mesa_format == _dri_texformat_argb8888 || mesa_format == _dri_texformat_rgb565 || + mesa_format == _dri_texformat_argb1555 || mesa_format == _dri_texformat_argb4444) + return 1; - if (image->mt) { - /* Map the texture image read-only */ - radeon_teximage_map(image, GL_FALSE); - } else { - /* Image hasn't been uploaded to a miptree yet */ - assert(image->base.Data); - } - - if (compressed) { - /* FIXME: this can't work for small textures (mips) which - use different hw stride */ - _mesa_get_compressed_teximage(ctx, target, level, pixels, - texObj, texImage); - } else { - _mesa_get_teximage(ctx, target, level, format, type, pixels, - texObj, texImage); - } - - if (image->mt) { - radeon_teximage_unmap(image); + switch (mesa_format) + { + case MESA_FORMAT_Z16: + case MESA_FORMAT_S8_Z24: + return 1; + default: + return 0; } } - -void -radeonGetTexImage(GLcontext * ctx, GLenum target, GLint level, - GLenum format, GLenum type, GLvoid * pixels, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - radeon_get_tex_image(ctx, target, level, format, type, pixels, - texObj, texImage, 0); -} - -void -radeonGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, - GLvoid *pixels, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - radeon_get_tex_image(ctx, target, level, 0, 0, pixels, - texObj, texImage, 1); -} diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.h b/src/mesa/drivers/dri/radeon/radeon_texture.h index f09dd652142..4ce639ea34e 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texture.h +++ b/src/mesa/drivers/dri/radeon/radeon_texture.h @@ -135,4 +135,6 @@ void radeonCopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLsizei height); +unsigned radeonIsFormatRenderable(gl_format mesa_format); + #endif diff --git a/src/mesa/drivers/dri/radeon/radeon_tile.c b/src/mesa/drivers/dri/radeon/radeon_tile.c new file mode 100644 index 00000000000..403da110106 --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_tile.c @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2010 Maciej Cencora <[email protected]> + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "radeon_tile.h" + +#include <stdint.h> +#include <string.h> + +#include "main/macros.h" +#include "radeon_debug.h" + +#define MICRO_TILE_SIZE 32 + +static void micro_tile_8_x_4_8bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current source row */ + unsigned col; /* current source column */ + unsigned k; /* number of processed tiles */ + const unsigned tile_width = 8, tile_height = 4; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint8_t *src2 = (uint8_t *)src + src_pitch * row + col; + uint8_t *dst2 = (uint8_t *)dst + row * dst_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint8_t); + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint8_t)); + dst2 += tile_width; + src2 += src_pitch; + } + } + } +} + +static void micro_tile_4_x_4_16bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current source row */ + unsigned col; /* current source column */ + unsigned k; /* number of processed tiles */ + const unsigned tile_width = 4, tile_height = 4; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint16_t *src2 = (uint16_t *)src + src_pitch * row + col; + uint16_t *dst2 = (uint16_t *)dst + row * dst_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint16_t)); + dst2 += tile_width; + src2 += src_pitch; + } + } + } +} + +static void micro_tile_8_x_2_16bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current source row */ + unsigned col; /* current source column */ + unsigned k; /* number of processed tiles */ + const unsigned tile_width = 8, tile_height = 2; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint16_t *src2 = (uint16_t *)src + src_pitch * row + col; + uint16_t *dst2 = (uint16_t *)dst + row * dst_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint16_t)); + dst2 += tile_width; + src2 += src_pitch; + } + } + } +} + +static void micro_tile_4_x_2_32bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current source row */ + unsigned col; /* current source column */ + unsigned k; /* number of processed tiles */ + const unsigned tile_width = 4, tile_height = 2; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint32_t *src2 = (uint32_t *)src + src_pitch * row + col; + uint32_t *dst2 = (uint32_t *)dst + row * dst_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint32_t); + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint32_t)); + dst2 += tile_width; + src2 += src_pitch; + } + } + } +} + +static void micro_tile_2_x_2_64bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current source row */ + unsigned col; /* current source column */ + unsigned k; /* number of processed tiles */ + const unsigned tile_width = 2, tile_height = 2; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint64_t *src2 = (uint64_t *)src + src_pitch * row + col; + uint64_t *dst2 = (uint64_t *)dst + row * dst_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint64_t); + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint64_t)); + dst2 += tile_width; + src2 += src_pitch; + } + } + } +} + +static void micro_tile_1_x_1_128bit(const void * src, unsigned src_pitch, + void * dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned i, j; + const unsigned elem_size = 16; /* sizeof(uint128_t) */ + + for (j = 0; j < height; ++j) + { + for (i = 0; i < width; ++i) + { + memcpy(dst, src, width * elem_size); + dst += dst_pitch * elem_size; + src += src_pitch * elem_size; + } + } +} + +void tile_image(const void * src, unsigned src_pitch, + void *dst, unsigned dst_pitch, + gl_format format, unsigned width, unsigned height) +{ + assert(src_pitch >= width); + assert(dst_pitch >= width); + + radeon_print(RADEON_TEXTURE, RADEON_TRACE, + "Software tiling: src_pitch %d, dst_pitch %d, width %d, height %d, bpp %d\n", + src_pitch, dst_pitch, width, height, _mesa_get_format_bytes(format)); + + switch (_mesa_get_format_bytes(format)) + { + case 16: + micro_tile_1_x_1_128bit(src, src_pitch, dst, dst_pitch, width, height); + break; + case 8: + micro_tile_2_x_2_64bit(src, src_pitch, dst, dst_pitch, width, height); + break; + case 4: + micro_tile_4_x_2_32bit(src, src_pitch, dst, dst_pitch, width, height); + break; + case 2: + if (_mesa_get_format_bits(format, GL_DEPTH_BITS)) + { + micro_tile_4_x_4_16bit(src, src_pitch, dst, dst_pitch, width, height); + } + else + { + micro_tile_8_x_2_16bit(src, src_pitch, dst, dst_pitch, width, height); + } + break; + case 1: + micro_tile_8_x_4_8bit(src, src_pitch, dst, dst_pitch, width, height); + break; + default: + assert(0); + break; + } +} + +static void micro_untile_8_x_4_8bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current destination row */ + unsigned col; /* current destination column */ + unsigned k; /* current tile number */ + const unsigned tile_width = 8, tile_height = 4; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + assert(src_pitch % tile_width == 0); + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint8_t *src2 = (uint8_t *)src + row * src_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint8_t); + uint8_t *dst2 = (uint8_t *)dst + dst_pitch * row + col; + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint8_t)); + dst2 += dst_pitch; + src2 += tile_width; + } + } + } +} + +static void micro_untile_8_x_2_16bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current destination row */ + unsigned col; /* current destination column */ + unsigned k; /* current tile number */ + const unsigned tile_width = 8, tile_height = 2; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + assert(src_pitch % tile_width == 0); + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint16_t *src2 = (uint16_t *)src + row * src_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); + uint16_t *dst2 = (uint16_t *)dst + dst_pitch * row + col; + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint16_t)); + dst2 += dst_pitch; + src2 += tile_width; + } + } + } +} + +static void micro_untile_4_x_4_16bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current destination row */ + unsigned col; /* current destination column */ + unsigned k; /* current tile number */ + const unsigned tile_width = 4, tile_height = 4; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + assert(src_pitch % tile_width == 0); + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint16_t *src2 = (uint16_t *)src + row * src_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); + uint16_t *dst2 = (uint16_t *)dst + dst_pitch * row + col; + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint16_t)); + dst2 += dst_pitch; + src2 += tile_width; + } + } + } +} + +static void micro_untile_4_x_2_32bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current destination row */ + unsigned col; /* current destination column */ + unsigned k; /* current tile number */ + const unsigned tile_width = 4, tile_height = 2; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + assert(src_pitch % tile_width == 0); + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint32_t *src2 = (uint32_t *)src + row * src_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint32_t); + uint32_t *dst2 = (uint32_t *)dst + dst_pitch * row + col; + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint32_t)); + dst2 += dst_pitch; + src2 += tile_width; + } + } + } +} + +static void micro_untile_2_x_2_64bit(const void * const src, unsigned src_pitch, + void * const dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned row; /* current destination row */ + unsigned col; /* current destination column */ + unsigned k; /* current tile number */ + const unsigned tile_width = 2, tile_height = 2; + const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; + + assert(src_pitch % tile_width == 0); + + k = 0; + for (row = 0; row < height; row += tile_height) + { + for (col = 0; col < width; col += tile_width, ++k) + { + uint64_t *src2 = (uint64_t *)src + row * src_pitch + + (k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint64_t); + uint64_t *dst2 = (uint64_t *)dst + dst_pitch * row + col; + unsigned j; + + for (j = 0; j < MIN2(tile_height, height - row); ++j) + { + unsigned columns = MIN2(tile_width, width - col); + memcpy(dst2, src2, columns * sizeof(uint64_t)); + dst2 += dst_pitch; + src2 += tile_width; + } + } + } +} + +static void micro_untile_1_x_1_128bit(const void * src, unsigned src_pitch, + void * dst, unsigned dst_pitch, + unsigned width, unsigned height) +{ + unsigned i, j; + const unsigned elem_size = 16; /* sizeof(uint128_t) */ + + for (j = 0; j < height; ++j) + { + for (i = 0; i < width; ++i) + { + memcpy(dst, src, width * elem_size); + dst += dst_pitch * elem_size; + src += src_pitch * elem_size; + } + } +} + +void untile_image(const void * src, unsigned src_pitch, + void *dst, unsigned dst_pitch, + gl_format format, unsigned width, unsigned height) +{ + assert(src_pitch >= width); + assert(dst_pitch >= width); + + radeon_print(RADEON_TEXTURE, RADEON_TRACE, + "Software untiling: src_pitch %d, dst_pitch %d, width %d, height %d, bpp %d\n", + src_pitch, dst_pitch, width, height, _mesa_get_format_bytes(format)); + + switch (_mesa_get_format_bytes(format)) + { + case 16: + micro_untile_1_x_1_128bit(src, src_pitch, dst, dst_pitch, width, height); + break; + case 8: + micro_untile_2_x_2_64bit(src, src_pitch, dst, dst_pitch, width, height); + break; + case 4: + micro_untile_4_x_2_32bit(src, src_pitch, dst, dst_pitch, width, height); + break; + case 2: + if (_mesa_get_format_bits(format, GL_DEPTH_BITS)) + { + micro_untile_4_x_4_16bit(src, src_pitch, dst, dst_pitch, width, height); + } + else + { + micro_untile_8_x_2_16bit(src, src_pitch, dst, dst_pitch, width, height); + } + break; + case 1: + micro_untile_8_x_4_8bit(src, src_pitch, dst, dst_pitch, width, height); + break; + default: + assert(0); + break; + } +} + +void get_tile_size(gl_format format, unsigned *block_width, unsigned *block_height) +{ + switch (_mesa_get_format_bytes(format)) + { + case 16: + *block_width = 1; + *block_height = 1; + break; + case 8: + *block_width = 2; + *block_height = 2; + break; + case 4: + *block_width = 4; + *block_height = 2; + break; + case 2: + if (_mesa_get_format_bits(format, GL_DEPTH_BITS)) + { + *block_width = 4; + *block_height = 4; + } + else + { + *block_width = 8; + *block_height = 2; + } + break; + case 1: + *block_width = 8; + *block_height = 4; + break; + default: + assert(0); + break; + } +} diff --git a/src/mesa/drivers/dri/radeon/radeon_tile.h b/src/mesa/drivers/dri/radeon/radeon_tile.h new file mode 100644 index 00000000000..31d9c5611c3 --- /dev/null +++ b/src/mesa/drivers/dri/radeon/radeon_tile.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2010 Maciej Cencora <[email protected]> + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <main/formats.h> + +void tile_image(const void * src, unsigned src_pitch, + void *dst, unsigned dst_pitch, + gl_format format, unsigned width, unsigned height); + +void untile_image(const void * src, unsigned src_pitch, + void *dst, unsigned dst_pitch, + gl_format format, unsigned width, unsigned height); + +void get_tile_size(gl_format format, unsigned *block_width, unsigned *block_height); diff --git a/src/mesa/drivers/dri/radeon/server/radeon_dri.c b/src/mesa/drivers/dri/radeon/server/radeon_dri.c deleted file mode 100644 index 7ead588dac8..00000000000 --- a/src/mesa/drivers/dri/radeon/server/radeon_dri.c +++ /dev/null @@ -1,1337 +0,0 @@ -/** - * \file server/radeon_dri.c - * \brief File to perform the device-specific initialization tasks typically - * done in the X server. - * - * Here they are converted to run in the client (or perhaps a standalone - * process), and to work with the frame buffer device rather than the X - * server infrastructure. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include "driver.h" -#include "drm.h" -#include "memops.h" - -#include "radeon.h" -#include "radeon_dri.h" -#include "radeon_macros.h" -#include "radeon_reg.h" -#include "drm_sarea.h" - -static size_t radeon_drm_page_size; - -static int RadeonSetParam(const DRIDriverContext *ctx, int param, int value) -{ - drm_radeon_setparam_t sp; - - memset(&sp, 0, sizeof(sp)); - sp.param = param; - sp.value = value; - - if (drmCommandWrite(ctx->drmFD, DRM_RADEON_SETPARAM, &sp, sizeof(sp))) { - return -1; - } - - return 0; -} - -/** - * \brief Wait for free FIFO entries. - * - * \param ctx display handle. - * \param entries number of free entries to wait. - * - * It polls the free entries from the chip until it reaches the requested value - * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out. - */ -static void RADEONWaitForFifo( const DRIDriverContext *ctx, - int entries ) -{ - unsigned char *RADEONMMIO = ctx->MMIOAddress; - int i; - - for (i = 0; i < 3000; i++) { - int fifo_slots = - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; - if (fifo_slots >= entries) return; - } - - /* There are recoveries possible, but I haven't seen them work - * in practice: - */ - fprintf(stderr, "FIFO timed out: %d entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS)); - exit(1); -} - -/** - * \brief Read a PLL register. - * - * \param ctx display handle. - * \param addr PLL register index. - * - * \return value of the PLL register. - */ -static unsigned int RADEONINPLL( const DRIDriverContext *ctx, int addr) -{ - unsigned char *RADEONMMIO = ctx->MMIOAddress; - unsigned int data; - - OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f); - data = INREG(RADEON_CLOCK_CNTL_DATA); - - return data; -} - -/** - * \brief Reset graphics card to known state. - * - * \param ctx display handle. - * - * Resets the values of several Radeon registers. - */ -static void RADEONEngineReset( const DRIDriverContext *ctx ) -{ - unsigned char *RADEONMMIO = ctx->MMIOAddress; - unsigned int clock_cntl_index; - unsigned int mclk_cntl; - unsigned int rbbm_soft_reset; - unsigned int host_path_cntl; - int i; - - OUTREGP(RADEON_RB2D_DSTCACHE_CTLSTAT, - RADEON_RB2D_DC_FLUSH_ALL, - ~RADEON_RB2D_DC_FLUSH_ALL); - for (i = 0; i < 512; i++) { - if (!(INREG(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY)) - break; - } - - clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); - - mclk_cntl = INPLL(ctx, RADEON_MCLK_CNTL); - OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl | - RADEON_FORCEON_MCLKA | - RADEON_FORCEON_MCLKB | - RADEON_FORCEON_YCLKA | - RADEON_FORCEON_YCLKB | - RADEON_FORCEON_MC | - RADEON_FORCEON_AIC)); - - /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some - * unexpected behaviour on some machines. Here we use - * RADEON_HOST_PATH_CNTL to reset it. - */ - host_path_cntl = INREG(RADEON_HOST_PATH_CNTL); - rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - - OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | - RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | - RADEON_SOFT_RESET_SE | - RADEON_SOFT_RESET_RE | - RADEON_SOFT_RESET_PP | - RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB)); - INREG(RADEON_RBBM_SOFT_RESET); - OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & - (unsigned int) ~(RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | - RADEON_SOFT_RESET_SE | - RADEON_SOFT_RESET_RE | - RADEON_SOFT_RESET_PP | - RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB))); - INREG(RADEON_RBBM_SOFT_RESET); - - OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET); - INREG(RADEON_HOST_PATH_CNTL); - OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl); - - OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); - - OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); - OUTPLL(RADEON_MCLK_CNTL, mclk_cntl); -} - -/** - * \brief Restore the drawing engine. - * - * \param ctx display handle - * - * Resets the graphics card and sets initial values for several registers of - * the card's drawing engine. - * - * Turns on the radeon command processor engine (i.e., the ringbuffer). - */ -static int RADEONEngineRestore( const DRIDriverContext *ctx ) -{ - RADEONInfoPtr info = ctx->driverPrivate; - unsigned char *RADEONMMIO = ctx->MMIOAddress; - int pitch64, datatype, dp_gui_master_cntl, err; - - fprintf(stderr, "%s\n", __FUNCTION__); - - OUTREG(RADEON_RB3D_CNTL, 0); - RADEONEngineReset( ctx ); - - switch (ctx->bpp) { - case 16: datatype = 4; break; - case 32: datatype = 6; break; - default: return 0; - } - - dp_gui_master_cntl = - ((datatype << RADEON_GMC_DST_DATATYPE_SHIFT) - | RADEON_GMC_CLR_CMP_CNTL_DIS); - - pitch64 = ((ctx->shared.virtualWidth * (ctx->bpp / 8) + 0x3f)) >> 6; - - RADEONWaitForFifo(ctx, 1); - OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DEFAULT_OFFSET) & 0xC0000000) - | (pitch64 << 22))); - - RADEONWaitForFifo(ctx, 1); - OUTREG(RADEON_SURFACE_CNTL, RADEON_SURF_TRANSLATION_DIS); - - RADEONWaitForFifo(ctx, 1); - OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX - | RADEON_DEFAULT_SC_BOTTOM_MAX)); - - RADEONWaitForFifo(ctx, 1); - OUTREG(RADEON_DP_GUI_MASTER_CNTL, (dp_gui_master_cntl - | RADEON_GMC_BRUSH_SOLID_COLOR - | RADEON_GMC_SRC_DATATYPE_COLOR)); - - RADEONWaitForFifo(ctx, 7); - OUTREG(RADEON_DST_LINE_START, 0); - OUTREG(RADEON_DST_LINE_END, 0); - OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); - OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0); - OUTREG(RADEON_DP_SRC_FRGD_CLR, 0xffffffff); - OUTREG(RADEON_DP_SRC_BKGD_CLR, 0); - OUTREG(RADEON_DP_WRITE_MASK, 0xffffffff); - OUTREG(RADEON_AUX_SC_CNTL, 0); - -/* RADEONWaitForIdleMMIO(ctx); */ - usleep(100); - - - OUTREG(RADEON_GEN_INT_CNTL, info->gen_int_cntl); - if (info->colorTiling) - info->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; - OUTREG(RADEON_CRTC_OFFSET_CNTL, info->crtc_offset_cntl); - - /* Initialize and start the CP if required */ - if ((err = drmCommandNone(ctx->drmFD, DRM_RADEON_CP_START)) != 0) { - fprintf(stderr, "%s: CP start %d\n", __FUNCTION__, err); - return 0; - } - - return 1; -} - - -/** - * \brief Shutdown the drawing engine. - * - * \param ctx display handle - * - * Turns off the command processor engine & restores the graphics card - * to a state that fbdev understands. - */ -static int RADEONEngineShutdown( const DRIDriverContext *ctx ) -{ - drm_radeon_cp_stop_t stop; - int ret, i; - - stop.flush = 1; - stop.idle = 1; - - ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, - sizeof(drm_radeon_cp_stop_t)); - - if (ret == 0) { - return 0; - } else if (errno != EBUSY) { - return -errno; - } - - stop.flush = 0; - - i = 0; - do { - ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, &stop, - sizeof(drm_radeon_cp_stop_t)); - } while (ret && errno == EBUSY && i++ < 10); - - if (ret == 0) { - return 0; - } else if (errno != EBUSY) { - return -errno; - } - - stop.idle = 0; - - if (drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_STOP, - &stop, sizeof(drm_radeon_cp_stop_t))) { - return -errno; - } else { - return 0; - } -} - -/** - * \brief Compute base 2 logarithm. - * - * \param val value. - * - * \return base 2 logarithm of \p val. - */ -static int RADEONMinBits(int val) -{ - int bits; - - if (!val) return 1; - for (bits = 0; val; val >>= 1, ++bits); - return bits; -} - -/** - * \brief Initialize the AGP state - * - * \param ctx display handle. - * \param info driver private data. - * - * \return one on success, or zero on failure. - * - * Acquires and enables the AGP device. Reserves memory in the AGP space for - * the ring buffer, vertex buffers and textures. Initialize the Radeon - * registers to point to that memory and add client mappings. - */ -static int RADEONDRIAgpInit( const DRIDriverContext *ctx, RADEONInfoPtr info) -{ - unsigned char *RADEONMMIO = ctx->MMIOAddress; - unsigned long mode; - int ret; - int s, l; - - if (drmAgpAcquire(ctx->drmFD) < 0) { - fprintf(stderr, "[gart] AGP not available\n"); - return 0; - } - - /* Modify the mode if the default mode is not appropriate for this - * particular combination of graphics card and AGP chipset. - */ - mode = drmAgpGetMode(ctx->drmFD); /* Default mode */ - - /* Disable fast write entirely - too many lockups. - */ - mode &= ~RADEON_AGP_MODE_MASK; - switch (ctx->agpmode) { - case 4: mode |= RADEON_AGP_4X_MODE; - case 2: mode |= RADEON_AGP_2X_MODE; - case 1: default: mode |= RADEON_AGP_1X_MODE; - } - - if (drmAgpEnable(ctx->drmFD, mode) < 0) { - fprintf(stderr, "[gart] AGP not enabled\n"); - drmAgpRelease(ctx->drmFD); - return 0; - } - else - fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode); - - /* Workaround for some hardware bugs */ - if (info->ChipFamily < CHIP_FAMILY_R200) - OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000); - - info->gartOffset = 0; - - if ((ret = drmAgpAlloc(ctx->drmFD, info->gartSize*1024*1024, 0, NULL, - &info->gartMemHandle)) < 0) { - fprintf(stderr, "[gart] Out of memory (%d)\n", ret); - drmAgpRelease(ctx->drmFD); - return 0; - } - fprintf(stderr, - "[gart] %d kB allocated with handle 0x%08x\n", - info->gartSize*1024, (unsigned)info->gartMemHandle); - - if (drmAgpBind(ctx->drmFD, - info->gartMemHandle, info->gartOffset) < 0) { - fprintf(stderr, "[gart] Could not bind\n"); - drmAgpFree(ctx->drmFD, info->gartMemHandle); - drmAgpRelease(ctx->drmFD); - return 0; - } - - /* Initialize the CP ring buffer data */ - info->ringStart = info->gartOffset; - info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size; - - info->ringReadOffset = info->ringStart + info->ringMapSize; - info->ringReadMapSize = radeon_drm_page_size; - - /* Reserve space for vertex/indirect buffers */ - info->bufStart = info->ringReadOffset + info->ringReadMapSize; - info->bufMapSize = info->bufSize*1024*1024; - - /* Reserve the rest for AGP textures */ - info->gartTexStart = info->bufStart + info->bufMapSize; - s = (info->gartSize*1024*1024 - info->gartTexStart); - l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - info->gartTexMapSize = (s >> l) << l; - info->log2GARTTexGran = l; - - if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize, - DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) { - fprintf(stderr, "[gart] Could not add ring mapping\n"); - return 0; - } - fprintf(stderr, "[gart] ring handle = 0x%08x\n", info->ringHandle); - - - if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize, - DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) { - fprintf(stderr, - "[gart] Could not add ring read ptr mapping\n"); - return 0; - } - - fprintf(stderr, - "[gart] ring read ptr handle = 0x%08lx\n", - info->ringReadPtrHandle); - - if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize, - DRM_AGP, 0, &info->bufHandle) < 0) { - fprintf(stderr, - "[gart] Could not add vertex/indirect buffers mapping\n"); - return 0; - } - fprintf(stderr, - "[gart] vertex/indirect buffers handle = 0x%08x\n", - info->bufHandle); - - if (drmAddMap(ctx->drmFD, info->gartTexStart, info->gartTexMapSize, - DRM_AGP, 0, &info->gartTexHandle) < 0) { - fprintf(stderr, - "[gart] Could not add AGP texture map mapping\n"); - return 0; - } - fprintf(stderr, - "[gart] AGP texture map handle = 0x%08lx\n", - info->gartTexHandle); - - /* Initialize Radeon's AGP registers */ - /* Ring buffer is at AGP offset 0 */ - OUTREG(RADEON_AGP_BASE, info->ringHandle); - - return 1; -} - -/* Initialize the PCI GART state. Request memory for use in PCI space, - * and initialize the Radeon registers to point to that memory. - */ -static int RADEONDRIPciInit(const DRIDriverContext *ctx, RADEONInfoPtr info) -{ - int ret; - int flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; - int s, l; - - ret = drmScatterGatherAlloc(ctx->drmFD, info->gartSize*1024*1024, - &info->gartMemHandle); - if (ret < 0) { - fprintf(stderr, "[pci] Out of memory (%d)\n", ret); - return 0; - } - fprintf(stderr, - "[pci] %d kB allocated with handle 0x%08lx\n", - info->gartSize*1024, info->gartMemHandle); - - info->gartOffset = 0; - - /* Initialize the CP ring buffer data */ - info->ringStart = info->gartOffset; - info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size; - - info->ringReadOffset = info->ringStart + info->ringMapSize; - info->ringReadMapSize = radeon_drm_page_size; - - /* Reserve space for vertex/indirect buffers */ - info->bufStart = info->ringReadOffset + info->ringReadMapSize; - info->bufMapSize = info->bufSize*1024*1024; - - /* Reserve the rest for AGP textures */ - info->gartTexStart = info->bufStart + info->bufMapSize; - s = (info->gartSize*1024*1024 - info->gartTexStart); - l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - info->gartTexMapSize = (s >> l) << l; - info->log2GARTTexGran = l; - - if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize, - DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) { - fprintf(stderr, - "[pci] Could not add ring mapping\n"); - return 0; - } - fprintf(stderr, - "[pci] ring handle = 0x%08x\n", info->ringHandle); - - if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize, - DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) { - fprintf(stderr, - "[pci] Could not add ring read ptr mapping\n"); - return 0; - } - fprintf(stderr, - "[pci] ring read ptr handle = 0x%08lx\n", - info->ringReadPtrHandle); - - if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize, - DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) { - fprintf(stderr, - "[pci] Could not add vertex/indirect buffers mapping\n"); - return 0; - } - fprintf(stderr, - "[pci] vertex/indirect buffers handle = 0x%08lx\n", - info->bufHandle); - - if (drmAddMap(ctx->drmFD, info->gartTexStart, info->gartTexMapSize, - DRM_SCATTER_GATHER, 0, &info->gartTexHandle) < 0) { - fprintf(stderr, - "[pci] Could not add GART texture map mapping\n"); - return 0; - } - fprintf(stderr, - "[pci] GART texture map handle = 0x%08x\n", - info->gartTexHandle); - - return 1; -} - - -/** - * \brief Initialize the kernel data structures and enable the CP engine. - * - * \param ctx display handle. - * \param info driver private data. - * - * \return non-zero on success, or zero on failure. - * - * This function is a wrapper around the DRM_RADEON_CP_INIT command, passing - * all the parameters in a drm_radeon_init_t structure. - */ -static int RADEONDRIKernelInit( const DRIDriverContext *ctx, - RADEONInfoPtr info) -{ - int cpp = ctx->bpp / 8; - drm_radeon_init_t drmInfo; - int ret; - - memset(&drmInfo, 0, sizeof(drm_radeon_init_t)); - - if ( (info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_M9) || - (info->ChipFamily == CHIP_FAMILY_RV280) ) - drmInfo.func = RADEON_INIT_R200_CP; - else - drmInfo.func = RADEON_INIT_CP; - - /* This is the struct passed to the kernel module for its initialization */ - drmInfo.sarea_priv_offset = sizeof(drm_sarea_t); - drmInfo.is_pci = ctx->isPCI; - drmInfo.cp_mode = RADEON_DEFAULT_CP_BM_MODE; - drmInfo.gart_size = info->gartSize*1024*1024; - drmInfo.ring_size = info->ringSize*1024*1024; - drmInfo.usec_timeout = 1000; - drmInfo.fb_bpp = ctx->bpp; - drmInfo.depth_bpp = ctx->bpp; - drmInfo.front_offset = info->frontOffset; - drmInfo.front_pitch = info->frontPitch * cpp; - drmInfo.back_offset = info->backOffset; - drmInfo.back_pitch = info->backPitch * cpp; - drmInfo.depth_offset = info->depthOffset; - drmInfo.depth_pitch = info->depthPitch * cpp; - drmInfo.fb_offset = info->LinearAddr; - drmInfo.mmio_offset = info->registerHandle; - drmInfo.ring_offset = info->ringHandle; - drmInfo.ring_rptr_offset = info->ringReadPtrHandle; - drmInfo.buffers_offset = info->bufHandle; - drmInfo.gart_textures_offset = info->gartTexHandle; - - ret = drmCommandWrite(ctx->drmFD, DRM_RADEON_CP_INIT, &drmInfo, - sizeof(drm_radeon_init_t)); - - return ret >= 0; -} - - -/** - * \brief Initialize the AGP heap. - * - * \param ctx display handle. - * \param info driver private data. - * - * This function is a wrapper around the DRM_RADEON_INIT_HEAP command, passing - * all the parameters in a drm_radeon_mem_init_heap structure. - */ -static void RADEONDRIAgpHeapInit(const DRIDriverContext *ctx, - RADEONInfoPtr info) -{ - drm_radeon_mem_init_heap_t drmHeap; - - /* Start up the simple memory manager for gart space */ - drmHeap.region = RADEON_MEM_REGION_GART; - drmHeap.start = 0; - drmHeap.size = info->gartTexMapSize; - - if (drmCommandWrite(ctx->drmFD, DRM_RADEON_INIT_HEAP, - &drmHeap, sizeof(drmHeap))) { - fprintf(stderr, - "[drm] Failed to initialized gart heap manager\n"); - } else { - fprintf(stderr, - "[drm] Initialized kernel gart heap manager, %d\n", - info->gartTexMapSize); - } -} - -/** - * \brief Add a map for the vertex buffers that will be accessed by any - * DRI-based clients. - * - * \param ctx display handle. - * \param info driver private data. - * - * \return one on success, or zero on failure. - * - * Calls drmAddBufs() with the previously allocated vertex buffers. - */ -static int RADEONDRIBufInit( const DRIDriverContext *ctx, RADEONInfoPtr info ) -{ - /* Initialize vertex buffers */ - info->bufNumBufs = drmAddBufs(ctx->drmFD, - info->bufMapSize / RADEON_BUFFER_SIZE, - RADEON_BUFFER_SIZE, - ctx->isPCI ? DRM_SG_BUFFER : DRM_AGP_BUFFER, - info->bufStart); - - if (info->bufNumBufs <= 0) { - fprintf(stderr, - "[drm] Could not create vertex/indirect buffers list\n"); - return 0; - } - fprintf(stderr, - "[drm] Added %d %d byte vertex/indirect buffers\n", - info->bufNumBufs, RADEON_BUFFER_SIZE); - - return 1; -} - -/** - * \brief Install an IRQ handler. - * - * \param ctx display handle. - * \param info driver private data. - * - * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to - * IRQ-free operation on failure. - */ -static void RADEONDRIIrqInit(const DRIDriverContext *ctx, - RADEONInfoPtr info) -{ - if (!info->irq) { - info->irq = drmGetInterruptFromBusID(ctx->drmFD, - ctx->pciBus, - ctx->pciDevice, - ctx->pciFunc); - - if ((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) { - fprintf(stderr, - "[drm] failure adding irq handler, " - "there is a device already using that irq\n" - "[drm] falling back to irq-free operation\n"); - info->irq = 0; - } - } - - if (info->irq) - fprintf(stderr, - "[drm] dma control initialized, using IRQ %d\n", - info->irq); -} - -static int RADEONCheckDRMVersion( const DRIDriverContext *ctx, - RADEONInfoPtr info ) -{ - drmVersionPtr version; - - version = drmGetVersion(ctx->drmFD); - if (version) { - int req_minor, req_patch; - - /* Need 1.8.x for proper cleanup-on-client-exit behaviour. - */ - req_minor = 8; - req_patch = 0; - - if (version->version_major != 1 || - version->version_minor < req_minor || - (version->version_minor == req_minor && - version->version_patchlevel < req_patch)) { - /* Incompatible drm version */ - fprintf(stderr, - "[dri] RADEONDRIScreenInit failed because of a version " - "mismatch.\n" - "[dri] radeon.o kernel module version is %d.%d.%d " - "but version 1.%d.%d or newer is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel, - req_minor, - req_patch); - drmFreeVersion(version); - return 0; - } - - info->drmMinor = version->version_minor; - drmFreeVersion(version); - } - - return 1; -} - -static int RADEONMemoryInit( const DRIDriverContext *ctx, RADEONInfoPtr info ) -{ - int width_bytes = ctx->shared.virtualWidth * ctx->cpp; - int cpp = ctx->cpp; - int bufferSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); - int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes - + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); - int l; - - info->frontOffset = 0; - info->frontPitch = ctx->shared.virtualWidth; - - fprintf(stderr, - "Using %d MB AGP aperture\n", info->gartSize); - fprintf(stderr, - "Using %d MB for the ring buffer\n", info->ringSize); - fprintf(stderr, - "Using %d MB for vertex/indirect buffers\n", info->bufSize); - fprintf(stderr, - "Using %d MB for AGP textures\n", info->gartTexSize); - - /* Front, back and depth buffers - everything else texture?? - */ - info->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize; - - if (ctx->colorTiling==1) - { - info->textureSize = ctx->shared.fbSize - ((ctx->shared.fbSize - info->textureSize + width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes*16); - } - - if (info->textureSize < 0) - return 0; - - l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - - /* Round the texture size up to the nearest whole number of - * texture regions. Again, be greedy about this, don't - * round down. - */ - info->log2TexGran = l; - info->textureSize = (info->textureSize >> l) << l; - - /* Set a minimum usable local texture heap size. This will fit - * two 256x256x32bpp textures. - */ - if (info->textureSize < 512 * 1024) { - info->textureOffset = 0; - info->textureSize = 0; - } - - /* Reserve space for textures */ - if (ctx->colorTiling==1) - { - info->textureOffset = ((ctx->shared.fbSize - info->textureSize) / - (width_bytes * 16)) * (width_bytes*16); - } - else - { - info->textureOffset = ((ctx->shared.fbSize - info->textureSize + - RADEON_BUFFER_ALIGN) & - ~RADEON_BUFFER_ALIGN); - } - /* Reserve space for the shared depth - * buffer. - */ - info->depthOffset = ((info->textureOffset - depthSize + - RADEON_BUFFER_ALIGN) & - ~RADEON_BUFFER_ALIGN); - info->depthPitch = ctx->shared.virtualWidth; - - info->backOffset = ((info->depthOffset - bufferSize + - RADEON_BUFFER_ALIGN) & - ~RADEON_BUFFER_ALIGN); - info->backPitch = ctx->shared.virtualWidth; - - - fprintf(stderr, - "Will use back buffer at offset 0x%x\n", - info->backOffset); - fprintf(stderr, - "Will use depth buffer at offset 0x%x\n", - info->depthOffset); - fprintf(stderr, - "Will use %d kb for textures at offset 0x%x\n", - info->textureSize/1024, info->textureOffset); - - info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | - (info->frontOffset >> 10)); - - info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | - (info->backOffset >> 10)); - - info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | - (info->depthOffset >> 10)); - - return 1; -} - -static int RADEONColorTilingInit( const DRIDriverContext *ctx, RADEONInfoPtr info ) -{ - int width_bytes = ctx->shared.virtualWidth * ctx->cpp; - int bufferSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes + RADEON_BUFFER_ALIGN) - & ~RADEON_BUFFER_ALIGN); - /* Setup color tiling */ - if (info->drmMinor<14) - info->colorTiling=0; - - if (info->colorTiling) - { - - int colorTilingFlag; - drm_radeon_surface_alloc_t front,back; - - RadeonSetParam(ctx, RADEON_SETPARAM_SWITCH_TILING, info->colorTiling ? 1 : 0); - - /* Setup the surfaces */ - if (info->ChipFamily < CHIP_FAMILY_R200) - colorTilingFlag=RADEON_SURF_TILE_COLOR_MACRO; - else - colorTilingFlag=R200_SURF_TILE_COLOR_MACRO; - - front.address = info->frontOffset; - front.size = bufferSize; - front.flags = (width_bytes) | colorTilingFlag; - drmCommandWrite(ctx->drmFD, DRM_RADEON_SURF_ALLOC, &front,sizeof(front)); - - back.address = info->backOffset; - back.size = bufferSize; - back.flags = (width_bytes) | colorTilingFlag; - drmCommandWrite(ctx->drmFD, DRM_RADEON_SURF_ALLOC, &back,sizeof(back)); - - } - return 1; -} - - - -/** - * Called at the start of each server generation. - * - * \param ctx display handle. - * \param info driver private data. - * - * \return non-zero on success, or zero on failure. - * - * Performs static frame buffer allocation. Opens the DRM device and add maps - * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more - * information. Creates a \e server context to grab the lock for the - * initialization ioctls and calls the other initilization functions in this - * file. Starts the CP engine via the DRM_RADEON_CP_START command. - * - * Setups a RADEONDRIRec structure to be passed to radeon_dri.so for its - * initialization. - */ -static int RADEONScreenInit( DRIDriverContext *ctx, RADEONInfoPtr info ) -{ - RADEONDRIPtr pRADEONDRI; - int err; - - usleep(100); - /*assert(!ctx->IsClient);*/ - - { - int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); - int maxy = ctx->shared.fbSize / width_bytes; - - - if (maxy <= ctx->shared.virtualHeight * 3) { - fprintf(stderr, - "Static buffer allocation failed -- " - "need at least %d kB video memory (have %d kB)\n", - (ctx->shared.virtualWidth * ctx->shared.virtualHeight * - ctx->cpp * 3 + 1023) / 1024, - ctx->shared.fbSize / 1024); - return 0; - } - } - - - if (info->ChipFamily >= CHIP_FAMILY_R300) { - fprintf(stderr, - "Direct rendering not yet supported on " - "Radeon 9700 and newer cards\n"); - return 0; - } - - radeon_drm_page_size = getpagesize(); - - info->registerSize = ctx->MMIOSize; - ctx->shared.SAREASize = SAREA_MAX; - - /* Note that drmOpen will try to load the kernel module, if needed. */ - ctx->drmFD = drmOpen("radeon", NULL ); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - - if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - if (drmAddMap( ctx->drmFD, - 0, - ctx->shared.SAREASize, - DRM_SHM, - DRM_CONTAINS_LOCK, - &ctx->shared.hSAREA) < 0) - { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap( ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - } - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - /* Need to AddMap the framebuffer and mmio regions here: - */ - if (drmAddMap( ctx->drmFD, - (drm_handle_t)ctx->FBStart, - ctx->FBSize, - DRM_FRAME_BUFFER, -#ifndef _EMBEDDED - 0, -#else - DRM_READ_ONLY, -#endif - &ctx->shared.hFrameBuffer) < 0) - { - fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); - return 0; - } - - fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", - ctx->shared.hFrameBuffer); - - - - if (drmAddMap(ctx->drmFD, - ctx->MMIOStart, - ctx->MMIOSize, - DRM_REGISTERS, - DRM_READ_ONLY, - &info->registerHandle) < 0) { - fprintf(stderr, "[drm] drmAddMap mmio failed\n"); - return 0; - } - fprintf(stderr, - "[drm] register handle = 0x%08lx\n", info->registerHandle); - - /* Check the radeon DRM version */ - if (!RADEONCheckDRMVersion(ctx, info)) { - return 0; - } - - if (ctx->isPCI) { - /* Initialize PCI */ - if (!RADEONDRIPciInit(ctx, info)) - return 0; - } - else { - /* Initialize AGP */ - if (!RADEONDRIAgpInit(ctx, info)) - return 0; - } - - /* Memory manager setup */ - if (!RADEONMemoryInit(ctx, info)) { - return 0; - } - - /* Create a 'server' context so we can grab the lock for - * initialization ioctls. - */ - if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return 0; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - /* Initialize the kernel data structures */ - if (!RADEONDRIKernelInit(ctx, info)) { - fprintf(stderr, "RADEONDRIKernelInit failed\n"); - DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); - return 0; - } - - /* Initialize the vertex buffers list */ - if (!RADEONDRIBufInit(ctx, info)) { - fprintf(stderr, "RADEONDRIBufInit failed\n"); - DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); - return 0; - } - - RADEONColorTilingInit(ctx, info); - - /* Initialize IRQ */ - RADEONDRIIrqInit(ctx, info); - - /* Initialize kernel gart memory manager */ - RADEONDRIAgpHeapInit(ctx, info); - - fprintf(stderr,"color tiling %sabled\n", info->colorTiling?"en":"dis"); - fprintf(stderr,"page flipping %sabled\n", info->page_flip_enable?"en":"dis"); - /* Initialize the SAREA private data structure */ - { - drm_radeon_sarea_t *pSAREAPriv; - pSAREAPriv = (drm_radeon_sarea_t *)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); - pSAREAPriv->pfState = info->page_flip_enable; - } - - - /* Quick hack to clear the front & back buffers. Could also use - * the clear ioctl to do this, but would need to setup hw state - * first. - */ - drimemsetio((char *)ctx->FBAddress + info->frontOffset, - 0, - info->frontPitch * ctx->cpp * ctx->shared.virtualHeight ); - - drimemsetio((char *)ctx->FBAddress + info->backOffset, - 0, - info->backPitch * ctx->cpp * ctx->shared.virtualHeight ); - - /* This is the struct passed to radeon_dri.so for its initialization */ - ctx->driverClientMsg = malloc(sizeof(RADEONDRIRec)); - ctx->driverClientMsgSize = sizeof(RADEONDRIRec); - pRADEONDRI = (RADEONDRIPtr)ctx->driverClientMsg; - pRADEONDRI->deviceID = info->Chipset; - pRADEONDRI->width = ctx->shared.virtualWidth; - pRADEONDRI->height = ctx->shared.virtualHeight; - pRADEONDRI->depth = ctx->bpp; /* XXX: depth */ - pRADEONDRI->bpp = ctx->bpp; - pRADEONDRI->IsPCI = ctx->isPCI; - pRADEONDRI->AGPMode = ctx->agpmode; - pRADEONDRI->frontOffset = info->frontOffset; - pRADEONDRI->frontPitch = info->frontPitch; - pRADEONDRI->backOffset = info->backOffset; - pRADEONDRI->backPitch = info->backPitch; - pRADEONDRI->depthOffset = info->depthOffset; - pRADEONDRI->depthPitch = info->depthPitch; - pRADEONDRI->textureOffset = info->textureOffset; - pRADEONDRI->textureSize = info->textureSize; - pRADEONDRI->log2TexGran = info->log2TexGran; - pRADEONDRI->registerHandle = info->registerHandle; - pRADEONDRI->registerSize = info->registerSize; - pRADEONDRI->statusHandle = info->ringReadPtrHandle; - pRADEONDRI->statusSize = info->ringReadMapSize; - pRADEONDRI->gartTexHandle = info->gartTexHandle; - pRADEONDRI->gartTexMapSize = info->gartTexMapSize; - pRADEONDRI->log2GARTTexGran = info->log2GARTTexGran; - pRADEONDRI->gartTexOffset = info->gartTexStart; - pRADEONDRI->sarea_priv_offset = sizeof(drm_sarea_t); - - /* Don't release the lock now - let the VT switch handler do it. */ - - return 1; -} - - -/** - * \brief Get Radeon chip family from chipset number. - * - * \param info driver private data. - * - * \return non-zero on success, or zero on failure. - * - * Called by radeonInitFBDev() to set RADEONInfoRec::ChipFamily - * according to the value of RADEONInfoRec::Chipset. Fails if the - * chipset is unrecognized or not appropriate for this driver (i.e., not - * an r100 style radeon) - */ -static int get_chipfamily_from_chipset( RADEONInfoPtr info ) -{ - switch (info->Chipset) { - case PCI_CHIP_RADEON_LY: - case PCI_CHIP_RADEON_LZ: - info->ChipFamily = CHIP_FAMILY_M6; - break; - - case PCI_CHIP_RADEON_QY: - case PCI_CHIP_RADEON_QZ: - info->ChipFamily = CHIP_FAMILY_VE; - break; - - case PCI_CHIP_R200_QL: - case PCI_CHIP_R200_QN: - case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_Ql: - case PCI_CHIP_R200_BB: - info->ChipFamily = CHIP_FAMILY_R200; - break; - - case PCI_CHIP_RV200_QW: /* RV200 desktop */ - case PCI_CHIP_RV200_QX: - info->ChipFamily = CHIP_FAMILY_RV200; - break; - - case PCI_CHIP_RADEON_LW: - case PCI_CHIP_RADEON_LX: - info->ChipFamily = CHIP_FAMILY_M7; - break; - - case PCI_CHIP_RV250_Id: - case PCI_CHIP_RV250_Ie: - case PCI_CHIP_RV250_If: - case PCI_CHIP_RV250_Ig: - info->ChipFamily = CHIP_FAMILY_RV250; - break; - - case PCI_CHIP_RV250_Ld: - case PCI_CHIP_RV250_Le: - case PCI_CHIP_RV250_Lf: - case PCI_CHIP_RV250_Lg: - info->ChipFamily = CHIP_FAMILY_M9; - break; - - case PCI_CHIP_RV280_Y_: - case PCI_CHIP_RV280_Ya: - case PCI_CHIP_RV280_Yb: - case PCI_CHIP_RV280_Yc: - info->ChipFamily = CHIP_FAMILY_RV280; - break; - - case PCI_CHIP_R300_ND: - case PCI_CHIP_R300_NE: - case PCI_CHIP_R300_NF: - case PCI_CHIP_R300_NG: - info->ChipFamily = CHIP_FAMILY_R300; - break; - - default: - /* Original Radeon/7200 */ - info->ChipFamily = CHIP_FAMILY_RADEON; - } - - return 1; -} - - -/** - * \brief Validate the fbdev mode. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Saves some registers and returns 1. - * - * \sa radeonValidateMode(). - */ -static int radeonValidateMode( const DRIDriverContext *ctx ) -{ - unsigned char *RADEONMMIO = ctx->MMIOAddress; - RADEONInfoPtr info = ctx->driverPrivate; - - info->gen_int_cntl = INREG(RADEON_GEN_INT_CNTL); - info->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); - - if (info->colorTiling) - info->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; - return 1; -} - - -/** - * \brief Examine mode returned by fbdev. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Restores registers that fbdev has clobbered and returns 1. - * - * \sa radeonValidateMode(). - */ -static int radeonPostValidateMode( const DRIDriverContext *ctx ) -{ - unsigned char *RADEONMMIO = ctx->MMIOAddress; - RADEONInfoPtr info = ctx->driverPrivate; - - RADEONColorTilingInit( ctx, info); - OUTREG(RADEON_GEN_INT_CNTL, info->gen_int_cntl); - if (info->colorTiling) - info->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; - OUTREG(RADEON_CRTC_OFFSET_CNTL, info->crtc_offset_cntl); - - return 1; -} - - -/** - * \brief Initialize the framebuffer device mode - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Fills in \p info with some default values and some information from \p ctx - * and then calls RADEONScreenInit() for the screen initialization. - * - * Before exiting clears the framebuffer memory accessing it directly. - */ -static int radeonInitFBDev( DRIDriverContext *ctx ) -{ - RADEONInfoPtr info = calloc(1, sizeof(*info)); - - { - int dummy = ctx->shared.virtualWidth; - - if (ctx->colorTiling==1) - { - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 255) & ~255; break; - case 2: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 63) & ~63; break; - } - } else { - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; - } - } - - ctx->shared.virtualWidth = dummy; - ctx->shared.Width = dummy; - } - - fprintf(stderr,"shared virtual width is %d\n", ctx->shared.virtualWidth); - ctx->driverPrivate = (void *)info; - - info->gartFastWrite = RADEON_DEFAULT_AGP_FAST_WRITE; - info->gartSize = RADEON_DEFAULT_AGP_SIZE; - info->gartTexSize = RADEON_DEFAULT_AGP_TEX_SIZE; - info->bufSize = RADEON_DEFAULT_BUFFER_SIZE; - info->ringSize = RADEON_DEFAULT_RING_SIZE; - info->page_flip_enable = RADEON_DEFAULT_PAGE_FLIP; - info->colorTiling = ctx->colorTiling; - - info->Chipset = ctx->chipset; - - if (!get_chipfamily_from_chipset( info )) { - fprintf(stderr, "Unknown or non-radeon chipset -- cannot continue\n"); - fprintf(stderr, "==> Verify PCI BusID is correct in miniglx.conf\n"); - return 0; - } - - info->frontPitch = ctx->shared.virtualWidth; - info->LinearAddr = ctx->FBStart & 0xfc000000; - - - if (!RADEONScreenInit( ctx, info )) - return 0; - - - return 1; -} - - -/** - * \brief The screen is being closed, so clean up any state and free any - * resources used by the DRI. - * - * \param ctx display handle. - * - * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver - * private data. - */ -static void radeonHaltFBDev( DRIDriverContext *ctx ) -{ - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = 0; - } -} - - -extern void radeonNotifyFocus( int ); - -/** - * \brief Exported driver interface for Mini GLX. - * - * \sa DRIDriverRec. - */ -const struct DRIDriverRec __driDriver = { - radeonValidateMode, - radeonPostValidateMode, - radeonInitFBDev, - radeonHaltFBDev, - RADEONEngineShutdown, - RADEONEngineRestore, -#ifndef _EMBEDDED - 0, -#else - radeonNotifyFocus, -#endif -}; diff --git a/src/mesa/drivers/dri/savage/Makefile b/src/mesa/drivers/dri/savage/Makefile index 2e5c40802c1..53511552c6d 100644 --- a/src/mesa/drivers/dri/savage/Makefile +++ b/src/mesa/drivers/dri/savage/Makefile @@ -5,9 +5,6 @@ include $(TOP)/configs/current LIBNAME = savage_dri.so -# Doesn't exist yet. -#MINIGLX_SOURCES = server/savage_dri.c - DRIVER_SOURCES = \ savage_xmesa.c \ savagedd.c \ diff --git a/src/mesa/drivers/dri/sis/Makefile b/src/mesa/drivers/dri/sis/Makefile index ad009fc2398..6b4f938bab3 100644 --- a/src/mesa/drivers/dri/sis/Makefile +++ b/src/mesa/drivers/dri/sis/Makefile @@ -5,10 +5,6 @@ include $(TOP)/configs/current LIBNAME = sis_dri.so - -# Not yet -# MINIGLX_SOURCES = server/sis_dri.c - DRIVER_SOURCES = \ sis6326_state.c \ sis6326_clear.c \ diff --git a/src/mesa/drivers/dri/swrast/Makefile b/src/mesa/drivers/dri/swrast/Makefile index 771169c1ff9..cc59eefdb2d 100644 --- a/src/mesa/drivers/dri/swrast/Makefile +++ b/src/mesa/drivers/dri/swrast/Makefile @@ -17,7 +17,8 @@ ASM_SOURCES = SWRAST_COMMON_SOURCES = \ ../../common/driverfuncs.c \ - ../common/utils.c + ../common/utils.c \ + ../common/dri_sw.c include ../Makefile.template diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c index 03c672ecf1b..e9ca99a86f0 100644 --- a/src/mesa/drivers/dri/swrast/swrast.c +++ b/src/mesa/drivers/dri/swrast/swrast.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 George Sapountzis <[email protected]> + * Copyright 2008, 2010 George Sapountzis <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -54,17 +54,9 @@ * Screen and config-related functions */ -static void -setupLoaderExtensions(__DRIscreen *psp, - const __DRIextension **extensions) -{ - int i; - - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) - psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; - } -} +static const __DRIextension *dri_screen_extensions[] = { + NULL +}; static __DRIconfig ** swrastFillInModes(__DRIscreen *psp, @@ -143,26 +135,14 @@ swrastFillInModes(__DRIscreen *psp, return configs; } -static __DRIscreen * -driCreateNewScreen(int scrn, const __DRIextension **extensions, - const __DRIconfig ***driver_configs, void *data) +static const __DRIconfig ** +dri_init_screen(__DRIscreen * psp) { - static const __DRIextension *emptyExtensionList[] = { NULL }; - __DRIscreen *psp; __DRIconfig **configs8, **configs16, **configs24, **configs32; - (void) data; - TRACE; - psp = calloc(1, sizeof(*psp)); - if (!psp) - return NULL; - - setupLoaderExtensions(psp, extensions); - - psp->num = scrn; - psp->extensions = emptyExtensionList; + psp->extensions = dri_screen_extensions; configs8 = swrastFillInModes(psp, 8, 8, 0, 1); configs16 = swrastFillInModes(psp, 16, 16, 0, 1); @@ -171,28 +151,15 @@ driCreateNewScreen(int scrn, const __DRIextension **extensions, configs16 = driConcatConfigs(configs8, configs16); configs24 = driConcatConfigs(configs16, configs24); - *driver_configs = (const __DRIconfig **) - driConcatConfigs(configs24, configs32); - - driInitExtensions( NULL, NULL, GL_FALSE ); - - return psp; -} - -static void driDestroyScreen(__DRIscreen *psp) -{ - TRACE; + configs32 = driConcatConfigs(configs24, configs32); - if (psp) { - free(psp); - } + return (const __DRIconfig **)configs32; } -static const __DRIextension **driGetExtensions(__DRIscreen *psp) +static void +dri_destroy_screen(__DRIscreen * sPriv) { TRACE; - - return psp->extensions; } @@ -336,94 +303,116 @@ swrast_new_renderbuffer(const GLvisual *visual, GLboolean front) return xrb; } -static __DRIdrawable * -driCreateNewDrawable(__DRIscreen *screen, - const __DRIconfig *config, void *data) +static GLboolean +dri_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const __GLcontextModes * visual, GLboolean isPixmap) { - __DRIdrawable *buf; + struct dri_drawable *drawable = NULL; + GLframebuffer *fb; struct swrast_renderbuffer *frontrb, *backrb; TRACE; - buf = calloc(1, sizeof *buf); - if (!buf) - return NULL; + drawable = CALLOC_STRUCT(dri_drawable); + if (drawable == NULL) + goto drawable_fail; - buf->loaderPrivate = data; + dPriv->driverPrivate = drawable; + drawable->dPriv = dPriv; - buf->driScreenPriv = screen; + drawable->row = malloc(MAX_WIDTH * 4); + if (drawable->row == NULL) + goto drawable_fail; - buf->row = malloc(MAX_WIDTH * 4); + fb = &drawable->Base; /* basic framebuffer setup */ - _mesa_initialize_window_framebuffer(&buf->Base, &config->modes); + _mesa_initialize_window_framebuffer(fb, visual); /* add front renderbuffer */ - frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE); - _mesa_add_renderbuffer(&buf->Base, BUFFER_FRONT_LEFT, &frontrb->Base); + frontrb = swrast_new_renderbuffer(visual, GL_TRUE); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base); /* add back renderbuffer */ - if (config->modes.doubleBufferMode) { - backrb = swrast_new_renderbuffer(&config->modes, GL_FALSE); - _mesa_add_renderbuffer(&buf->Base, BUFFER_BACK_LEFT, &backrb->Base); + if (visual->doubleBufferMode) { + backrb = swrast_new_renderbuffer(visual, GL_FALSE); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base); } /* add software renderbuffers */ - _mesa_add_soft_renderbuffers(&buf->Base, + _mesa_add_soft_renderbuffers(fb, GL_FALSE, /* color */ - config->modes.haveDepthBuffer, - config->modes.haveStencilBuffer, - config->modes.haveAccumBuffer, + visual->haveDepthBuffer, + visual->haveStencilBuffer, + visual->haveAccumBuffer, GL_FALSE, /* alpha */ GL_FALSE /* aux bufs */); - return buf; + return GL_TRUE; + +drawable_fail: + + if (drawable) + free(drawable->row); + + FREE(drawable); + + return GL_FALSE; } static void -driDestroyDrawable(__DRIdrawable *buf) +dri_destroy_buffer(__DRIdrawable * dPriv) { TRACE; - if (buf) { - struct gl_framebuffer *fb = &buf->Base; + if (dPriv) { + struct dri_drawable *drawable = dri_drawable(dPriv); + GLframebuffer *fb; - free(buf->row); + free(drawable->row); + + fb = &drawable->Base; fb->DeletePending = GL_TRUE; _mesa_reference_framebuffer(&fb, NULL); } } -static void driSwapBuffers(__DRIdrawable *buf) +static void +dri_swap_buffers(__DRIdrawable * dPriv) { - GET_CURRENT_CONTEXT(ctx); + __DRIscreen *sPriv = dPriv->driScreenPriv; - struct swrast_renderbuffer *frontrb = - swrast_renderbuffer(buf->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - struct swrast_renderbuffer *backrb = - swrast_renderbuffer(buf->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); + GET_CURRENT_CONTEXT(ctx); - __DRIscreen *screen = buf->driScreenPriv; + struct dri_drawable *drawable = dri_drawable(dPriv); + GLframebuffer *fb; + struct swrast_renderbuffer *frontrb, *backrb; TRACE; + fb = &drawable->Base; + + frontrb = swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + backrb = swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + /* check for signle-buffered */ if (backrb == NULL) return; /* check if swapping currently bound buffer */ - if (ctx && ctx->DrawBuffer == &(buf->Base)) { + if (ctx && ctx->DrawBuffer == fb) { /* flush pending rendering */ _mesa_notifySwapBuffers(ctx); } - screen->swrast_loader->putImage(buf, __DRI_SWRAST_IMAGE_OP_SWAP, - 0, 0, - frontrb->Base.Width, - frontrb->Base.Height, - backrb->Base.Data, - buf->loaderPrivate); + sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + 0, 0, + frontrb->Base.Width, + frontrb->Base.Height, + backrb->Base.Data, + dPriv->loaderPrivate); } @@ -434,13 +423,13 @@ static void driSwapBuffers(__DRIdrawable *buf) static void get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h ) { - __DRIdrawable *buf = swrast_drawable(fb); - __DRIscreen *screen = buf->driScreenPriv; + __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv; + __DRIscreen *sPriv = dPriv->driScreenPriv; int x, y; - screen->swrast_loader->getDrawableInfo(buf, - &x, &y, w, h, - buf->loaderPrivate); + sPriv->swrast_loader->getDrawableInfo(dPriv, + &x, &y, w, h, + dPriv->loaderPrivate); } static void @@ -502,37 +491,40 @@ swrast_init_driver_functions(struct dd_function_table *driver) * Context-related functions. */ -static __DRIcontext * -driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, - __DRIcontext *shared, void *data) +static GLboolean +dri_create_context(const __GLcontextModes * visual, + __DRIcontext * cPriv, void *sharedContextPrivate) { - __DRIcontext *ctx; - GLcontext *mesaCtx; + struct dri_context *ctx = NULL; + struct dri_context *share = (struct dri_context *)sharedContextPrivate; + GLcontext *mesaCtx = NULL; + GLcontext *sharedCtx = NULL; struct dd_function_table functions; TRACE; - ctx = calloc(1, sizeof *ctx); - if (!ctx) - return NULL; - - ctx->loaderPrivate = data; + ctx = CALLOC_STRUCT(dri_context); + if (ctx == NULL) + goto context_fail; - ctx->driScreenPriv = screen; + cPriv->driverPrivate = ctx; + ctx->cPriv = cPriv; /* build table of device driver functions */ _mesa_init_driver_functions(&functions); swrast_init_driver_functions(&functions); - if (!_mesa_initialize_context(&ctx->Base, &config->modes, - shared ? &shared->Base : NULL, - &functions, (void *) ctx)) { - free(ctx); - return NULL; + if (share) { + sharedCtx = &share->Base; } mesaCtx = &ctx->Base; + /* basic context setup */ + if (!_mesa_initialize_context(mesaCtx, visual, sharedCtx, &functions, (void *) cPriv)) { + goto context_fail; + } + /* do bounds checking to prevent segfaults and server crashes! */ mesaCtx->Const.CheckArrayBounds = GL_TRUE; @@ -558,17 +550,28 @@ driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, _mesa_meta_init(mesaCtx); - return ctx; + driInitExtensions( mesaCtx, NULL, GL_FALSE ); + + return GL_TRUE; + +context_fail: + + FREE(ctx); + + return GL_FALSE; } static void -driDestroyContext(__DRIcontext *ctx) +dri_destroy_context(__DRIcontext * cPriv) { - GLcontext *mesaCtx; TRACE; - if (ctx) { + if (cPriv) { + struct dri_context *ctx = dri_context(cPriv); + GLcontext *mesaCtx; + mesaCtx = &ctx->Base; + _mesa_meta_free(mesaCtx); _swsetup_DestroyContext( mesaCtx ); _swrast_DestroyContext( mesaCtx ); @@ -578,26 +581,22 @@ driDestroyContext(__DRIcontext *ctx) } } -static int -driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask) -{ - TRACE; - - _mesa_copy_context(&src->Base, &dst->Base, mask); - return GL_TRUE; -} - -static int driBindContext(__DRIcontext *ctx, - __DRIdrawable *draw, - __DRIdrawable *read) +static GLboolean +dri_make_current(__DRIcontext * cPriv, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv) { GLcontext *mesaCtx; GLframebuffer *mesaDraw; GLframebuffer *mesaRead; TRACE; - if (ctx) { - if (!draw || !read) + if (cPriv) { + struct dri_context *ctx = dri_context(cPriv); + struct dri_drawable *draw = dri_drawable(driDrawPriv); + struct dri_drawable *read = dri_drawable(driReadPriv); + + if (!driDrawPriv || !driReadPriv) return GL_FALSE; mesaCtx = &ctx->Base; @@ -614,7 +613,7 @@ static int driBindContext(__DRIcontext *ctx, _glapi_check_multithread(); swrast_check_and_update_window_size(mesaCtx, mesaDraw); - if (read != draw) + if (mesaRead != mesaDraw) swrast_check_and_update_window_size(mesaCtx, mesaRead); _mesa_make_current( mesaCtx, @@ -629,35 +628,25 @@ static int driBindContext(__DRIcontext *ctx, return GL_TRUE; } -static int driUnbindContext(__DRIcontext *ctx) +static GLboolean +dri_unbind_context(__DRIcontext * cPriv) { TRACE; - (void) ctx; + (void) cPriv; return GL_TRUE; } -static const __DRIcoreExtension driCoreExtension = { - { __DRI_CORE, __DRI_CORE_VERSION }, - NULL, /* driCreateNewScreen */ - driDestroyScreen, - driGetExtensions, - driGetConfigAttrib, - driIndexConfigAttrib, - NULL, /* driCreateNewDrawable */ - driDestroyDrawable, - driSwapBuffers, - driCreateNewContext, - driCopyContext, - driDestroyContext, - driBindContext, - driUnbindContext -}; - -static const __DRIswrastExtension driSWRastExtension = { - { __DRI_SWRAST, __DRI_SWRAST_VERSION }, - driCreateNewScreen, - driCreateNewDrawable +const struct __DriverAPIRec driDriverAPI = { + .InitScreen = dri_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .SwapBuffers = dri_swap_buffers, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, }; /* This is the table of extensions that the loader will dlsym() for. */ diff --git a/src/mesa/drivers/dri/swrast/swrast_priv.h b/src/mesa/drivers/dri/swrast/swrast_priv.h index 4722007f958..77670d89a5e 100644 --- a/src/mesa/drivers/dri/swrast/swrast_priv.h +++ b/src/mesa/drivers/dri/swrast/swrast_priv.h @@ -3,6 +3,7 @@ * Version: 7.1 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright 2008, 2010 George Sapountzis <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,11 +23,6 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Authors: - * George Sapountzis <[email protected]> - */ - #ifndef _SWRAST_PRIV_H #define _SWRAST_PRIV_H @@ -34,6 +30,7 @@ #include <GL/gl.h> #include <GL/internal/dri_interface.h> #include "main/mtypes.h" +#include "dri_sw.h" /** @@ -58,33 +55,51 @@ /** * Data types */ -struct __DRIscreenRec { - int num; - - const __DRIextension **extensions; +struct dri_context +{ + /* mesa, base class, must be first */ + GLcontext Base; - const __DRIswrastLoaderExtension *swrast_loader; + /* dri */ + __DRIcontext *cPriv; }; -struct __DRIcontextRec { - GLcontext Base; - - void *loaderPrivate; +static INLINE struct dri_context * +dri_context(__DRIcontext * driContextPriv) +{ + return (struct dri_context *)driContextPriv->driverPrivate; +} - __DRIscreen *driScreenPriv; -}; +static INLINE struct dri_context * +swrast_context(GLcontext *ctx) +{ + return (struct dri_context *) ctx; +} -struct __DRIdrawableRec { +struct dri_drawable +{ + /* mesa, base class, must be first */ GLframebuffer Base; - void *loaderPrivate; - - __DRIscreen *driScreenPriv; + /* dri */ + __DRIdrawable *dPriv; /* scratch row for optimized front-buffer rendering */ char *row; }; +static INLINE struct dri_drawable * +dri_drawable(__DRIdrawable * driDrawPriv) +{ + return (struct dri_drawable *)driDrawPriv->driverPrivate; +} + +static INLINE struct dri_drawable * +swrast_drawable(GLframebuffer *fb) +{ + return (struct dri_drawable *) fb; +} + struct swrast_renderbuffer { struct gl_renderbuffer Base; @@ -94,18 +109,6 @@ struct swrast_renderbuffer { GLuint bpp; }; -static INLINE __DRIcontext * -swrast_context(GLcontext *ctx) -{ - return (__DRIcontext *) ctx; -} - -static INLINE __DRIdrawable * -swrast_drawable(GLframebuffer *fb) -{ - return (__DRIdrawable *) fb; -} - static INLINE struct swrast_renderbuffer * swrast_renderbuffer(struct gl_renderbuffer *rb) { diff --git a/src/mesa/drivers/dri/swrast/swrast_span.c b/src/mesa/drivers/dri/swrast/swrast_span.c index 5290dc82b91..c5681e34a91 100644 --- a/src/mesa/drivers/dri/swrast/swrast_span.c +++ b/src/mesa/drivers/dri/swrast/swrast_span.c @@ -3,6 +3,7 @@ * Version: 7.1 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright 2008, 2010 George Sapountzis <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,11 +23,6 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Authors: - * George Sapountzis <[email protected]> - */ - #include "swrast_priv.h" #define YFLIP(_xrb, Y) ((_xrb)->Base.Height - (Y) - 1) diff --git a/src/mesa/drivers/dri/swrast/swrast_spantemp.h b/src/mesa/drivers/dri/swrast/swrast_spantemp.h index 879a0c12e76..079726ae4ab 100644 --- a/src/mesa/drivers/dri/swrast/swrast_spantemp.h +++ b/src/mesa/drivers/dri/swrast/swrast_spantemp.h @@ -39,8 +39,8 @@ static INLINE void PUT_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; @@ -53,8 +53,8 @@ PUT_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) static INLINE void GET_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; @@ -65,8 +65,8 @@ GET_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) static INLINE void PUT_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; @@ -78,8 +78,8 @@ PUT_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) static INLINE void GET_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; diff --git a/src/mesa/drivers/dri/tdfx/Makefile b/src/mesa/drivers/dri/tdfx/Makefile index b9f25db4fe8..96bd8f8202f 100644 --- a/src/mesa/drivers/dri/tdfx/Makefile +++ b/src/mesa/drivers/dri/tdfx/Makefile @@ -5,9 +5,6 @@ include $(TOP)/configs/current LIBNAME = tdfx_dri.so -# not yet -# MINIGLX_SOURCES = server/tdfx_dri.c - DRIVER_SOURCES = \ tdfx_context.c \ tdfx_dd.c \ diff --git a/src/mesa/drivers/dri/tdfx/server/tdfx_dri.c b/src/mesa/drivers/dri/tdfx/server/tdfx_dri.c deleted file mode 100644 index 63fe875f59e..00000000000 --- a/src/mesa/drivers/dri/tdfx/server/tdfx_dri.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* Authors: - * Keith Whitwell - * Daniel Borca - */ - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include "driver.h" -#include "drm.h" -#include "imports.h" - -#include "dri_util.h" - -#include "tdfx_context.h" -#include "tdfx_dri.h" -#include "xf86drm.h" - - -#define TILE_WIDTH 128 -#define TILE_HEIGHT 32 - -#define CMDFIFO_PAGES 64 - - -static int -calcBufferStride (int xres, int tiled, int cpp) -{ - int strideInTiles; - - if (tiled) { - /* Calculate tile width stuff */ - strideInTiles = (xres+TILE_WIDTH-1)/TILE_WIDTH; - - return strideInTiles*cpp*TILE_WIDTH; - } else { - return xres*cpp; - } -} /* calcBufferStride */ - - -static int -calcBufferHeightInTiles (int yres) -{ - int heightInTiles; /* Height of buffer in tiles */ - - /* Calculate tile height stuff */ - heightInTiles = yres >> 5; - - if (yres & (TILE_HEIGHT - 1)) - heightInTiles++; - - return heightInTiles; - -} /* calcBufferHeightInTiles */ - - -static int -calcBufferSize (int xres, int yres, int tiled, int cpp) -{ - int stride, height, bufSize; - - if (tiled) { - stride = calcBufferStride(xres, tiled, cpp); - height = TILE_HEIGHT * calcBufferHeightInTiles(yres); - } else { - stride = xres*cpp; - height = yres; - } - - bufSize = stride * height; - - return bufSize; -} /* calcBufferSize */ - - -static void allocateMemory (const DRIDriverContext *ctx, TDFXDRIPtr pTDFX) -{ - int memRemaining, fifoSize, screenSizeInTiles; - int fbSize; - char *str; - int pixmapCacheLinesMin; - int cursorOffset, cursorSize; - - pTDFX->stride = calcBufferStride(pTDFX->width, !0, pTDFX->cpp); - - /* enough to do DVD */ - pixmapCacheLinesMin = ((720*480*pTDFX->cpp) + - pTDFX->stride - 1)/pTDFX->stride; - - if (pTDFX->deviceID > PCI_CHIP_VOODOO3) { - if ((pixmapCacheLinesMin + pTDFX->height) > 4095) - pixmapCacheLinesMin = 4095 - pTDFX->height; - } else { - if ((pixmapCacheLinesMin + pTDFX->height) > 2047) - pixmapCacheLinesMin = 2047 - pTDFX->height; - } - - if (pTDFX->cpp!=3) { - screenSizeInTiles=calcBufferSize(pTDFX->width, pTDFX->height, - !0, pTDFX->cpp); - } - else { - /* cpp==3 needs to bump up to 4 */ - screenSizeInTiles=calcBufferSize(pTDFX->width, pTDFX->height, - !0, 4); - } - - /* - * Layout is: - * cursor, fifo, fb, tex, bb, db - */ - - fbSize = (pTDFX->height + pixmapCacheLinesMin) * pTDFX->stride; - - memRemaining=(pTDFX->mem - 1) &~ 0xFFF; - /* Note that a page is 4096 bytes, and a */ - /* tile is 32 x 128 = 4096 bytes. So, */ - /* page and tile boundaries are the same */ - /* Place the depth offset first, forcing */ - /* it to be on an *odd* page boundary. */ - pTDFX->depthOffset = (memRemaining - screenSizeInTiles) &~ 0xFFF; - if ((pTDFX->depthOffset & (0x1 << 12)) == 0) { - pTDFX->depthOffset -= (0x1 << 12); - } - /* Now, place the back buffer, forcing it */ - /* to be on an *even* page boundary. */ - pTDFX->backOffset = (pTDFX->depthOffset - screenSizeInTiles) &~ 0xFFF; - if (pTDFX->backOffset & (0x1 << 12)) { - pTDFX->backOffset -= (0x1 << 12); - } - /* Give the cmd fifo at least */ - /* CMDFIFO_PAGES pages, but no more than */ - /* 64. NOTE: Don't go higher than 64, as */ - /* there is suspect code in Glide3 ! */ - fifoSize = ((64 <= CMDFIFO_PAGES) ? 64 : CMDFIFO_PAGES) << 12; - - /* We give 4096 bytes to the cursor */ - cursorSize = 0/*4096*/; - cursorOffset = 0; - - pTDFX->fifoOffset = cursorOffset + cursorSize; - pTDFX->fifoSize = fifoSize; - /* Now, place the front buffer, forcing */ - /* it to be on a page boundary too, just */ - /* for giggles. */ - pTDFX->fbOffset = pTDFX->fifoOffset + pTDFX->fifoSize; - pTDFX->textureOffset = pTDFX->fbOffset + fbSize; - if (pTDFX->depthOffset <= pTDFX->textureOffset || - pTDFX->backOffset <= pTDFX->textureOffset) { - /* - * pTDFX->textureSize < 0 means that the DRI is disabled. pTDFX->backOffset - * is used to calculate the maximum amount of memory available for - * 2D offscreen use. With DRI disabled, set this to the top of memory. - */ - - pTDFX->textureSize = -1; - pTDFX->backOffset = pTDFX->mem; - pTDFX->depthOffset = -1; - fprintf(stderr, - "Not enough video memory available for textures and depth buffer\n" - "\tand/or back buffer. Disabling DRI. To use DRI try lower\n" - "\tresolution modes and/or a smaller virtual screen size\n"); - } else { - pTDFX->textureSize = pTDFX->backOffset - pTDFX->textureOffset; - } -} - - -static int createScreen (DRIDriverContext *ctx, TDFXDRIPtr pTDFX) -{ - int err; - - { - int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); - int maxy = ctx->shared.fbSize / width_bytes; - - - if (maxy <= ctx->shared.virtualHeight * 3) { - fprintf(stderr, - "Static buffer allocation failed -- " - "need at least %d kB video memory (have %d kB)\n", - (ctx->shared.virtualWidth * ctx->shared.virtualHeight * - ctx->cpp * 3 + 1023) / 1024, - ctx->shared.fbSize / 1024); - return 0; - } - } - - ctx->shared.SAREASize = SAREA_MAX; - pTDFX->regsSize = ctx->MMIOSize; - - /* Note that drmOpen will try to load the kernel module, if needed. */ - ctx->drmFD = drmOpen("tdfx", NULL ); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - - if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - if (drmAddMap( ctx->drmFD, - 0, - ctx->shared.SAREASize, - DRM_SHM, - DRM_CONTAINS_LOCK, - &ctx->shared.hSAREA) < 0) - { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap( ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - } - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - /* Need to AddMap the framebuffer and mmio regions here: - */ - if (drmAddMap( ctx->drmFD, - (drm_handle_t)ctx->FBStart, - ctx->FBSize, - DRM_FRAME_BUFFER, -#ifndef _EMBEDDED - 0, -#else - DRM_READ_ONLY, -#endif - &ctx->shared.hFrameBuffer) < 0) - { - fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); - return 0; - } - - fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", - ctx->shared.hFrameBuffer); - - - if (drmAddMap(ctx->drmFD, - ctx->MMIOStart, - ctx->MMIOSize, - DRM_REGISTERS, - DRM_READ_ONLY, - &pTDFX->regs) < 0) { - fprintf(stderr, "[drm] drmAddMap mmio failed\n"); - return 0; - } - fprintf(stderr, - "[drm] register handle = 0x%08lx\n", pTDFX->regs); - - - /* Create a 'server' context so we can grab the lock for - * initialization ioctls. - */ - if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return 0; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - /* Initialize the kernel data structures */ - - /* Initialize kernel gart memory manager */ - allocateMemory(ctx, pTDFX); - - /* Initialize the SAREA private data structure */ - - - /* Quick hack to clear the front & back buffers. Could also use - * the clear ioctl to do this, but would need to setup hw state - * first. - */ - - - /* This is the struct passed to tdfx_dri.so for its initialization */ - ctx->driverClientMsg = malloc(sizeof(TDFXDRIRec)); - ctx->driverClientMsgSize = sizeof(TDFXDRIRec); - memcpy(ctx->driverClientMsg, pTDFX, ctx->driverClientMsgSize); - pTDFX = (TDFXDRIPtr)ctx->driverClientMsg; - - /* Don't release the lock now - let the VT switch handler do it. */ - - return 1; -} - - -/** - * \brief Validate the fbdev mode. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Saves some registers and returns 1. - * - * \sa tdfxValidateMode(). - */ -static int tdfxValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - - -/** - * \brief Examine mode returned by fbdev. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Restores registers that fbdev has clobbered and returns 1. - * - * \sa tdfxValidateMode(). - */ -static int tdfxPostValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - - -/** - * \brief Initialize the framebuffer device mode - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Before exiting clears the framebuffer memory accessing it directly. - */ -static int tdfxInitFBDev( DRIDriverContext *ctx ) -{ - TDFXDRIPtr pTDFX = calloc(1, sizeof(TDFXDRIRec)); - - { - int dummy = ctx->shared.virtualWidth; - - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; - } - - ctx->shared.virtualWidth = dummy; - } - - ctx->driverPrivate = (void *)pTDFX; - - pTDFX->deviceID = ctx->chipset; - pTDFX->width = ctx->shared.virtualWidth; - pTDFX->height = ctx->shared.virtualHeight; - pTDFX->cpp = ctx->cpp; - pTDFX->mem = ctx->FBSize; /* ->shared.fbSize? mem probe? */ - pTDFX->sarea_priv_offset = sizeof(drm_sarea_t); - - if (!createScreen(ctx, pTDFX)) - return 0; - - return 1; -} - - -/** - * \brief The screen is being closed, so clean up any state and free any - * resources used by the DRI. - * - * \param ctx display handle. - * - * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver - * private data. - */ -static void tdfxHaltFBDev( DRIDriverContext *ctx ) -{ - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = 0; - } -} - - -/** - * \brief Shutdown the drawing engine. - * - * \param ctx display handle - * - * Turns off the 3D engine & restores the graphics card - * to a state that fbdev understands. - */ -static int tdfxEngineShutdown( const DRIDriverContext *ctx ) -{ - fprintf(stderr, "%s: not implemented\n", __FUNCTION__); - return 1; -} - - -/** - * \brief Restore the drawing engine. - * - * \param ctx display handle - * - * Resets the graphics card and sets initial values for several registers of - * the card's drawing engine. - * - * Turns on 3dfx - */ -static int tdfxEngineRestore( const DRIDriverContext *ctx ) -{ - fprintf(stderr, "%s: not implemented\n", __FUNCTION__); - return 1; -} - - -/** - * \brief Exported driver interface for Mini GLX. - * - * \sa DRIDriverRec. - */ -struct DRIDriverRec __driDriver = { - tdfxValidateMode, - tdfxPostValidateMode, - tdfxInitFBDev, - tdfxHaltFBDev, - tdfxEngineShutdown, - tdfxEngineRestore, - 0 -}; diff --git a/src/mesa/drivers/dri/unichrome/Makefile b/src/mesa/drivers/dri/unichrome/Makefile index 344d34fce36..14cf9f30386 100644 --- a/src/mesa/drivers/dri/unichrome/Makefile +++ b/src/mesa/drivers/dri/unichrome/Makefile @@ -5,8 +5,6 @@ include $(TOP)/configs/current LIBNAME = unichrome_dri.so -MINIGLX_SOURCES = server/via_dri.c - DRIVER_SOURCES = \ via_context.c \ via_fb.c \ diff --git a/src/mesa/drivers/dri/unichrome/server/via_dri.c b/src/mesa/drivers/dri/unichrome/server/via_dri.c deleted file mode 100644 index 74034485e28..00000000000 --- a/src/mesa/drivers/dri/unichrome/server/via_dri.c +++ /dev/null @@ -1,1251 +0,0 @@ -/* - * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include "driver.h" -#include "drm.h" -#include "imports.h" - -#include "dri_util.h" - -#include "via_context.h" -#include "via_dri.h" -#include "via_driver.h" -#include "xf86drm.h" - -static void VIAEnableMMIO(DRIDriverContext * ctx); -static void VIADisableMMIO(DRIDriverContext * ctx); -static void VIADisableExtendedFIFO(DRIDriverContext *ctx); -static void VIAEnableExtendedFIFO(DRIDriverContext *ctx); -static void VIAInitialize2DEngine(DRIDriverContext *ctx); -static void VIAInitialize3DEngine(DRIDriverContext *ctx); - -static int VIADRIScreenInit(DRIDriverContext * ctx); -static void VIADRICloseScreen(DRIDriverContext * ctx); -static int VIADRIFinishScreenInit(DRIDriverContext * ctx); - -/* _SOLO : missing macros normally defined by X code */ -#define xf86DrvMsg(a, b, ...) fprintf(stderr, __VA_ARGS__) -#define MMIO_IN8(base, addr) ((*(((volatile uint8_t*)base)+(addr)))+0) -#define MMIO_OUT8(base, addr, val) ((*(((volatile uint8_t*)base)+(addr)))=((uint8_t)val)) -#define MMIO_OUT16(base, addr, val) ((*(volatile uint16_t*)(((uint8_t*)base)+(addr)))=((uint16_t)val)) - -#define VIDEO 0 -#define AGP 1 -#define AGP_PAGE_SIZE 4096 -#define AGP_PAGES 8192 -#define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES) -#define AGP_CMDBUF_PAGES 512 -#define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES) - -static char VIAKernelDriverName[] = "via"; -static char VIAClientDriverName[] = "unichrome"; - -static int VIADRIAgpInit(const DRIDriverContext *ctx, VIAPtr pVia); -static int VIADRIPciInit(DRIDriverContext * ctx, VIAPtr pVia); -static int VIADRIFBInit(DRIDriverContext * ctx, VIAPtr pVia); -static int VIADRIKernelInit(DRIDriverContext * ctx, VIAPtr pVia); -static int VIADRIMapInit(DRIDriverContext * ctx, VIAPtr pVia); - -static void VIADRIIrqInit( DRIDriverContext *ctx ) -{ - VIAPtr pVia = VIAPTR(ctx); - VIADRIPtr pVIADRI = pVia->devPrivate; - - pVIADRI->irqEnabled = drmGetInterruptFromBusID(pVia->drmFD, - ctx->pciBus, - ctx->pciDevice, - ctx->pciFunc); - - if ((drmCtlInstHandler(pVia->drmFD, pVIADRI->irqEnabled))) { - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[drm] Failure adding irq handler. " - "Falling back to irq-free operation.\n"); - pVIADRI->irqEnabled = 0; - } - - if (pVIADRI->irqEnabled) - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Irq handler installed, using IRQ %d.\n", - pVIADRI->irqEnabled); -} - -static void VIADRIIrqExit( DRIDriverContext *ctx ) { - VIAPtr pVia = VIAPTR(ctx); - VIADRIPtr pVIADRI = pVia->devPrivate; - - if (pVIADRI->irqEnabled) { - if (drmCtlUninstHandler(pVia->drmFD)) { - xf86DrvMsg(pScreen-myNum, X_INFO,"[drm] Irq handler uninstalled.\n"); - } else { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] Could not uninstall irq handler.\n"); - } - } -} - -static void VIADRIRingBufferCleanup(DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - VIADRIPtr pVIADRI = pVia->devPrivate; - drm_via_dma_init_t ringBufInit; - - if (pVIADRI->ringBufActive) { - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Cleaning up DMA ring-buffer.\n"); - ringBufInit.func = VIA_CLEANUP_DMA; - if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, - sizeof(ringBufInit))) { - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[drm] Failed to clean up DMA ring-buffer: %d\n", errno); - } - pVIADRI->ringBufActive = 0; - } -} - -static int VIADRIRingBufferInit(DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - VIADRIPtr pVIADRI = pVia->devPrivate; - drm_via_dma_init_t ringBufInit; - drmVersionPtr drmVer; - - pVIADRI->ringBufActive = 0; - - if (NULL == (drmVer = drmGetVersion(pVia->drmFD))) { - return GL_FALSE; - } - - if (((drmVer->version_major <= 1) && (drmVer->version_minor <= 3))) { - return GL_FALSE; - } - - /* - * Info frome code-snippet on DRI-DEVEL list; Erdi Chen. - */ - - switch (pVia->ChipId) { - case PCI_CHIP_VT3259: - ringBufInit.reg_pause_addr = 0x40c; - break; - default: - ringBufInit.reg_pause_addr = 0x418; - break; - } - - ringBufInit.offset = pVia->agpSize; - ringBufInit.size = AGP_CMDBUF_SIZE; - ringBufInit.func = VIA_INIT_DMA; - if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, - sizeof(ringBufInit))) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] Failed to initialize DMA ring-buffer: %d\n", errno); - return GL_FALSE; - } - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP offset 0x%lx.\n", - ringBufInit.size, ringBufInit.offset); - - pVIADRI->ringBufActive = 1; - return GL_TRUE; -} - -static int VIADRIAgpInit(const DRIDriverContext *ctx, VIAPtr pVia) -{ - unsigned long agp_phys; - drmAddress agpaddr; - VIADRIPtr pVIADRI; - pVIADRI = pVia->devPrivate; - pVia->agpSize = 0; - - if (drmAgpAcquire(pVia->drmFD) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed %d\n", errno); - return GL_FALSE; - } - - if (drmAgpEnable(pVia->drmFD, drmAgpGetMode(pVia->drmFD)&~0x0) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpEnable failed\n"); - return GL_FALSE; - } - - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] drmAgpEnabled succeeded\n"); - - if (drmAgpAlloc(pVia->drmFD, AGP_SIZE, 0, &agp_phys, &pVia->agpHandle) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] drmAgpAlloc failed\n"); - drmAgpRelease(pVia->drmFD); - return GL_FALSE; - } - - if (drmAgpBind(pVia->drmFD, pVia->agpHandle, 0) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] drmAgpBind failed\n"); - drmAgpFree(pVia->drmFD, pVia->agpHandle); - drmAgpRelease(pVia->drmFD); - - return GL_FALSE; - } - - /* - * Place the ring-buffer last in the AGP region, and restrict the - * public map not to include the buffer for security reasons. - */ - - pVia->agpSize = AGP_SIZE - AGP_CMDBUF_SIZE; - pVia->agpAddr = drmAgpBase(pVia->drmFD); - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] agpAddr = 0x%08lx\n",pVia->agpAddr); - - pVIADRI->agp.size = pVia->agpSize; - if (drmAddMap(pVia->drmFD, (drm_handle_t)0, - pVIADRI->agp.size, DRM_AGP, 0, - &pVIADRI->agp.handle) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] Failed to map public agp area\n"); - pVIADRI->agp.size = 0; - return GL_FALSE; - } - /* Map AGP from kernel to Xserver - Not really needed */ - drmMap(pVia->drmFD, pVIADRI->agp.handle,pVIADRI->agp.size, &agpaddr); - - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] agpAddr = 0x%08lx\n", pVia->agpAddr); - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] agpSize = 0x%08lx\n", pVia->agpSize); - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] agp physical addr = 0x%08lx\n", agp_phys); - - { - drm_via_agp_t agp; - agp.offset = 0; - agp.size = AGP_SIZE-AGP_CMDBUF_SIZE; - if (drmCommandWrite(pVia->drmFD, DRM_VIA_AGP_INIT, &agp, - sizeof(drm_via_agp_t)) < 0) { - drmUnmap(&agpaddr,pVia->agpSize); - drmRmMap(pVia->drmFD,pVIADRI->agp.handle); - drmAgpUnbind(pVia->drmFD, pVia->agpHandle); - drmAgpFree(pVia->drmFD, pVia->agpHandle); - drmAgpRelease(pVia->drmFD); - return GL_FALSE; - } - } - - return GL_TRUE; -} - -static int VIADRIFBInit(DRIDriverContext * ctx, VIAPtr pVia) -{ - int FBSize = pVia->FBFreeEnd-pVia->FBFreeStart; - int FBOffset = pVia->FBFreeStart; - VIADRIPtr pVIADRI = pVia->devPrivate; - pVIADRI->fbOffset = FBOffset; - pVIADRI->fbSize = pVia->videoRambytes; - - { - drm_via_fb_t fb; - fb.offset = FBOffset; - fb.size = FBSize; - - if (drmCommandWrite(pVia->drmFD, DRM_VIA_FB_INIT, &fb, - sizeof(drm_via_fb_t)) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] failed to init frame buffer area\n"); - return GL_FALSE; - } else { - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] FBFreeStart= 0x%08x FBFreeEnd= 0x%08x " - "FBSize= 0x%08x\n", - pVia->FBFreeStart, pVia->FBFreeEnd, FBSize); - return GL_TRUE; - } - } -} - -static int VIADRIPciInit(DRIDriverContext * ctx, VIAPtr pVia) -{ - return GL_TRUE; -} - -static int VIADRIScreenInit(DRIDriverContext * ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - VIADRIPtr pVIADRI; - int err; - -#if 0 - ctx->shared.SAREASize = ((sizeof(drm_sarea_t) + 0xfff) & 0x1000); -#else - if (sizeof(drm_sarea_t)+sizeof(drm_via_sarea_t) > SAREA_MAX) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Data does not fit in SAREA\n"); - return GL_FALSE; - } - ctx->shared.SAREASize = SAREA_MAX; -#endif - - ctx->drmFD = drmOpen(VIAKernelDriverName, NULL); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - pVia->drmFD = ctx->drmFD; - - err = drmSetBusid(ctx->drmFD, ctx->pciBusID); - if (err < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - err = drmAddMap(ctx->drmFD, 0, ctx->shared.SAREASize, DRM_SHM, - DRM_CONTAINS_LOCK, &ctx->shared.hSAREA); - if (err < 0) { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap(ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - } - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - /* Need to AddMap the framebuffer and mmio regions here: - */ - if (drmAddMap(ctx->drmFD, - (drm_handle_t)ctx->FBStart, - ctx->FBSize, - DRM_FRAME_BUFFER, -#ifndef _EMBEDDED - 0, -#else - DRM_READ_ONLY, -#endif - &ctx->shared.hFrameBuffer) < 0) - { - fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); - return 0; - } - - fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", - ctx->shared.hFrameBuffer); - - pVIADRI = (VIADRIPtr) CALLOC(sizeof(VIADRIRec)); - if (!pVIADRI) { - drmClose(ctx->drmFD); - return GL_FALSE; - } - pVia->devPrivate = pVIADRI; - ctx->driverClientMsg = pVIADRI; - ctx->driverClientMsgSize = sizeof(*pVIADRI); - - /* DRIScreenInit doesn't add all the common mappings. Add additional mappings here. */ - if (!VIADRIMapInit(ctx, pVia)) { - VIADRICloseScreen(ctx); - return GL_FALSE; - } - - pVIADRI->regs.size = VIA_MMIO_REGSIZE; - pVIADRI->regs.handle = pVia->registerHandle; - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] mmio Registers = 0x%08lx\n", - pVIADRI->regs.handle); - - if (drmMap(pVia->drmFD, - pVIADRI->regs.handle, - pVIADRI->regs.size, - (drmAddress *)&pVia->MapBase) != 0) - { - VIADRICloseScreen(ctx); - return GL_FALSE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] mmio mapped.\n" ); - - VIAEnableMMIO(ctx); - - /* Get video memory clock. */ - VGAOUT8(0x3D4, 0x3D); - pVia->MemClk = (VGAIN8(0x3D5) & 0xF0) >> 4; - xf86DrvMsg(0, X_INFO, "[dri] MemClk (0x%x)\n", pVia->MemClk); - - /* 3D rendering has noise if not enabled. */ - VIAEnableExtendedFIFO(ctx); - - VIAInitialize2DEngine(ctx); - - /* Must disable MMIO or 3D won't work. */ - VIADisableMMIO(ctx); - - VIAInitialize3DEngine(ctx); - - pVia->IsPCI = !VIADRIAgpInit(ctx, pVia); - - if (pVia->IsPCI) { - VIADRIPciInit(ctx, pVia); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] use pci.\n" ); - } - else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] use agp.\n" ); - - if (!(VIADRIFBInit(ctx, pVia))) { - VIADRICloseScreen(ctx); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] frame buffer initialize fail .\n" ); - return GL_FALSE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] frame buffer initialized.\n" ); - - return VIADRIFinishScreenInit(ctx); -} - -static void -VIADRICloseScreen(DRIDriverContext * ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - VIADRIPtr pVIADRI=(VIADRIPtr)pVia->devPrivate; - - VIADRIRingBufferCleanup(ctx); - - if (pVia->MapBase) { - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Unmapping MMIO registers\n"); - drmUnmap(pVia->MapBase, pVIADRI->regs.size); - } - - if (pVia->agpSize) { - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Freeing agp memory\n"); - drmAgpFree(pVia->drmFD, pVia->agpHandle); - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Releasing agp module\n"); - drmAgpRelease(pVia->drmFD); - } - -#if 0 - if (pVia->DRIIrqEnable) -#endif - VIADRIIrqExit(ctx); -} - -static int -VIADRIFinishScreenInit(DRIDriverContext * ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - VIADRIPtr pVIADRI; - int err; - - err = drmCreateContext(ctx->drmFD, &ctx->serverContext); - if (err != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return GL_FALSE; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - - if (!VIADRIKernelInit(ctx, pVia)) { - VIADRICloseScreen(ctx); - return GL_FALSE; - } - xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] kernel data initialized.\n"); - - /* set SAREA value */ - { - drm_via_sarea_t *saPriv; - - saPriv=(drm_via_sarea_t*)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - assert(saPriv); - memset(saPriv, 0, sizeof(*saPriv)); - saPriv->ctxOwner = -1; - } - pVIADRI=(VIADRIPtr)pVia->devPrivate; - pVIADRI->deviceID=pVia->Chipset; - pVIADRI->width=ctx->shared.virtualWidth; - pVIADRI->height=ctx->shared.virtualHeight; - pVIADRI->mem=ctx->shared.fbSize; - pVIADRI->bytesPerPixel= (ctx->bpp+7) / 8; - pVIADRI->sarea_priv_offset = sizeof(drm_sarea_t); - /* TODO */ - pVIADRI->scrnX=pVIADRI->width; - pVIADRI->scrnY=pVIADRI->height; - - /* Initialize IRQ */ -#if 0 - if (pVia->DRIIrqEnable) -#endif - VIADRIIrqInit(ctx); - - pVIADRI->ringBufActive = 0; - VIADRIRingBufferInit(ctx); - - return GL_TRUE; -} - -/* Initialize the kernel data structures. */ -static int VIADRIKernelInit(DRIDriverContext * ctx, VIAPtr pVia) -{ - drm_via_init_t drmInfo; - memset(&drmInfo, 0, sizeof(drm_via_init_t)); - drmInfo.sarea_priv_offset = sizeof(drm_sarea_t); - drmInfo.func = VIA_INIT_MAP; - drmInfo.fb_offset = pVia->FrameBufferBase; - drmInfo.mmio_offset = pVia->registerHandle; - if (pVia->IsPCI) - drmInfo.agpAddr = (uint32_t)NULL; - else - drmInfo.agpAddr = (uint32_t)pVia->agpAddr; - - if ((drmCommandWrite(pVia->drmFD, DRM_VIA_MAP_INIT,&drmInfo, - sizeof(drm_via_init_t))) < 0) - return GL_FALSE; - - return GL_TRUE; -} -/* Add a map for the MMIO registers */ -static int VIADRIMapInit(DRIDriverContext * ctx, VIAPtr pVia) -{ - int flags = 0; - - if (drmAddMap(pVia->drmFD, pVia->MmioBase, VIA_MMIO_REGSIZE, - DRM_REGISTERS, flags, &pVia->registerHandle) < 0) { - return GL_FALSE; - } - - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] register handle = 0x%08lx\n", pVia->registerHandle); - - return GL_TRUE; -} - -static int viaValidateMode(const DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - - return 1; -} - -static int viaPostValidateMode(const DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - - return 1; -} - -static void VIAEnableMMIO(DRIDriverContext * ctx) -{ - /*vgaHWPtr hwp = VGAHWPTR(ctx);*/ - VIAPtr pVia = VIAPTR(ctx); - unsigned char val; - -#if 0 - if (xf86IsPrimaryPci(pVia->PciInfo)) { - /* If we are primary card, we still use std vga port. If we use - * MMIO, system will hang in vgaHWSave when our card used in - * PLE and KLE (integrated Trident MVP4) - */ - vgaHWSetStdFuncs(hwp); - } - else { - vgaHWSetMmioFuncs(hwp, pVia->MapBase, 0x8000); - } -#endif - - val = VGAIN8(0x3c3); - VGAOUT8(0x3c3, val | 0x01); - val = VGAIN8(0x3cc); - VGAOUT8(0x3c2, val | 0x01); - - /* Unlock Extended IO Space */ - VGAOUT8(0x3c4, 0x10); - VGAOUT8(0x3c5, 0x01); - - /* Enable MMIO */ - if(!pVia->IsSecondary) { - VGAOUT8(0x3c4, 0x1a); - val = VGAIN8(0x3c5); -#ifdef DEBUG - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "primary val = %x\n", val); -#endif - VGAOUT8(0x3c5, val | 0x68); - } - else { - VGAOUT8(0x3c4, 0x1a); - val = VGAIN8(0x3c5); -#ifdef DEBUG - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "secondary val = %x\n", val); -#endif - VGAOUT8(0x3c5, val | 0x38); - } - - /* Unlock CRTC registers */ - VGAOUT8(0x3d4, 0x47); - VGAOUT8(0x3d5, 0x00); - - return; -} - -static void VIADisableMMIO(DRIDriverContext * ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - unsigned char val; - - VGAOUT8(0x3c4, 0x1a); - val = VGAIN8(0x3c5); - VGAOUT8(0x3c5, val & 0x97); - - return; -} - -static void VIADisableExtendedFIFO(DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - uint32_t dwGE230, dwGE298; - - /* Cause of exit XWindow will dump back register value, others chipset no - * need to set extended fifo value */ - if (pVia->Chipset == VIA_CLE266 && pVia->ChipRev < 15 && - (ctx->shared.virtualWidth > 1024 || pVia->HasSecondary)) { - /* Turn off Extend FIFO */ - /* 0x298[29] */ - dwGE298 = VIAGETREG(0x298); - VIASETREG(0x298, dwGE298 | 0x20000000); - /* 0x230[21] */ - dwGE230 = VIAGETREG(0x230); - VIASETREG(0x230, dwGE230 & ~0x00200000); - /* 0x298[29] */ - dwGE298 = VIAGETREG(0x298); - VIASETREG(0x298, dwGE298 & ~0x20000000); - } -} - -static void VIAEnableExtendedFIFO(DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - uint8_t bRegTemp; - uint32_t dwGE230, dwGE298; - - switch (pVia->Chipset) { - case VIA_CLE266: - if (pVia->ChipRev > 14) { /* For 3123Cx */ - if (pVia->HasSecondary) { /* SAMM or DuoView case */ - if (ctx->shared.virtualWidth >= 1024) - { - /* 3c5.16[0:5] */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp |= 0x1C; - VGAOUT8(0x3C5, bRegTemp); - /* 3c5.17[0:6] */ - VGAOUT8(0x3C4, 0x17); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x7F; - bRegTemp |= 0x3F; - VGAOUT8(0x3C5, bRegTemp); - pVia->EnableExtendedFIFO = GL_TRUE; - } - } - else /* Single view or Simultaneoue case */ - { - if (ctx->shared.virtualWidth > 1024) - { - /* 3c5.16[0:5] */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp |= 0x17; - VGAOUT8(0x3C5, bRegTemp); - /* 3c5.17[0:6] */ - VGAOUT8(0x3C4, 0x17); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x7F; - bRegTemp |= 0x2F; - VGAOUT8(0x3C5, bRegTemp); - pVia->EnableExtendedFIFO = GL_TRUE; - } - } - /* 3c5.18[0:5] */ - VGAOUT8(0x3C4, 0x18); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp |= 0x17; - bRegTemp |= 0x40; /* force the preq always higher than treq */ - VGAOUT8(0x3C5, bRegTemp); - } - else { /* for 3123Ax */ - if (ctx->shared.virtualWidth > 1024 || pVia->HasSecondary) { - /* Turn on Extend FIFO */ - /* 0x298[29] */ - dwGE298 = VIAGETREG(0x298); - VIASETREG(0x298, dwGE298 | 0x20000000); - /* 0x230[21] */ - dwGE230 = VIAGETREG(0x230); - VIASETREG(0x230, dwGE230 | 0x00200000); - /* 0x298[29] */ - dwGE298 = VIAGETREG(0x298); - VIASETREG(0x298, dwGE298 & ~0x20000000); - - /* 3c5.16[0:5] */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp |= 0x17; - /* bRegTemp |= 0x10; */ - VGAOUT8(0x3C5, bRegTemp); - /* 3c5.17[0:6] */ - VGAOUT8(0x3C4, 0x17); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x7F; - bRegTemp |= 0x2F; - /*bRegTemp |= 0x1F;*/ - VGAOUT8(0x3C5, bRegTemp); - /* 3c5.18[0:5] */ - VGAOUT8(0x3C4, 0x18); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp |= 0x17; - bRegTemp |= 0x40; /* force the preq always higher than treq */ - VGAOUT8(0x3C5, bRegTemp); - pVia->EnableExtendedFIFO = GL_TRUE; - } - } - break; - case VIA_KM400: - if (pVia->HasSecondary) { /* SAMM or DuoView case */ - if ((ctx->shared.virtualWidth >= 1600) && - (pVia->MemClk <= VIA_MEM_DDR200)) { - /* enable CRT extendded FIFO */ - VGAOUT8(0x3C4, 0x17); - VGAOUT8(0x3C5, 0x1C); - /* revise second display queue depth and read threshold */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp = (bRegTemp) | (0x09); - VGAOUT8(0x3C5, bRegTemp); - } - else { - /* enable CRT extendded FIFO */ - VGAOUT8(0x3C4, 0x17); - VGAOUT8(0x3C5,0x3F); - /* revise second display queue depth and read threshold */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp = (bRegTemp) | (0x1C); - VGAOUT8(0x3C5, bRegTemp); - } - /* 3c5.18[0:5] */ - VGAOUT8(0x3C4, 0x18); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp |= 0x17; - bRegTemp |= 0x40; /* force the preq always higher than treq */ - VGAOUT8(0x3C5, bRegTemp); - pVia->EnableExtendedFIFO = GL_TRUE; - } - else { - if ( (ctx->shared.virtualWidth > 1024) && (ctx->shared.virtualWidth <= 1280) ) - { - /* enable CRT extendded FIFO */ - VGAOUT8(0x3C4, 0x17); - VGAOUT8(0x3C5, 0x3F); - /* revise second display queue depth and read threshold */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp = (bRegTemp) | (0x17); - VGAOUT8(0x3C5, bRegTemp); - pVia->EnableExtendedFIFO = GL_TRUE; - } - else if ((ctx->shared.virtualWidth > 1280)) - { - /* enable CRT extendded FIFO */ - VGAOUT8(0x3C4, 0x17); - VGAOUT8(0x3C5, 0x3F); - /* revise second display queue depth and read threshold */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp = (bRegTemp) | (0x1C); - VGAOUT8(0x3C5, bRegTemp); - pVia->EnableExtendedFIFO = GL_TRUE; - } - else - { - /* enable CRT extendded FIFO */ - VGAOUT8(0x3C4, 0x17); - VGAOUT8(0x3C5, 0x3F); - /* revise second display queue depth and read threshold */ - VGAOUT8(0x3C4, 0x16); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp = (bRegTemp) | (0x10); - VGAOUT8(0x3C5, bRegTemp); - } - /* 3c5.18[0:5] */ - VGAOUT8(0x3C4, 0x18); - bRegTemp = VGAIN8(0x3C5); - bRegTemp &= ~0x3F; - bRegTemp |= 0x17; - bRegTemp |= 0x40; /* force the preq always higher than treq */ - VGAOUT8(0x3C5, bRegTemp); - } - break; - case VIA_K8M800: - /*=* R1 Display FIFO depth (384 /8 -1 -> 0xbf) SR17[7:0] (8bits) *=*/ - VGAOUT8(0x3c4, 0x17); - VGAOUT8(0x3c5, 0xbf); - - /*=* R2 Display fetch datum threshold value (328/4 -> 0x52) - SR16[5:0], SR16[7] (7bits) *=*/ - VGAOUT8(0x3c4, 0x16); - bRegTemp = VGAIN8(0x3c5) & ~0xBF; - bRegTemp |= (0x52 & 0x3F); - bRegTemp |= ((0x52 & 0x40) << 1); - VGAOUT8(0x3c5, bRegTemp); - - /*=* R3 Switch to the highest agent threshold value (74 -> 0x4a) - SR18[5:0], SR18[7] (7bits) *=*/ - VGAOUT8(0x3c4, 0x18); - bRegTemp = VGAIN8(0x3c5) & ~0xBF; - bRegTemp |= (0x4a & 0x3F); - bRegTemp |= ((0x4a & 0x40) << 1); - VGAOUT8(0x3c5, bRegTemp); -#if 0 - /*=* R4 Fetch Number for a scan line (unit: 8 bytes) - SR1C[7:0], SR1D[1:0] (10bits) *=*/ - wRegTemp = (pBIOSInfo->offsetWidthByQWord >> 1) + 4; - VGAOUT8(0x3c4, 0x1c); - VGAOUT8(0x3c5, (uint8_t)(wRegTemp & 0xFF)); - VGAOUT8(0x3c4, 0x1d); - bRegTemp = VGAIN8(0x3c5) & ~0x03; - VGAOUT8(0x3c5, bRegTemp | ((wRegTemp & 0x300) >> 8)); -#endif - if (ctx->shared.virtualWidth >= 1400 && ctx->bpp == 32) - { - /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/ - VGAOUT8(0x3c4, 0x22); - bRegTemp = VGAIN8(0x3c5) & ~0x1F; - VGAOUT8(0x3c5, bRegTemp | 0x10); - } - else - { - /*=* Max. length for a request SR22[4:0] - (128/4 -> over flow 0x0) *=*/ - VGAOUT8(0x3c4, 0x22); - bRegTemp = VGAIN8(0x3c5) & ~0x1F; - VGAOUT8(0x3c5, bRegTemp); - } - break; - case VIA_PM800: - /*=* R1 Display FIFO depth (96-1 -> 0x5f) SR17[7:0] (8bits) *=*/ - VGAOUT8(0x3c4, 0x17); - VGAOUT8(0x3c5, 0x5f); - - /*=* R2 Display fetch datum threshold value (32 -> 0x20) - SR16[5:0], SR16[7] (7bits) *=*/ - VGAOUT8(0x3c4, 0x16); - bRegTemp = VGAIN8(0x3c5) & ~0xBF; - bRegTemp |= (0x20 & 0x3F); - bRegTemp |= ((0x20 & 0x40) << 1); - VGAOUT8(0x3c5, bRegTemp); - - /*=* R3 Switch to the highest agent threshold value (16 -> 0x10) - SR18[5:0], SR18[7] (7bits) *=*/ - VGAOUT8(0x3c4, 0x18); - bRegTemp = VGAIN8(0x3c5) & ~0xBF; - bRegTemp |= (0x10 & 0x3F); - bRegTemp |= ((0x10 & 0x40) << 1); - VGAOUT8(0x3c5, bRegTemp); -#if 0 - /*=* R4 Fetch Number for a scan line (unit: 8 bytes) - SR1C[7:0], SR1D[1:0] (10bits) *=*/ - wRegTemp = (pBIOSInfo->offsetWidthByQWord >> 1) + 4; - VGAOUT8(0x3c4, 0x1c); - VGAOUT8(0x3c5, (uint8_t)(wRegTemp & 0xFF)); - VGAOUT8(0x3c4, 0x1d); - bRegTemp = VGAIN8(0x3c5) & ~0x03; - VGAOUT8(0x3c5, bRegTemp | ((wRegTemp & 0x300) >> 8)); -#endif - if (ctx->shared.virtualWidth >= 1400 && ctx->bpp == 32) - { - /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/ - VGAOUT8(0x3c4, 0x22); - bRegTemp = VGAIN8(0x3c5) & ~0x1F; - VGAOUT8(0x3c5, bRegTemp | 0x10); - } - else - { - /*=* Max. length for a request SR22[4:0] (0x1F) *=*/ - VGAOUT8(0x3c4, 0x22); - bRegTemp = VGAIN8(0x3c5) & ~0x1F; - VGAOUT8(0x3c5, bRegTemp | 0x1F); - } - break; - default: - break; - } -} - -static void VIAInitialize2DEngine(DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - uint32_t dwVQStartAddr, dwVQEndAddr; - uint32_t dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; - uint32_t dwGEMode; - - /* init 2D engine regs to reset 2D engine */ - VIASETREG(0x04, 0x0); - VIASETREG(0x08, 0x0); - VIASETREG(0x0c, 0x0); - VIASETREG(0x10, 0x0); - VIASETREG(0x14, 0x0); - VIASETREG(0x18, 0x0); - VIASETREG(0x1c, 0x0); - VIASETREG(0x20, 0x0); - VIASETREG(0x24, 0x0); - VIASETREG(0x28, 0x0); - VIASETREG(0x2c, 0x0); - VIASETREG(0x30, 0x0); - VIASETREG(0x34, 0x0); - VIASETREG(0x38, 0x0); - VIASETREG(0x3c, 0x0); - VIASETREG(0x40, 0x0); - - VIADisableMMIO(ctx); - - /* Init AGP and VQ regs */ - VIASETREG(0x43c, 0x00100000); - VIASETREG(0x440, 0x00000000); - VIASETREG(0x440, 0x00333004); - VIASETREG(0x440, 0x60000000); - VIASETREG(0x440, 0x61000000); - VIASETREG(0x440, 0x62000000); - VIASETREG(0x440, 0x63000000); - VIASETREG(0x440, 0x64000000); - VIASETREG(0x440, 0x7D000000); - - VIASETREG(0x43c, 0xfe020000); - VIASETREG(0x440, 0x00000000); - - if (pVia->VQStart != 0) { - /* Enable VQ */ - dwVQStartAddr = pVia->VQStart; - dwVQEndAddr = pVia->VQEnd; - dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF); - dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF); - dwVQStartEndH = 0x52000000 | ((dwVQStartAddr & 0xFF000000) >> 24) | - ((dwVQEndAddr & 0xFF000000) >> 16); - dwVQLen = 0x53000000 | (VIA_VQ_SIZE >> 3); - - VIASETREG(0x43c, 0x00fe0000); - VIASETREG(0x440, 0x080003fe); - VIASETREG(0x440, 0x0a00027c); - VIASETREG(0x440, 0x0b000260); - VIASETREG(0x440, 0x0c000274); - VIASETREG(0x440, 0x0d000264); - VIASETREG(0x440, 0x0e000000); - VIASETREG(0x440, 0x0f000020); - VIASETREG(0x440, 0x1000027e); - VIASETREG(0x440, 0x110002fe); - VIASETREG(0x440, 0x200f0060); - - VIASETREG(0x440, 0x00000006); - VIASETREG(0x440, 0x40008c0f); - VIASETREG(0x440, 0x44000000); - VIASETREG(0x440, 0x45080c04); - VIASETREG(0x440, 0x46800408); - - VIASETREG(0x440, dwVQStartEndH); - VIASETREG(0x440, dwVQStartL); - VIASETREG(0x440, dwVQEndL); - VIASETREG(0x440, dwVQLen); - } - else { - /* Diable VQ */ - VIASETREG(0x43c, 0x00fe0000); - VIASETREG(0x440, 0x00000004); - VIASETREG(0x440, 0x40008c0f); - VIASETREG(0x440, 0x44000000); - VIASETREG(0x440, 0x45080c04); - VIASETREG(0x440, 0x46800408); - } - - dwGEMode = 0; - - switch (ctx->bpp) { - case 16: - dwGEMode |= VIA_GEM_16bpp; - break; - case 32: - dwGEMode |= VIA_GEM_32bpp; - break; - default: - dwGEMode |= VIA_GEM_8bpp; - break; - } - -#if 0 - switch (ctx->shared.virtualWidth) { - case 800: - dwGEMode |= VIA_GEM_800; - break; - case 1024: - dwGEMode |= VIA_GEM_1024; - break; - case 1280: - dwGEMode |= VIA_GEM_1280; - break; - case 1600: - dwGEMode |= VIA_GEM_1600; - break; - case 2048: - dwGEMode |= VIA_GEM_2048; - break; - default: - dwGEMode |= VIA_GEM_640; - break; - } -#endif - - VIAEnableMMIO(ctx); - - /* Set BPP and Pitch */ - VIASETREG(VIA_REG_GEMODE, dwGEMode); - - /* Set Src and Dst base address and pitch, pitch is qword */ - VIASETREG(VIA_REG_SRCBASE, 0x0); - VIASETREG(VIA_REG_DSTBASE, 0x0); - VIASETREG(VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((ctx->shared.virtualWidth * ctx->bpp >> 3) >> 3) | - (((ctx->shared.virtualWidth * ctx->bpp >> 3) >> 3) << 16)); -} - -static int b3DRegsInitialized = 0; - -static void VIAInitialize3DEngine(DRIDriverContext *ctx) -{ - VIAPtr pVia = VIAPTR(ctx); - int i; - - if (!b3DRegsInitialized) - { - - VIASETREG(0x43C, 0x00010000); - - for (i = 0; i <= 0x7D; i++) - { - VIASETREG(0x440, (uint32_t) i << 24); - } - - VIASETREG(0x43C, 0x00020000); - - for (i = 0; i <= 0x94; i++) - { - VIASETREG(0x440, (uint32_t) i << 24); - } - - VIASETREG(0x440, 0x82400000); - - VIASETREG(0x43C, 0x01020000); - - - for (i = 0; i <= 0x94; i++) - { - VIASETREG(0x440, (uint32_t) i << 24); - } - - VIASETREG(0x440, 0x82400000); - VIASETREG(0x43C, 0xfe020000); - - for (i = 0; i <= 0x03; i++) - { - VIASETREG(0x440, (uint32_t) i << 24); - } - - VIASETREG(0x43C, 0x00030000); - - for (i = 0; i <= 0xff; i++) - { - VIASETREG(0x440, 0); - } - VIASETREG(0x43C, 0x00100000); - VIASETREG(0x440, 0x00333004); - VIASETREG(0x440, 0x10000002); - VIASETREG(0x440, 0x60000000); - VIASETREG(0x440, 0x61000000); - VIASETREG(0x440, 0x62000000); - VIASETREG(0x440, 0x63000000); - VIASETREG(0x440, 0x64000000); - - VIASETREG(0x43C, 0x00fe0000); - - if (pVia->ChipRev >= 3 ) - VIASETREG(0x440,0x40008c0f); - else - VIASETREG(0x440,0x4000800f); - - VIASETREG(0x440,0x44000000); - VIASETREG(0x440,0x45080C04); - VIASETREG(0x440,0x46800408); - VIASETREG(0x440,0x50000000); - VIASETREG(0x440,0x51000000); - VIASETREG(0x440,0x52000000); - VIASETREG(0x440,0x53000000); - - b3DRegsInitialized = 1; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "3D Engine has been initialized.\n"); - } - - VIASETREG(0x43C,0x00fe0000); - VIASETREG(0x440,0x08000001); - VIASETREG(0x440,0x0A000183); - VIASETREG(0x440,0x0B00019F); - VIASETREG(0x440,0x0C00018B); - VIASETREG(0x440,0x0D00019B); - VIASETREG(0x440,0x0E000000); - VIASETREG(0x440,0x0F000000); - VIASETREG(0x440,0x10000000); - VIASETREG(0x440,0x11000000); - VIASETREG(0x440,0x20000000); -} - -static int -WaitIdleCLE266(VIAPtr pVia) -{ - int loop = 0; - - /*mem_barrier();*/ - - while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP)) - ; - - while ((VIAGETREG(VIA_REG_STATUS) & - (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && - (loop++ < MAXLOOP)) - ; - - return loop >= MAXLOOP; -} - -static int viaInitFBDev(DRIDriverContext *ctx) -{ - VIAPtr pVia = CALLOC(sizeof(*pVia)); - - ctx->driverPrivate = (void *)pVia; - - switch (ctx->chipset) { - case PCI_CHIP_CLE3122: - case PCI_CHIP_CLE3022: - pVia->Chipset = VIA_CLE266; - break; - case PCI_CHIP_VT7205: - case PCI_CHIP_VT3205: - pVia->Chipset = VIA_KM400; - break; - case PCI_CHIP_VT3204: - case PCI_CHIP_VT3344: - pVia->Chipset = VIA_K8M800; - break; - case PCI_CHIP_VT3259: - pVia->Chipset = VIA_PM800; - break; - default: - xf86DrvMsg(0, X_ERROR, "VIA: Unknown device ID (0x%x)\n", ctx->chipset); - } - - /* _SOLO TODO XXX need to read ChipRev too */ - pVia->ChipRev = 0; - - pVia->videoRambytes = ctx->shared.fbSize; - pVia->MmioBase = ctx->MMIOStart; - pVia->FrameBufferBase = ctx->FBStart & 0xfc000000; - - pVia->FBFreeStart = ctx->shared.virtualWidth * ctx->cpp * - ctx->shared.virtualHeight; - -#if 1 - /* Alloc a second framebuffer for the second head */ - pVia->FBFreeStart += ctx->shared.virtualWidth * ctx->cpp * - ctx->shared.virtualHeight; -#endif - - pVia->VQStart = pVia->FBFreeStart; - pVia->VQEnd = pVia->FBFreeStart + VIA_VQ_SIZE - 1; - - pVia->FBFreeStart += VIA_VQ_SIZE; - - pVia->FBFreeEnd = pVia->videoRambytes; - - if (!VIADRIScreenInit(ctx)) - return 0; - - return 1; -} - -static void viaHaltFBDev(DRIDriverContext *ctx) -{ - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = 0; - } -} - -static int viaEngineShutdown(const DRIDriverContext *ctx) -{ - return 1; -} - -static int viaEngineRestore(const DRIDriverContext *ctx) -{ - return 1; -} - -const struct DRIDriverRec __driDriver = -{ - viaValidateMode, - viaPostValidateMode, - viaInitFBDev, - viaHaltFBDev, - viaEngineShutdown, - viaEngineRestore, - 0, -}; - diff --git a/src/mesa/es/state_tracker/st_cb_drawtex.c b/src/mesa/es/state_tracker/st_cb_drawtex.c index 0a5cba9d927..f75f4861a2f 100644 --- a/src/mesa/es/state_tracker/st_cb_drawtex.c +++ b/src/mesa/es/state_tracker/st_cb_drawtex.c @@ -120,8 +120,11 @@ st_DrawTex(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, GLboolean emitColor; uint semantic_names[2 + MAX_TEXTURE_UNITS]; uint semantic_indexes[2 + MAX_TEXTURE_UNITS]; + struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS]; GLbitfield inputs = VERT_BIT_POS; + st_validate_state(st); + /* determine if we need vertex color */ if (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL0) emitColor = GL_TRUE; @@ -232,6 +235,7 @@ st_DrawTex(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, cso_save_viewport(cso); cso_save_vertex_shader(cso); + cso_save_vertex_elements(cso); { void *vs = lookup_shader(pipe, numAttribs, @@ -239,6 +243,14 @@ st_DrawTex(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, cso_set_vertex_shader_handle(cso, vs); } + for (i = 0; i < numAttribs; i++) { + velements[i].src_offset = i * 4 * sizeof(float); + velements[i].instance_divisor = 0; + velements[i].vertex_buffer_index = 0; + velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + cso_set_vertex_elements(cso, numAttribs, velements); + /* viewport state: viewport matching window dims */ { const struct gl_framebuffer *fb = st->ctx->DrawBuffer; @@ -270,6 +282,7 @@ st_DrawTex(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, /* restore state */ cso_restore_viewport(cso); cso_restore_vertex_shader(cso); + cso_restore_vertex_elements(cso); } diff --git a/src/mesa/glapi/glapi.c b/src/mesa/glapi/glapi.c index 13de594aafb..ce85cf6a87b 100644 --- a/src/mesa/glapi/glapi.c +++ b/src/mesa/glapi/glapi.c @@ -59,7 +59,7 @@ #endif #include "glapi/glapi.h" -#include "glapi/glapitable.h" +#include "glapi/glapi_priv.h" extern _glapi_proc __glapi_noop_table[]; @@ -291,45 +291,3 @@ _glapi_get_dispatch(void) return _glapi_Dispatch; #endif } - - - - -/* - * The dispatch table size (number of entries) is the size of the - * _glapi_table struct plus the number of dynamic entries we can add. - * The extra slots can be filled in by DRI drivers that register new extension - * functions. - */ -#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS) - - -/** - * Return size of dispatch table struct as number of functions (or - * slots). - */ -PUBLIC GLuint -_glapi_get_dispatch_table_size(void) -{ - return DISPATCH_TABLE_SIZE; -} - - -/** - * Make sure there are no NULL pointers in the given dispatch table. - * Intended for debugging purposes. - */ -void -_glapi_check_table_not_null(const struct _glapi_table *table) -{ -#if 0 /* enable this for extra DEBUG */ - const GLuint entries = _glapi_get_dispatch_table_size(); - const void **tab = (const void **) table; - GLuint i; - for (i = 1; i < entries; i++) { - assert(tab[i]); - } -#else - (void) table; -#endif -} diff --git a/src/mesa/glapi/glapi.h b/src/mesa/glapi/glapi.h index 1ca2e4beff1..7dcf2e8910b 100644 --- a/src/mesa/glapi/glapi.h +++ b/src/mesa/glapi/glapi.h @@ -165,29 +165,8 @@ extern _glapi_proc _glapi_get_proc_address(const char *funcName); -/** - * GL API local functions and defines - */ - -extern void -init_glapi_relocs_once(void); - -extern void -_glapi_check_table_not_null(const struct _glapi_table *table); - - -extern void -_glapi_check_table(const struct _glapi_table *table); - - extern const char * _glapi_get_proc_name(unsigned int offset); -/* - * Number of extension functions which we can dynamically add at runtime. - */ -#define MAX_EXTENSION_FUNCS 300 - - #endif diff --git a/src/mesa/glapi/glapi_entrypoint.c b/src/mesa/glapi/glapi_entrypoint.c new file mode 100644 index 00000000000..239780e7539 --- /dev/null +++ b/src/mesa/glapi/glapi_entrypoint.c @@ -0,0 +1,352 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file glapi_entrypoint.c + * + * Arch-specific code for manipulating GL API entrypoints (dispatch stubs). + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#include "glapi/mesa.h" +#else +#include "main/glheader.h" +#include "main/compiler.h" +#endif + +#include "glapi/glapi.h" +#include "glapi/glapi_priv.h" + + +#ifdef USE_X86_ASM + +#if defined( GLX_USE_TLS ) +extern GLubyte gl_dispatch_functions_start[]; +extern GLubyte gl_dispatch_functions_end[]; +#else +extern const GLubyte gl_dispatch_functions_start[]; +#endif + +#endif /* USE_X86_ASM */ + + +#if defined(DISPATCH_FUNCTION_SIZE) + +_glapi_proc +get_entrypoint_address(unsigned int functionOffset) +{ + return (_glapi_proc) (gl_dispatch_functions_start + + (DISPATCH_FUNCTION_SIZE * functionOffset)); +} + +#endif + + +#if defined(USE_X86_ASM) + +/** + * Perform platform-specific GL API entry-point fixups. + */ +static void +init_glapi_relocs( void ) +{ +#if defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT) + extern unsigned long _x86_get_dispatch(void); + char run_time_patch[] = { + 0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */ + }; + GLuint *offset = (GLuint *) &run_time_patch[2]; /* 32-bits for x86/32 */ + const GLubyte * const get_disp = (const GLubyte *) run_time_patch; + GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start; + + *offset = _x86_get_dispatch(); + while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) { + (void) memcpy( curr_func, get_disp, sizeof(run_time_patch)); + curr_func += DISPATCH_FUNCTION_SIZE; + } +#endif +} + + +/** + * Generate a dispatch function (entrypoint) which jumps through + * the given slot number (offset) in the current dispatch table. + * We need assembly language in order to accomplish this. + */ +_glapi_proc +generate_entrypoint(unsigned int functionOffset) +{ + /* 32 is chosen as something of a magic offset. For x86, the dispatch + * at offset 32 is the first one where the offset in the + * "jmp OFFSET*4(%eax)" can't be encoded in a single byte. + */ + const GLubyte * const template_func = gl_dispatch_functions_start + + (DISPATCH_FUNCTION_SIZE * 32); + GLubyte * const code = (GLubyte *) _glapi_exec_malloc(DISPATCH_FUNCTION_SIZE); + + + if ( code != NULL ) { + (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE); + fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset ); + } + + return (_glapi_proc) code; +} + + +/** + * This function inserts a new dispatch offset into the assembly language + * stub that was generated with the preceeding function. + */ +void +fill_in_entrypoint_offset(_glapi_proc entrypoint, unsigned int offset) +{ + GLubyte * const code = (GLubyte *) entrypoint; + +#if defined(GLX_USE_TLS) + *((unsigned int *)(code + 8)) = 4 * offset; +#elif defined(THREADS) + *((unsigned int *)(code + 11)) = 4 * offset; + *((unsigned int *)(code + 22)) = 4 * offset; +#else + *((unsigned int *)(code + 7)) = 4 * offset; +#endif +} + + +#elif defined(USE_SPARC_ASM) + +extern void __glapi_sparc_icache_flush(unsigned int *); + +static void +init_glapi_relocs( void ) +{ +#if defined(PTHREADS) || defined(GLX_USE_TLS) + static const unsigned int template[] = { +#ifdef GLX_USE_TLS + 0x05000000, /* sethi %hi(_glapi_tls_Dispatch), %g2 */ + 0x8730e00a, /* srl %g3, 10, %g3 */ + 0x8410a000, /* or %g2, %lo(_glapi_tls_Dispatch), %g2 */ +#ifdef __arch64__ + 0xc259c002, /* ldx [%g7 + %g2], %g1 */ + 0xc2584003, /* ldx [%g1 + %g3], %g1 */ +#else + 0xc201c002, /* ld [%g7 + %g2], %g1 */ + 0xc2004003, /* ld [%g1 + %g3], %g1 */ +#endif + 0x81c04000, /* jmp %g1 */ + 0x01000000, /* nop */ +#else +#ifdef __arch64__ + 0x03000000, /* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */ + 0x05000000, /* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */ + 0x82106000, /* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */ + 0x8730e00a, /* 64-bit 0x0c --> srl %g3, 10, %g3 */ + 0x83287020, /* 64-bit 0x10 --> sllx %g1, 32, %g1 */ + 0x82004002, /* 64-bit 0x14 --> add %g1, %g2, %g1 */ + 0xc2586000, /* 64-bit 0x18 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */ +#else + 0x03000000, /* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */ + 0x8730e00a, /* 32-bit 0x04 --> srl %g3, 10, %g3 */ + 0xc2006000, /* 32-bit 0x08 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */ +#endif + 0x80a06000, /* --> cmp %g1, 0 */ + 0x02800005, /* --> be +4*5 */ + 0x01000000, /* --> nop */ +#ifdef __arch64__ + 0xc2584003, /* 64-bit --> ldx [%g1 + %g3], %g1 */ +#else + 0xc2004003, /* 32-bit --> ld [%g1 + %g3], %g1 */ +#endif + 0x81c04000, /* --> jmp %g1 */ + 0x01000000, /* --> nop */ +#ifdef __arch64__ + 0x9de3bf80, /* 64-bit --> save %sp, -128, %sp */ +#else + 0x9de3bfc0, /* 32-bit --> save %sp, -64, %sp */ +#endif + 0xa0100003, /* --> mov %g3, %l0 */ + 0x40000000, /* --> call _glapi_get_dispatch */ + 0x01000000, /* --> nop */ + 0x82100008, /* --> mov %o0, %g1 */ + 0x86100010, /* --> mov %l0, %g3 */ + 0x10bffff7, /* --> ba -4*9 */ + 0x81e80000, /* --> restore */ +#endif + }; +#ifdef GLX_USE_TLS + extern unsigned int __glapi_sparc_tls_stub; + extern unsigned long __glapi_sparc_get_dispatch(void); + unsigned int *code = &__glapi_sparc_tls_stub; + unsigned long dispatch = __glapi_sparc_get_dispatch(); +#else + extern unsigned int __glapi_sparc_pthread_stub; + unsigned int *code = &__glapi_sparc_pthread_stub; + unsigned long dispatch = (unsigned long) &_glapi_Dispatch; + unsigned long call_dest = (unsigned long ) &_glapi_get_dispatch; + int idx; +#endif + +#ifdef GLX_USE_TLS + code[0] = template[0] | (dispatch >> 10); + code[1] = template[1]; + __glapi_sparc_icache_flush(&code[0]); + code[2] = template[2] | (dispatch & 0x3ff); + code[3] = template[3]; + __glapi_sparc_icache_flush(&code[2]); + code[4] = template[4]; + code[5] = template[5]; + __glapi_sparc_icache_flush(&code[4]); + code[6] = template[6]; + __glapi_sparc_icache_flush(&code[6]); +#else +#if defined(__arch64__) + code[0] = template[0] | (dispatch >> (32 + 10)); + code[1] = template[1] | ((dispatch & 0xffffffff) >> 10); + __glapi_sparc_icache_flush(&code[0]); + code[2] = template[2] | ((dispatch >> 32) & 0x3ff); + code[3] = template[3]; + __glapi_sparc_icache_flush(&code[2]); + code[4] = template[4]; + code[5] = template[5]; + __glapi_sparc_icache_flush(&code[4]); + code[6] = template[6] | (dispatch & 0x3ff); + idx = 7; +#else + code[0] = template[0] | (dispatch >> 10); + code[1] = template[1]; + __glapi_sparc_icache_flush(&code[0]); + code[2] = template[2] | (dispatch & 0x3ff); + idx = 3; +#endif + code[idx + 0] = template[idx + 0]; + __glapi_sparc_icache_flush(&code[idx - 1]); + code[idx + 1] = template[idx + 1]; + code[idx + 2] = template[idx + 2]; + __glapi_sparc_icache_flush(&code[idx + 1]); + code[idx + 3] = template[idx + 3]; + code[idx + 4] = template[idx + 4]; + __glapi_sparc_icache_flush(&code[idx + 3]); + code[idx + 5] = template[idx + 5]; + code[idx + 6] = template[idx + 6]; + __glapi_sparc_icache_flush(&code[idx + 5]); + code[idx + 7] = template[idx + 7]; + code[idx + 8] = template[idx + 8] | + (((call_dest - ((unsigned long) &code[idx + 8])) + >> 2) & 0x3fffffff); + __glapi_sparc_icache_flush(&code[idx + 7]); + code[idx + 9] = template[idx + 9]; + code[idx + 10] = template[idx + 10]; + __glapi_sparc_icache_flush(&code[idx + 9]); + code[idx + 11] = template[idx + 11]; + code[idx + 12] = template[idx + 12]; + __glapi_sparc_icache_flush(&code[idx + 11]); + code[idx + 13] = template[idx + 13]; + __glapi_sparc_icache_flush(&code[idx + 13]); +#endif +#endif +} + + +_glapi_proc +generate_entrypoint(GLuint functionOffset) +{ +#if defined(PTHREADS) || defined(GLX_USE_TLS) + static const unsigned int template[] = { + 0x07000000, /* sethi %hi(0), %g3 */ + 0x8210000f, /* mov %o7, %g1 */ + 0x40000000, /* call */ + 0x9e100001, /* mov %g1, %o7 */ + }; +#ifdef GLX_USE_TLS + extern unsigned int __glapi_sparc_tls_stub; + unsigned long call_dest = (unsigned long ) &__glapi_sparc_tls_stub; +#else + extern unsigned int __glapi_sparc_pthread_stub; + unsigned long call_dest = (unsigned long ) &__glapi_sparc_pthread_stub; +#endif + unsigned int *code = (unsigned int *) _glapi_exec_malloc(sizeof(template)); + if (code) { + code[0] = template[0] | (functionOffset & 0x3fffff); + code[1] = template[1]; + __glapi_sparc_icache_flush(&code[0]); + code[2] = template[2] | + (((call_dest - ((unsigned long) &code[2])) + >> 2) & 0x3fffffff); + code[3] = template[3]; + __glapi_sparc_icache_flush(&code[2]); + } + return (_glapi_proc) code; +#endif +} + + +void +fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) +{ + unsigned int *code = (unsigned int *) entrypoint; + + code[0] &= ~0x3fffff; + code[0] |= (offset * sizeof(void *)) & 0x3fffff; + __glapi_sparc_icache_flush(&code[0]); +} + + +#else /* USE_*_ASM */ + +static void +init_glapi_relocs( void ) +{ +} + + +_glapi_proc +generate_entrypoint(GLuint functionOffset) +{ + (void) functionOffset; + return NULL; +} + + +void +fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) +{ + /* an unimplemented architecture */ + (void) entrypoint; + (void) offset; +} + +#endif /* USE_*_ASM */ + + +void +init_glapi_relocs_once( void ) +{ +#if defined(PTHREADS) || defined(GLX_USE_TLS) + static pthread_once_t once_control = PTHREAD_ONCE_INIT; + pthread_once( & once_control, init_glapi_relocs ); +#endif +} diff --git a/src/mesa/glapi/glapi_execmem.c b/src/mesa/glapi/glapi_execmem.c new file mode 100644 index 00000000000..57f00be8dcc --- /dev/null +++ b/src/mesa/glapi/glapi_execmem.c @@ -0,0 +1,128 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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. + */ + + +/** + * \file glapi_execmem.c + * + * Function for allocating executable memory for dispatch stubs. + * + * Copied from main/execmem.c and simplified for dispatch stubs. + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#include "glapi/mesa.h" +#else +#include "main/compiler.h" +#endif + +#include "glapi/glthread.h" +#include "glapi/glapi_priv.h" + + +#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun) + +#include <unistd.h> +#include <sys/mman.h> + +#ifdef MESA_SELINUX +#include <selinux/selinux.h> +#endif + + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + + +#define EXEC_MAP_SIZE (4*1024) + +_glthread_DECLARE_STATIC_MUTEX(exec_mutex); + +static unsigned int head = 0; + +static unsigned char *exec_mem = NULL; + + +/* + * Dispatch stubs are of fixed size and never freed. Thus, we do not need to + * overlay a heap, we just mmap a page and manage through an index. + */ + +static int +init_map(void) +{ +#ifdef MESA_SELINUX + if (is_selinux_enabled()) { + if (!security_get_boolean_active("allow_execmem") || + !security_get_boolean_pending("allow_execmem")) + return 0; + } +#endif + + if (!exec_mem) + exec_mem = mmap(NULL, EXEC_MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + return (exec_mem != MAP_FAILED); +} + + +void * +_glapi_exec_malloc(unsigned int size) +{ + void *addr = NULL; + + _glthread_LOCK_MUTEX(exec_mutex); + + if (!init_map()) + goto bail; + + /* free space check, assumes no integer overflow */ + if (head + size > EXEC_MAP_SIZE) + goto bail; + + /* allocation, assumes proper addr and size alignement */ + addr = exec_mem + head; + head += size; + +bail: + _glthread_UNLOCK_MUTEX(exec_mutex); + + return addr; +} + + +#else + +void * +_glapi_exec_malloc(unsigned int size) +{ + return malloc(size); +} + + +#endif diff --git a/src/mesa/glapi/glapi_getproc.c b/src/mesa/glapi/glapi_getproc.c index a6dbf173e82..c73e8dd3b04 100644 --- a/src/mesa/glapi/glapi_getproc.c +++ b/src/mesa/glapi/glapi_getproc.c @@ -39,25 +39,19 @@ #endif #include "glapi/glapi.h" -#include "glapi/glapioffsets.h" +#include "glapi/glapi_priv.h" #include "glapi/glapitable.h" +#include "glapi/glapioffsets.h" -#if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS) -# define DISPATCH_FUNCTION_SIZE 16 -#elif defined(USE_X86_ASM) -# if defined(THREADS) && !defined(GLX_USE_TLS) -# define DISPATCH_FUNCTION_SIZE 32 -# else -# define DISPATCH_FUNCTION_SIZE 16 -# endif -#endif +/********************************************************************** + * Static function management. + */ + -#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer) +#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) # define NEED_FUNCTION_POINTER #endif - -/* The code in this file is auto-generated with Python */ #include "glapi/glprocs.h" @@ -66,13 +60,13 @@ * and return the corresponding glprocs_table_t entry. */ static const glprocs_table_t * -find_entry( const char * n ) +get_static_proc( const char * n ) { GLuint i; for (i = 0; static_functions[i].Name_offset >= 0; i++) { const char *testName = gl_string_table + static_functions[i].Name_offset; #ifdef MANGLE - /* skip the "m" prefix on the name */ + /* skip the prefix on the name */ if (strcmp(testName, n + 1) == 0) #else if (strcmp(testName, n) == 0) @@ -92,27 +86,16 @@ find_entry( const char * n ) static GLint get_static_proc_offset(const char *funcName) { - const glprocs_table_t * const f = find_entry( funcName ); - if (f) { - return f->Offset; + const glprocs_table_t * const f = get_static_proc( funcName ); + if (f == NULL) { + return -1; } - return -1; -} - -#ifdef USE_X86_ASM - -#if defined( GLX_USE_TLS ) -extern GLubyte gl_dispatch_functions_start[]; -extern GLubyte gl_dispatch_functions_end[]; -#else -extern const GLubyte gl_dispatch_functions_start[]; -#endif - -#endif /* USE_X86_ASM */ + return f->Offset; +} -#if !defined(XFree86Server) && !defined(XGLServer) +#if !defined(XFree86Server) /** * Return dispatch function address for the named static (built-in) function. @@ -121,27 +104,32 @@ extern const GLubyte gl_dispatch_functions_start[]; static _glapi_proc get_static_proc_address(const char *funcName) { - const glprocs_table_t * const f = find_entry( funcName ); - if (f) { + const glprocs_table_t * const f = get_static_proc( funcName ); + if (f == NULL) { + return NULL; + } + #if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING) - return (f->Address == NULL) - ? (_glapi_proc) (gl_dispatch_functions_start - + (DISPATCH_FUNCTION_SIZE * f->Offset)) - : f->Address; + return (f->Address == NULL) + ? get_entrypoint_address(f->Offset) + : f->Address; #elif defined(DISPATCH_FUNCTION_SIZE) - return (_glapi_proc) (gl_dispatch_functions_start - + (DISPATCH_FUNCTION_SIZE * f->Offset)); + return get_entrypoint_address(f->Offset); #else - return f->Address; + return f->Address; #endif - } - else { - return NULL; - } } -#endif /* !defined(XFree86Server) && !defined(XGLServer) */ +#else + +static _glapi_proc +get_static_proc_address(const char *funcName) +{ + (void) funcName; + return NULL; +} +#endif /* !defined(XFree86Server) */ /** @@ -162,172 +150,6 @@ get_static_proc_name( GLuint offset ) -#if defined(PTHREADS) || defined(GLX_USE_TLS) - -/** - * Perform platform-specific GL API entry-point fixups. - */ -static void -init_glapi_relocs( void ) -{ -#if defined(USE_X86_ASM) && defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT) - extern unsigned long _x86_get_dispatch(void); - char run_time_patch[] = { - 0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */ - }; - GLuint *offset = (GLuint *) &run_time_patch[2]; /* 32-bits for x86/32 */ - const GLubyte * const get_disp = (const GLubyte *) run_time_patch; - GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start; - - *offset = _x86_get_dispatch(); - while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) { - (void) memcpy( curr_func, get_disp, sizeof(run_time_patch)); - curr_func += DISPATCH_FUNCTION_SIZE; - } -#endif -#ifdef USE_SPARC_ASM - extern void __glapi_sparc_icache_flush(unsigned int *); - static const unsigned int template[] = { -#ifdef GLX_USE_TLS - 0x05000000, /* sethi %hi(_glapi_tls_Dispatch), %g2 */ - 0x8730e00a, /* srl %g3, 10, %g3 */ - 0x8410a000, /* or %g2, %lo(_glapi_tls_Dispatch), %g2 */ -#ifdef __arch64__ - 0xc259c002, /* ldx [%g7 + %g2], %g1 */ - 0xc2584003, /* ldx [%g1 + %g3], %g1 */ -#else - 0xc201c002, /* ld [%g7 + %g2], %g1 */ - 0xc2004003, /* ld [%g1 + %g3], %g1 */ -#endif - 0x81c04000, /* jmp %g1 */ - 0x01000000, /* nop */ -#else -#ifdef __arch64__ - 0x03000000, /* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */ - 0x05000000, /* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */ - 0x82106000, /* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */ - 0x8730e00a, /* 64-bit 0x0c --> srl %g3, 10, %g3 */ - 0x83287020, /* 64-bit 0x10 --> sllx %g1, 32, %g1 */ - 0x82004002, /* 64-bit 0x14 --> add %g1, %g2, %g1 */ - 0xc2586000, /* 64-bit 0x18 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */ -#else - 0x03000000, /* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */ - 0x8730e00a, /* 32-bit 0x04 --> srl %g3, 10, %g3 */ - 0xc2006000, /* 32-bit 0x08 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */ -#endif - 0x80a06000, /* --> cmp %g1, 0 */ - 0x02800005, /* --> be +4*5 */ - 0x01000000, /* --> nop */ -#ifdef __arch64__ - 0xc2584003, /* 64-bit --> ldx [%g1 + %g3], %g1 */ -#else - 0xc2004003, /* 32-bit --> ld [%g1 + %g3], %g1 */ -#endif - 0x81c04000, /* --> jmp %g1 */ - 0x01000000, /* --> nop */ -#ifdef __arch64__ - 0x9de3bf80, /* 64-bit --> save %sp, -128, %sp */ -#else - 0x9de3bfc0, /* 32-bit --> save %sp, -64, %sp */ -#endif - 0xa0100003, /* --> mov %g3, %l0 */ - 0x40000000, /* --> call _glapi_get_dispatch */ - 0x01000000, /* --> nop */ - 0x82100008, /* --> mov %o0, %g1 */ - 0x86100010, /* --> mov %l0, %g3 */ - 0x10bffff7, /* --> ba -4*9 */ - 0x81e80000, /* --> restore */ -#endif - }; -#ifdef GLX_USE_TLS - extern unsigned int __glapi_sparc_tls_stub; - extern unsigned long __glapi_sparc_get_dispatch(void); - unsigned int *code = &__glapi_sparc_tls_stub; - unsigned long dispatch = __glapi_sparc_get_dispatch(); -#else - extern unsigned int __glapi_sparc_pthread_stub; - unsigned int *code = &__glapi_sparc_pthread_stub; - unsigned long dispatch = (unsigned long) &_glapi_Dispatch; - unsigned long call_dest = (unsigned long ) &_glapi_get_dispatch; - int idx; -#endif - -#if defined(GLX_USE_TLS) - code[0] = template[0] | (dispatch >> 10); - code[1] = template[1]; - __glapi_sparc_icache_flush(&code[0]); - code[2] = template[2] | (dispatch & 0x3ff); - code[3] = template[3]; - __glapi_sparc_icache_flush(&code[2]); - code[4] = template[4]; - code[5] = template[5]; - __glapi_sparc_icache_flush(&code[4]); - code[6] = template[6]; - __glapi_sparc_icache_flush(&code[6]); -#else -#if defined(__arch64__) - code[0] = template[0] | (dispatch >> (32 + 10)); - code[1] = template[1] | ((dispatch & 0xffffffff) >> 10); - __glapi_sparc_icache_flush(&code[0]); - code[2] = template[2] | ((dispatch >> 32) & 0x3ff); - code[3] = template[3]; - __glapi_sparc_icache_flush(&code[2]); - code[4] = template[4]; - code[5] = template[5]; - __glapi_sparc_icache_flush(&code[4]); - code[6] = template[6] | (dispatch & 0x3ff); - idx = 7; -#else - code[0] = template[0] | (dispatch >> 10); - code[1] = template[1]; - __glapi_sparc_icache_flush(&code[0]); - code[2] = template[2] | (dispatch & 0x3ff); - idx = 3; -#endif - code[idx + 0] = template[idx + 0]; - __glapi_sparc_icache_flush(&code[idx - 1]); - code[idx + 1] = template[idx + 1]; - code[idx + 2] = template[idx + 2]; - __glapi_sparc_icache_flush(&code[idx + 1]); - code[idx + 3] = template[idx + 3]; - code[idx + 4] = template[idx + 4]; - __glapi_sparc_icache_flush(&code[idx + 3]); - code[idx + 5] = template[idx + 5]; - code[idx + 6] = template[idx + 6]; - __glapi_sparc_icache_flush(&code[idx + 5]); - code[idx + 7] = template[idx + 7]; - code[idx + 8] = template[idx + 8] | - (((call_dest - ((unsigned long) &code[idx + 8])) - >> 2) & 0x3fffffff); - __glapi_sparc_icache_flush(&code[idx + 7]); - code[idx + 9] = template[idx + 9]; - code[idx + 10] = template[idx + 10]; - __glapi_sparc_icache_flush(&code[idx + 9]); - code[idx + 11] = template[idx + 11]; - code[idx + 12] = template[idx + 12]; - __glapi_sparc_icache_flush(&code[idx + 11]); - code[idx + 13] = template[idx + 13]; - __glapi_sparc_icache_flush(&code[idx + 13]); -#endif -#endif -} - -void -init_glapi_relocs_once( void ) -{ - static pthread_once_t once_control = PTHREAD_ONCE_INIT; - pthread_once( & once_control, init_glapi_relocs ); -} - -#else - -void -init_glapi_relocs_once( void ) { } - -#endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */ - - - /********************************************************************** * Extension function management. */ @@ -381,107 +203,54 @@ struct _glapi_function { static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS]; static GLuint NumExtEntryPoints = 0; -#ifdef USE_SPARC_ASM -extern void __glapi_sparc_icache_flush(unsigned int *); -#endif - -static void -fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset); -/** - * Generate a dispatch function (entrypoint) which jumps through - * the given slot number (offset) in the current dispatch table. - * We need assembly language in order to accomplish this. - */ -static _glapi_proc -generate_entrypoint(GLuint functionOffset) +static struct _glapi_function * +get_extension_proc(const char *funcName) { -#if defined(USE_X86_ASM) - /* 32 is chosen as something of a magic offset. For x86, the dispatch - * at offset 32 is the first one where the offset in the - * "jmp OFFSET*4(%eax)" can't be encoded in a single byte. - */ - const GLubyte * const template_func = gl_dispatch_functions_start - + (DISPATCH_FUNCTION_SIZE * 32); - GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE); - - - if ( code != NULL ) { - (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE); - fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset ); + GLuint i; + for (i = 0; i < NumExtEntryPoints; i++) { + if (strcmp(ExtEntryTable[i].name, funcName) == 0) { + return & ExtEntryTable[i]; + } } + return NULL; +} - return (_glapi_proc) code; -#elif defined(USE_SPARC_ASM) - -#if defined(PTHREADS) || defined(GLX_USE_TLS) - static const unsigned int template[] = { - 0x07000000, /* sethi %hi(0), %g3 */ - 0x8210000f, /* mov %o7, %g1 */ - 0x40000000, /* call */ - 0x9e100001, /* mov %g1, %o7 */ - }; -#ifdef GLX_USE_TLS - extern unsigned int __glapi_sparc_tls_stub; - unsigned long call_dest = (unsigned long ) &__glapi_sparc_tls_stub; -#else - extern unsigned int __glapi_sparc_pthread_stub; - unsigned long call_dest = (unsigned long ) &__glapi_sparc_pthread_stub; -#endif - unsigned int *code = (unsigned int *) malloc(sizeof(template)); - if (code) { - code[0] = template[0] | (functionOffset & 0x3fffff); - code[1] = template[1]; - __glapi_sparc_icache_flush(&code[0]); - code[2] = template[2] | - (((call_dest - ((unsigned long) &code[2])) - >> 2) & 0x3fffffff); - code[3] = template[3]; - __glapi_sparc_icache_flush(&code[2]); + +static GLint +get_extension_proc_offset(const char *funcName) +{ + const struct _glapi_function * const f = get_extension_proc( funcName ); + if (f == NULL) { + return -1; } - return (_glapi_proc) code; -#endif -#else - (void) functionOffset; - return NULL; -#endif /* USE_*_ASM */ + return f->dispatch_offset; } -/** - * This function inserts a new dispatch offset into the assembly language - * stub that was generated with the preceeding function. - */ -static void -fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) +static _glapi_proc +get_extension_proc_address(const char *funcName) { -#if defined(USE_X86_ASM) - GLubyte * const code = (GLubyte *) entrypoint; - -#if DISPATCH_FUNCTION_SIZE == 32 - *((unsigned int *)(code + 11)) = 4 * offset; - *((unsigned int *)(code + 22)) = 4 * offset; -#elif DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS ) - *((unsigned int *)(code + 8)) = 4 * offset; -#elif DISPATCH_FUNCTION_SIZE == 16 - *((unsigned int *)(code + 7)) = 4 * offset; -#else -# error Invalid DISPATCH_FUNCTION_SIZE! -#endif + const struct _glapi_function * const f = get_extension_proc( funcName ); + if (f == NULL) { + return NULL; + } -#elif defined(USE_SPARC_ASM) - unsigned int *code = (unsigned int *) entrypoint; - code[0] &= ~0x3fffff; - code[0] |= (offset * sizeof(void *)) & 0x3fffff; - __glapi_sparc_icache_flush(&code[0]); -#else + return f->dispatch_stub; +} - /* an unimplemented architecture */ - (void) entrypoint; - (void) offset; -#endif /* USE_*_ASM */ +static const char * +get_extension_proc_name(GLuint offset) +{ + GLuint i; + for (i = 0; i < NumExtEntryPoints; i++) { + if (ExtEntryTable[i].dispatch_offset == offset) { + return ExtEntryTable[i].name; + } + } + return NULL; } @@ -518,20 +287,55 @@ static struct _glapi_function * add_function_name( const char * funcName ) { struct _glapi_function * entry = NULL; - - if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) { - _glapi_proc entrypoint = generate_entrypoint(~0); - if (entrypoint != NULL) { - entry = & ExtEntryTable[NumExtEntryPoints]; - - ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName); - ExtEntryTable[NumExtEntryPoints].parameter_signature = NULL; - ExtEntryTable[NumExtEntryPoints].dispatch_offset = ~0; - ExtEntryTable[NumExtEntryPoints].dispatch_stub = entrypoint; - NumExtEntryPoints++; - } + _glapi_proc entrypoint = NULL; + char * name_dup = NULL; + + if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS) + return NULL; + + if (funcName == NULL) + return NULL; + + name_dup = str_dup(funcName); + if (name_dup == NULL) + return NULL; + + entrypoint = generate_entrypoint(~0); + + if (entrypoint == NULL) { + free(name_dup); + return NULL; } + entry = & ExtEntryTable[NumExtEntryPoints]; + NumExtEntryPoints++; + + entry->name = name_dup; + entry->parameter_signature = NULL; + entry->dispatch_offset = ~0; + entry->dispatch_stub = entrypoint; + + return entry; +} + + +static struct _glapi_function * +set_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset ) +{ + char * sig_dup = NULL; + + if (signature == NULL) + return NULL; + + sig_dup = str_dup(signature); + if (sig_dup == NULL) + return NULL; + + fill_in_entrypoint_offset(entry->dispatch_stub, offset); + + entry->parameter_signature = sig_dup; + entry->dispatch_offset = offset; + return entry; } @@ -593,88 +397,103 @@ _glapi_add_dispatch( const char * const * function_names, struct _glapi_function * entry[8]; GLboolean is_static[8]; unsigned i; - unsigned j; int offset = ~0; - int new_offset; + init_glapi_relocs_once(); (void) memset( is_static, 0, sizeof( is_static ) ); (void) memset( entry, 0, sizeof( entry ) ); + /* Find the _single_ dispatch offset for all function names that already + * exist (and have a dispatch offset). + */ + for ( i = 0 ; function_names[i] != NULL ; i++ ) { - /* Do some trivial validation on the name of the function. - */ + const char * funcName = function_names[i]; + int static_offset; + int extension_offset; - if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l') + if (funcName[0] != 'g' || funcName[1] != 'l') return -1; - - /* Determine if the named function already exists. If the function does - * exist, it must have the same parameter signature as the function - * being added. - */ - - new_offset = get_static_proc_offset(function_names[i]); - if (new_offset >= 0) { + + /* search built-in functions */ + static_offset = get_static_proc_offset(funcName); + + if (static_offset >= 0) { + + is_static[i] = GL_TRUE; + /* FIXME: Make sure the parameter signatures match! How do we get * FIXME: the parameter signature for static functions? */ - if ( (offset != ~0) && (new_offset != offset) ) { + if ( (offset != ~0) && (static_offset != offset) ) { return -1; } - is_static[i] = GL_TRUE; - offset = new_offset; + offset = static_offset; + + continue; } - - - for ( j = 0 ; j < NumExtEntryPoints ; j++ ) { - if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) { - /* The offset may be ~0 if the function name was added by - * glXGetProcAddress but never filled in by the driver. - */ - - if (ExtEntryTable[j].dispatch_offset != ~0) { - if (strcmp(real_sig, ExtEntryTable[j].parameter_signature) - != 0) { - return -1; - } - - if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) { - return -1; - } - - offset = ExtEntryTable[j].dispatch_offset; - } - - entry[i] = & ExtEntryTable[j]; - break; + + /* search added extension functions */ + entry[i] = get_extension_proc(funcName); + + if (entry[i] != NULL) { + extension_offset = entry[i]->dispatch_offset; + + /* The offset may be ~0 if the function name was added by + * glXGetProcAddress but never filled in by the driver. + */ + + if (extension_offset == ~0) { + continue; + } + + if (strcmp(real_sig, entry[i]->parameter_signature) != 0) { + return -1; } + + if ( (offset != ~0) && (extension_offset != offset) ) { + return -1; + } + + offset = extension_offset; } } + /* If all function names are either new (or with no dispatch offset), + * allocate a new dispatch offset. + */ + if (offset == ~0) { offset = next_dynamic_offset; next_dynamic_offset++; } + /* Fill in the dispatch offset for the new function names (and those with + * no dispatch offset). + */ + for ( i = 0 ; function_names[i] != NULL ; i++ ) { - if (! is_static[i] ) { + if (is_static[i]) { + continue; + } + + /* generate entrypoints for new function names */ + if (entry[i] == NULL) { + entry[i] = add_function_name( function_names[i] ); if (entry[i] == NULL) { - entry[i] = add_function_name( function_names[i] ); - if (entry[i] == NULL) { - /* FIXME: Possible memory leak here. - */ - return -1; - } + /* FIXME: Possible memory leak here. */ + return -1; } + } - entry[i]->parameter_signature = str_dup(real_sig); - fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset); - entry[i]->dispatch_offset = offset; + if (entry[i]->dispatch_offset == ~0) { + set_entry_info( entry[i], real_sig, offset ); } } - + return offset; } @@ -685,13 +504,13 @@ _glapi_add_dispatch( const char * const * function_names, PUBLIC GLint _glapi_get_proc_offset(const char *funcName) { + GLint offset; + /* search extension functions first */ - GLuint i; - for (i = 0; i < NumExtEntryPoints; i++) { - if (strcmp(ExtEntryTable[i].name, funcName) == 0) { - return ExtEntryTable[i].dispatch_offset; - } - } + offset = get_extension_proc_offset(funcName); + if (offset >= 0) + return offset; + /* search static functions */ return get_static_proc_offset(funcName); } @@ -706,11 +525,14 @@ _glapi_get_proc_offset(const char *funcName) PUBLIC _glapi_proc _glapi_get_proc_address(const char *funcName) { + _glapi_proc func; struct _glapi_function * entry; - GLuint i; + + init_glapi_relocs_once(); #ifdef MANGLE - if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l') + /* skip the prefix on the name */ + if (funcName[1] != 'g' || funcName[2] != 'l') return NULL; #else if (funcName[0] != 'g' || funcName[1] != 'l') @@ -718,23 +540,21 @@ _glapi_get_proc_address(const char *funcName) #endif /* search extension functions first */ - for (i = 0; i < NumExtEntryPoints; i++) { - if (strcmp(ExtEntryTable[i].name, funcName) == 0) { - return ExtEntryTable[i].dispatch_stub; - } - } + func = get_extension_proc_address(funcName); + if (func) + return func; -#if !defined( XFree86Server ) && !defined( XGLServer ) /* search static functions */ - { - const _glapi_proc func = get_static_proc_address(funcName); - if (func) - return func; - } -#endif /* !defined( XFree86Server ) */ + func = get_static_proc_address(funcName); + if (func) + return func; + /* generate entrypoint, dispatch offset must be filled in by the driver */ entry = add_function_name(funcName); - return (entry == NULL) ? NULL : entry->dispatch_stub; + if (entry == NULL) + return NULL; + + return entry->dispatch_stub; } @@ -746,7 +566,6 @@ _glapi_get_proc_address(const char *funcName) const char * _glapi_get_proc_name(GLuint offset) { - GLuint i; const char * n; /* search built-in functions */ @@ -756,16 +575,56 @@ _glapi_get_proc_name(GLuint offset) } /* search added extension functions */ - for (i = 0; i < NumExtEntryPoints; i++) { - if (ExtEntryTable[i].dispatch_offset == offset) { - return ExtEntryTable[i].name; - } - } - return NULL; + return get_extension_proc_name(offset); } +/********************************************************************** + * GL API table functions. + */ + + +/* + * The dispatch table size (number of entries) is the size of the + * _glapi_table struct plus the number of dynamic entries we can add. + * The extra slots can be filled in by DRI drivers that register new extension + * functions. + */ +#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS) + + +/** + * Return size of dispatch table struct as number of functions (or + * slots). + */ +PUBLIC GLuint +_glapi_get_dispatch_table_size(void) +{ + return DISPATCH_TABLE_SIZE; +} + + +/** + * Make sure there are no NULL pointers in the given dispatch table. + * Intended for debugging purposes. + */ +void +_glapi_check_table_not_null(const struct _glapi_table *table) +{ +#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */ + const GLuint entries = _glapi_get_dispatch_table_size(); + const void **tab = (const void **) table; + GLuint i; + for (i = 1; i < entries; i++) { + assert(tab[i]); + } +#else + (void) table; +#endif +} + + /** * Do some spot checks to be sure that the dispatch table * slots are assigned correctly. For debugging only. @@ -773,7 +632,7 @@ _glapi_get_proc_name(GLuint offset) void _glapi_check_table(const struct _glapi_table *table) { -#if 0 /* enable this for extra DEBUG */ +#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */ { GLuint BeginOffset = _glapi_get_proc_offset("glBegin"); char *BeginFunc = (char*) &table->Begin; diff --git a/src/mesa/glapi/glapi_priv.h b/src/mesa/glapi/glapi_priv.h new file mode 100644 index 00000000000..da6fee63fe7 --- /dev/null +++ b/src/mesa/glapi/glapi_priv.h @@ -0,0 +1,99 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _GLAPI_PRIV_H +#define _GLAPI_PRIV_H + +#include "glthread.h" +#include "glapi.h" + + + +/* getproc */ + +extern void +_glapi_check_table_not_null(const struct _glapi_table *table); + + +extern void +_glapi_check_table(const struct _glapi_table *table); + + +/* execmem */ + +extern void * +_glapi_exec_malloc(unsigned int size); + + +/* entrypoint */ + +extern void +init_glapi_relocs_once(void); + + +extern _glapi_proc +generate_entrypoint(unsigned int functionOffset); + + +extern void +fill_in_entrypoint_offset(_glapi_proc entrypoint, unsigned int offset); + + +extern _glapi_proc +get_entrypoint_address(unsigned int functionOffset); + + +/** + * Size (in bytes) of dispatch function (entrypoint). + */ +#if defined(USE_X86_ASM) +# if defined(GLX_USE_TLS) +# define DISPATCH_FUNCTION_SIZE 16 +# elif defined(THREADS) +# define DISPATCH_FUNCTION_SIZE 32 +# else +# define DISPATCH_FUNCTION_SIZE 16 +# endif +#endif + +#if defined(USE_X64_64_ASM) +# if defined(GLX_USE_TLS) +# define DISPATCH_FUNCTION_SIZE 16 +# endif +#endif + + +/** + * Number of extension functions which we can dynamically add at runtime. + * + * Number of extension functions is also subject to the size of backing exec + * mem we allocate. For the common case of dispatch stubs with size 16 bytes, + * the two limits will be hit simultaneously. For larger dispatch function + * sizes, MAX_EXTENSION_FUNCS is effectively reduced. + */ +#define MAX_EXTENSION_FUNCS 256 + + +#endif diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 14c533e0d43..7c442e390c2 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -1549,6 +1549,7 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target, texObj = _mesa_lookup_texture(ctx, texture); if (texObj != NULL) { if (textarget == 0) { + /* XXX what's the purpose of this? */ err = (texObj->Target != GL_TEXTURE_3D) && (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); @@ -1559,6 +1560,13 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target, : (texObj->Target != textarget); } } + else { + /* can't render to a non-existant texture */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture%sEXT(non existant texture)", + caller); + return; + } if (err) { _mesa_error(ctx, GL_INVALID_OPERATION, diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 6a85162d5da..5a654e5c2a3 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -986,6 +986,10 @@ _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format) return GL_TRUE; } + +/** + * Used to answer the GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES query. + */ GLenum _mesa_get_color_read_format(GLcontext *ctx) { @@ -999,6 +1003,10 @@ _mesa_get_color_read_format(GLcontext *ctx) } } + +/** + * Used to answer the GL_IMPLEMENTATION_COLOR_READ_TYPE_OES query. + */ GLenum _mesa_get_color_read_type(GLcontext *ctx) { diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h index 7ed1e1a32a4..59f62ebd6c5 100644 --- a/src/mesa/main/version.h +++ b/src/mesa/main/version.h @@ -1,6 +1,6 @@ /* * Mesa 3-D graphics library - * Version: 7.8 + * Version: 7.9 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * Copyright (C) 2009 VMware, Inc. All Rights Reserved. @@ -33,9 +33,9 @@ /* Mesa version */ #define MESA_MAJOR 7 -#define MESA_MINOR 8 +#define MESA_MINOR 9 #define MESA_PATCH 0 -#define MESA_VERSION_STRING "7.8-rc1" +#define MESA_VERSION_STRING "7.9-devel" /* To make version comparison easy */ #define MESA_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak index 9f2e4e51575..d6ae696e395 100644 --- a/src/mesa/sources.mak +++ b/src/mesa/sources.mak @@ -88,6 +88,8 @@ MAIN_SOURCES = \ GLAPI_SOURCES = \ glapi/glapi.c \ glapi/glapi_dispatch.c \ + glapi/glapi_entrypoint.c \ + glapi/glapi_execmem.c \ glapi/glapi_getproc.c \ glapi/glapi_nop.c \ glapi/glthread.c @@ -212,6 +214,7 @@ STATETRACKER_SOURCES = \ state_tracker/st_format.c \ state_tracker/st_framebuffer.c \ state_tracker/st_gen_mipmap.c \ + state_tracker/st_manager.c \ state_tracker/st_mesa_to_tgsi.c \ state_tracker/st_program.c \ state_tracker/st_texture.c diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 7806df4a531..9fa4dae5ca9 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -34,6 +34,7 @@ #include "st_atom.h" #include "st_cb_bitmap.h" #include "st_program.h" +#include "st_manager.h" #include "pipe/p_context.h" @@ -136,9 +137,7 @@ void st_validate_state( struct st_context *st ) check_program_state( st ); - if (st->pipe->screen->update_buffer) - st->pipe->screen->update_buffer(st->pipe->screen, - st->pipe->priv); + st_manager_validate_framebuffers(st); if (state->st == 0) return; diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index 0b2e3f53812..03e33361448 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -138,7 +138,6 @@ static void load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) { struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *transfer; const GLuint rSize = ctx->PixelMaps.RtoR.Size; const GLuint gSize = ctx->PixelMaps.GtoG.Size; @@ -151,7 +150,7 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) transfer = st_cond_flush_get_tex_transfer(st_context(ctx), pt, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, texSize, texSize); - dest = (uint *) screen->transfer_map(screen, transfer); + dest = (uint *) pipe->transfer_map(pipe, transfer); /* Pack four 1D maps into a 2D texture: * R map is placed horizontally, indexed by S, in channel 0 @@ -172,8 +171,8 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) } } - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->tex_transfer_destroy(pipe, transfer); } @@ -257,6 +256,8 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key) /* create the colormap/texture now if not already done */ if (!st->pixel_xfer.pixelmap_texture) { st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx); + st->pixel_xfer.pixelmap_sampler_view = st_sampler_view_from_texture(ctx->st->pipe, + st->pixel_xfer.pixelmap_texture); } /* with a little effort, we can do four pixel map look-ups with diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 57b71c1e7b0..241c001f94f 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -56,7 +56,7 @@ update_textures(struct st_context *st) /* loop over sampler units (aka tex image units) */ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { - struct pipe_texture *pt = NULL; + struct pipe_sampler_view *sampler_view = NULL; if (samplersUsed & (1 << su)) { struct gl_texture_object *texObj; @@ -84,7 +84,7 @@ update_textures(struct st_context *st) st->state.num_textures = su + 1; - pt = st_get_stobj_texture(stObj); + sampler_view = st_get_stobj_sampler_view(stObj); } /* @@ -96,17 +96,17 @@ update_textures(struct st_context *st) } */ - pipe_texture_reference(&st->state.sampler_texture[su], pt); + pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); } - cso_set_sampler_textures(st->cso_context, - st->state.num_textures, - st->state.sampler_texture); + cso_set_fragment_sampler_views(st->cso_context, + st->state.num_textures, + st->state.sampler_views); if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { - cso_set_vertex_sampler_textures(st->cso_context, - MIN2(st->state.num_textures, - st->ctx->Const.MaxVertexTextureImageUnits), - st->state.sampler_texture); + cso_set_vertex_sampler_views(st->cso_context, + MIN2(st->state.num_textures, + st->ctx->Const.MaxVertexTextureImageUnits), + st->state.sampler_views); } } diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index 33e43ddcc4c..01aba3e3dd4 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -129,7 +129,6 @@ accum_accum(struct st_context *st, GLfloat value, struct st_renderbuffer *color_strb) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *color_trans; size_t stride = acc_strb->stride; GLubyte *data = acc_strb->data; @@ -145,7 +144,7 @@ accum_accum(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -166,7 +165,7 @@ accum_accum(struct st_context *st, GLfloat value, } free(buf); - screen->tex_transfer_destroy(color_trans); + pipe->tex_transfer_destroy(pipe, color_trans); } @@ -177,7 +176,6 @@ accum_load(struct st_context *st, GLfloat value, struct st_renderbuffer *color_strb) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *color_trans; size_t stride = acc_strb->stride; GLubyte *data = acc_strb->data; @@ -194,7 +192,7 @@ accum_load(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -215,7 +213,7 @@ accum_load(struct st_context *st, GLfloat value, } free(buf); - screen->tex_transfer_destroy(color_trans); + pipe->tex_transfer_destroy(pipe, color_trans); } @@ -226,7 +224,6 @@ accum_return(GLcontext *ctx, GLfloat value, struct st_renderbuffer *color_strb) { struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; const GLubyte *colormask = ctx->Color.ColorMask[0]; enum pipe_transfer_usage usage; struct pipe_transfer *color_trans; @@ -251,7 +248,7 @@ accum_return(GLcontext *ctx, GLfloat value, width, height); if (usage & PIPE_TRANSFER_READ) - pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -280,10 +277,10 @@ accum_return(GLcontext *ctx, GLfloat value, _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - pipe_put_tile_rgba(color_trans, 0, 0, width, height, buf); + pipe_put_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); free(buf); - screen->tex_transfer_destroy(color_trans); + pipe->tex_transfer_destroy(pipe, color_trans); } diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 0332d4dbdfe..9a0446bb710 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -259,7 +259,6 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, const GLubyte *bitmap) { struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *transfer; ubyte *dest; struct pipe_texture *pt; @@ -285,7 +284,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, PIPE_TRANSFER_WRITE, 0, 0, width, height); - dest = screen->transfer_map(screen, transfer); + dest = pipe->transfer_map(pipe, transfer); /* Put image into texture transfer */ memset(dest, 0xff, height * transfer->stride); @@ -295,8 +294,8 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, _mesa_unmap_pbo_source(ctx, unpack); /* Release transfer */ - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->tex_transfer_destroy(pipe, transfer); return pt; } @@ -398,7 +397,7 @@ setup_bitmap_vertex_data(struct st_context *st, static void draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, GLsizei width, GLsizei height, - struct pipe_texture *pt, + struct pipe_sampler_view *sv, const GLfloat *color) { struct st_context *st = ctx->st; @@ -436,10 +435,11 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_save_rasterizer(cso); cso_save_samplers(cso); - cso_save_sampler_textures(cso); + cso_save_fragment_sampler_views(cso); cso_save_viewport(cso); cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); + cso_save_vertex_elements(cso); /* rasterizer state: just scissor */ st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled; @@ -465,11 +465,11 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* user textures, plus the bitmap texture */ { - struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures); - memcpy(textures, st->state.sampler_texture, sizeof(textures)); - textures[stfp->bitmap_sampler] = pt; - cso_set_sampler_textures(cso, num, textures); + memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views)); + sampler_views[stfp->bitmap_sampler] = sv; + cso_set_fragment_sampler_views(cso, num, sampler_views); } /* viewport state: viewport matching window dims */ @@ -490,6 +490,8 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_set_viewport(cso, &vp); } + cso_set_vertex_elements(cso, 3, st->velems_util_draw); + /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ z = z * 2.0 - 1.0; @@ -505,10 +507,11 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* restore state */ cso_restore_rasterizer(cso); cso_restore_samplers(cso); - cso_restore_sampler_textures(cso); + cso_restore_fragment_sampler_views(cso); cso_restore_viewport(cso); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); + cso_restore_vertex_elements(cso); } @@ -516,7 +519,6 @@ static void reset_cache(struct st_context *st) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct bitmap_cache *cache = st->bitmap.cache; /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/ @@ -528,7 +530,7 @@ reset_cache(struct st_context *st) cache->ymax = -1000000; if (cache->trans) { - screen->tex_transfer_destroy(cache->trans); + pipe->tex_transfer_destroy(pipe, cache->trans); cache->trans = NULL; } @@ -566,7 +568,6 @@ static void create_cache_trans(struct st_context *st) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct bitmap_cache *cache = st->bitmap.cache; if (cache->trans) @@ -579,7 +580,7 @@ create_cache_trans(struct st_context *st) PIPE_TRANSFER_WRITE, 0, 0, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT); - cache->buffer = screen->transfer_map(screen, cache->trans); + cache->buffer = pipe->transfer_map(pipe, cache->trans); /* init image to all 0xff */ memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT); @@ -597,7 +598,7 @@ st_flush_bitmap_cache(struct st_context *st) if (st->ctx->DrawBuffer) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; + struct pipe_sampler_view *sv; assert(cache->xmin <= cache->xmax); @@ -613,20 +614,25 @@ st_flush_bitmap_cache(struct st_context *st) if (cache->trans) { if (0) print_cache(cache); - screen->transfer_unmap(screen, cache->trans); + pipe->transfer_unmap(pipe, cache->trans); cache->buffer = NULL; - screen->tex_transfer_destroy(cache->trans); + pipe->tex_transfer_destroy(pipe, cache->trans); cache->trans = NULL; } - draw_bitmap_quad(st->ctx, - cache->xpos, - cache->ypos, - cache->zpos, - BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, - cache->texture, - cache->color); + sv = st_sampler_view_from_texture(st->pipe, cache->texture); + if (sv) { + draw_bitmap_quad(st->ctx, + cache->xpos, + cache->ypos, + cache->zpos, + BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, + sv, + cache->color); + + pipe_sampler_view_reference(&sv, NULL); + } } /* release/free the texture */ @@ -749,10 +755,18 @@ st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (pt) { + struct pipe_sampler_view *sv = st_sampler_view_from_texture(st->pipe, pt); + assert(pt->target == PIPE_TEXTURE_2D); - draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], - width, height, pt, - st->ctx->Current.RasterColor); + + if (sv) { + draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2], + width, height, sv, + st->ctx->Current.RasterColor); + + pipe_sampler_view_reference(&sv, NULL); + } + /* release/free the texture */ pipe_texture_reference(&pt, NULL); } @@ -819,7 +833,6 @@ void st_destroy_bitmap(struct st_context *st) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct bitmap_cache *cache = st->bitmap.cache; @@ -836,8 +849,8 @@ st_destroy_bitmap(struct st_context *st) if (cache) { if (cache->trans) { - screen->transfer_unmap(screen, cache->trans); - screen->tex_transfer_destroy(cache->trans); + pipe->transfer_unmap(pipe, cache->trans); + pipe->tex_transfer_destroy(pipe, cache->trans); } pipe_texture_reference(&st->bitmap.cache->texture, NULL); free(st->bitmap.cache); diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index 36e03018d9f..06b0a18fd22 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -69,6 +69,7 @@ st_BlitFramebuffer(GLcontext *ctx, const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); struct st_context *st = ctx->st; + struct pipe_context *pipe = st->pipe; const uint pFilter = ((filter == GL_NEAREST) ? PIPE_TEX_MIPFILTER_NEAREST : PIPE_TEX_MIPFILTER_LINEAR); @@ -111,8 +112,8 @@ st_BlitFramebuffer(GLcontext *ctx, &readFB->Attachment[readFB->_ColorReadBufferIndex]; if(srcAtt->Type == GL_TEXTURE) { - struct pipe_screen *screen = ctx->st->pipe->screen; - const struct st_texture_object *srcObj = + struct pipe_screen *screen = pipe->screen; + struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture); struct st_renderbuffer *dstRb = st_renderbuffer(drawFB->_ColorDrawBuffers[0]); @@ -132,7 +133,8 @@ st_BlitFramebuffer(GLcontext *ctx, return; util_blit_pixels(st->blit, - srcSurf, srcX0, srcY0, srcX1, srcY1, + srcSurf, st_get_stobj_sampler_view(srcObj), + srcX0, srcY0, srcX1, srcY1, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); @@ -144,10 +146,11 @@ st_BlitFramebuffer(GLcontext *ctx, struct st_renderbuffer *dstRb = st_renderbuffer(drawFB->_ColorDrawBuffers[0]); struct pipe_surface *srcSurf = srcRb->surface; + struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcRb, pipe); struct pipe_surface *dstSurf = dstRb->surface; util_blit_pixels(st->blit, - srcSurf, srcX0, srcY0, srcX1, srcY1, + srcSurf, srcView, srcX0, srcY0, srcX1, srcY1, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } @@ -179,11 +182,13 @@ st_BlitFramebuffer(GLcontext *ctx, if ((mask & depthStencil) == depthStencil && srcDepthSurf == srcStencilSurf && dstDepthSurf == dstStencilSurf) { + struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcDepthRb, pipe); + /* Blitting depth and stencil values between combined * depth/stencil buffers. This is the ideal case for such buffers. */ util_blit_pixels(st->blit, - srcDepthSurf, srcX0, srcY0, srcX1, srcY1, + srcDepthSurf, srcView, srcX0, srcY0, srcX1, srcY1, dstDepthSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 9e66eed3634..de86062fc40 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -213,6 +213,7 @@ clear_with_quad(GLcontext *ctx, cso_save_clip(st->cso_context); cso_save_fragment_shader(st->cso_context); cso_save_vertex_shader(st->cso_context); + cso_save_vertex_elements(st->cso_context); /* blend state: RGBA masking */ { @@ -264,6 +265,8 @@ clear_with_quad(GLcontext *ctx, cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil); } + cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw); + cso_set_rasterizer(st->cso_context, &st->clear.raster); /* viewport state: viewport matching window dims */ @@ -297,6 +300,8 @@ clear_with_quad(GLcontext *ctx, cso_restore_clip(st->cso_context); cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); + cso_restore_vertex_elements(st->cso_context); + } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 7c611cb4ec9..72a2ddb379b 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -293,6 +293,51 @@ base_format(GLenum format) /** + * Create a temporary texture to hold an image of the given size. + * If width, height are not POT and the driver only handles POT textures, + * allocate the next larger size of texture that is POT. + */ +static struct pipe_texture * +alloc_texture(struct st_context *st, GLsizei width, GLsizei height, + enum pipe_format texFormat) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_texture *pt; + int ptw, pth; + + ptw = width; + pth = height; + + /* Need to use POT texture? */ + if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { + int l2pt, maxSize; + + l2pt = util_logbase2(width); + if (1 << l2pt != width) { + ptw = 1 << (l2pt + 1); + } + + l2pt = util_logbase2(height); + if (1 << l2pt != height) { + pth = 1 << (l2pt + 1); + } + + /* Check against maximum texture size */ + maxSize = 1 << (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + assert(ptw <= maxSize); + assert(pth <= maxSize); + } + + pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0, + ptw, pth, 1, PIPE_TEXTURE_USAGE_SAMPLER); + + return pt; +} + + +/** * Make texture containing an image for glDrawPixels image. * If 'pixels' is NULL, leave the texture image data undefined. */ @@ -304,13 +349,11 @@ make_texture(struct st_context *st, { GLcontext *ctx = st->ctx; struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; gl_format mformat; struct pipe_texture *pt; enum pipe_format pipeFormat; GLuint cpp; GLenum baseFormat; - int ptw, pth; baseFormat = base_format(format); @@ -325,29 +368,8 @@ make_texture(struct st_context *st, if (!pixels) return NULL; - /* Need to use POT texture? */ - ptw = width; - pth = height; - if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { - int l2pt, maxSize; - - l2pt = util_logbase2(width); - if (1<<l2pt != width) { - ptw = 1<<(l2pt+1); - } - l2pt = util_logbase2(height); - if (1<<l2pt != height) { - pth = 1<<(l2pt+1); - } - - /* Check against maximum texture size */ - maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); - assert(ptw <= maxSize); - assert(pth <= maxSize); - } - - pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, ptw, pth, 1, - PIPE_TEXTURE_USAGE_SAMPLER); + /* alloc temporary texture */ + pt = alloc_texture(st, width, height, pipeFormat); if (!pt) { _mesa_unmap_pbo_source(ctx, unpack); return NULL; @@ -368,7 +390,7 @@ make_texture(struct st_context *st, width, height); /* map texture transfer */ - dest = screen->transfer_map(screen, transfer); + dest = pipe->transfer_map(pipe, transfer); /* Put image into texture transfer. @@ -388,8 +410,8 @@ make_texture(struct st_context *st, unpack); /* unmap */ - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->tex_transfer_destroy(pipe, transfer); assert(success); @@ -503,7 +525,7 @@ static void draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, GLsizei width, GLsizei height, GLfloat zoomX, GLfloat zoomY, - struct pipe_texture *pt, + struct pipe_sampler_view *sv, void *driver_vp, void *driver_fp, const GLfloat *color, @@ -526,9 +548,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_save_rasterizer(cso); cso_save_viewport(cso); cso_save_samplers(cso); - cso_save_sampler_textures(cso); + cso_save_fragment_sampler_views(cso); cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); + cso_save_vertex_elements(cso); /* rasterizer state: just scissor */ { @@ -581,15 +604,17 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_set_viewport(cso, &vp); } + cso_set_vertex_elements(cso, 3, st->velems_util_draw); + /* texture state: */ if (st->pixel_xfer.pixelmap_enabled) { - struct pipe_texture *textures[2]; - textures[0] = pt; - textures[1] = st->pixel_xfer.pixelmap_texture; - pipe->set_fragment_sampler_textures(pipe, 2, textures); + struct pipe_sampler_view *sampler_views[2]; + sampler_views[0] = sv; + sampler_views[1] = st->pixel_xfer.pixelmap_sampler_view; + cso_set_fragment_sampler_views(cso, 2, sampler_views); } else { - pipe->set_fragment_sampler_textures(pipe, 1, &pt); + cso_set_fragment_sampler_views(cso, 1, &sv); } /* Compute Gallium window coords (y=0=top) with pixel zoom. @@ -610,16 +635,17 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, z = z * 2.0 - 1.0; draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, - (GLfloat) width / pt->width0, - (GLfloat) height / pt->height0); + (GLfloat) width / sv->texture->width0, + (GLfloat) height / sv->texture->height0); /* restore state */ cso_restore_rasterizer(cso); cso_restore_viewport(cso); cso_restore_samplers(cso); - cso_restore_sampler_textures(cso); + cso_restore_fragment_sampler_views(cso); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); + cso_restore_vertex_elements(cso); } @@ -631,7 +657,6 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *strb; enum pipe_transfer_usage usage; struct pipe_transfer *pt; @@ -665,7 +690,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, usage, x, y, width, height); - stmap = screen->transfer_map(screen, pt); + stmap = pipe->transfer_map(pipe, pt); pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); assert(pixels); @@ -765,8 +790,8 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, _mesa_unmap_pbo_source(ctx, &clippedUnpack); /* unmap the stencil buffer */ - screen->transfer_unmap(screen, pt); - screen->tex_transfer_destroy(pt); + pipe->transfer_unmap(pipe, pt); + pipe->tex_transfer_destroy(pipe, pt); } @@ -810,12 +835,17 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, struct pipe_texture *pt = make_texture(st, width, height, format, type, unpack, pixels); if (pt) { - draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], - width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, - pt, - driver_vp, - driver_fp, - color, GL_FALSE); + struct pipe_sampler_view *sv = st_sampler_view_from_texture(st->pipe, pt); + + if (sv) { + draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], + width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, + sv, + driver_vp, + driver_fp, + color, GL_FALSE); + pipe_sampler_view_reference(&sv, NULL); + } pipe_texture_reference(&pt, NULL); } } @@ -829,7 +859,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint dstx, GLint dsty) { struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); - struct pipe_screen *screen = ctx->st->pipe->screen; + struct pipe_context *pipe = ctx->st->pipe; enum pipe_transfer_usage usage; struct pipe_transfer *ptDraw; ubyte *drawMap; @@ -865,7 +895,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, assert(util_format_get_blockheight(ptDraw->texture->format) == 1); /* map the stencil buffer */ - drawMap = screen->transfer_map(screen, ptDraw); + drawMap = pipe->transfer_map(pipe, ptDraw); /* draw */ /* XXX PixelZoom not handled yet */ @@ -918,8 +948,8 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, free(buffer); /* unmap the stencil buffer */ - screen->transfer_unmap(screen, ptDraw); - screen->tex_transfer_destroy(ptDraw); + pipe->transfer_unmap(pipe, ptDraw); + pipe->tex_transfer_destroy(pipe, ptDraw); } @@ -934,9 +964,9 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct st_renderbuffer *rbRead; void *driver_vp, *driver_fp; struct pipe_texture *pt; + struct pipe_sampler_view *sv; GLfloat *color; enum pipe_format srcFormat, texFormat; - int ptw, pth; GLboolean invertTex = GL_FALSE; GLint readX, readY, readW, readH; struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; @@ -1007,33 +1037,17 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, readW = MAX2(0, readW); readH = MAX2(0, readH); - /* Need to use POT texture? */ - ptw = width; - pth = height; - if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { - int l2pt, maxSize; - - l2pt = util_logbase2(width); - if (1<<l2pt != width) { - ptw = 1<<(l2pt+1); - } - l2pt = util_logbase2(height); - if (1<<l2pt != height) { - pth = 1<<(l2pt+1); - } - - /* Check against maximum texture size */ - maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); - assert(ptw <= maxSize); - assert(pth <= maxSize); - } - - pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0, - ptw, pth, 1, - PIPE_TEXTURE_USAGE_SAMPLER); + /* alloc temporary texture */ + pt = alloc_texture(st, width, height, texFormat); if (!pt) return; + sv = st_sampler_view_from_texture(st->pipe, pt); + if (!sv) { + pipe_texture_reference(&pt, NULL); + return; + } + /* Make temporary texture which is a copy of the src region. */ if (srcFormat == texFormat) { @@ -1059,8 +1073,8 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, if (0) { /* debug */ - debug_dump_surface("copypixsrcsurf", psRead); - debug_dump_surface("copypixtemptex", psTex); + debug_dump_surface(pipe, "copypixsrcsurf", psRead); + debug_dump_surface(pipe, "copypixtemptex", psTex); } pipe_surface_reference(&psRead, NULL); @@ -1090,22 +1104,22 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(ptRead, readX, readY, readW, readH, buf); - pipe_put_tile_rgba(ptTex, unpack.SkipPixels, unpack.SkipRows, + pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_rgba(pipe, ptTex, unpack.SkipPixels, unpack.SkipRows, readW, readH, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(ptRead, readX, readY, readW, readH, buf); - pipe_put_tile_z(ptTex, unpack.SkipPixels, unpack.SkipRows, - readW, readH, buf); + pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_z(pipe, ptTex, unpack.SkipPixels, unpack.SkipRows, + readW, readH, buf); free(buf); } - screen->tex_transfer_destroy(ptRead); - screen->tex_transfer_destroy(ptTex); + pipe->tex_transfer_destroy(pipe, ptRead); + pipe->tex_transfer_destroy(pipe, ptTex); } /* OK, the texture 'pt' contains the src image/pixels. Now draw a @@ -1113,12 +1127,13 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, - pt, + sv, driver_vp, driver_fp, color, invertTex); pipe_texture_reference(&pt, NULL); + pipe_sampler_view_reference(&sv, NULL); } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 00e9d1dccbd..4ccba1db85d 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -48,6 +48,7 @@ #include "st_format.h" #include "st_public.h" #include "st_texture.h" +#include "st_manager.h" #include "util/u_format.h" #include "util/u_rect.h" @@ -103,6 +104,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, */ pipe_surface_reference( &strb->surface, NULL ); pipe_texture_reference( &strb->texture, NULL ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); /* Setup new texture template. */ @@ -162,6 +164,7 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb) ASSERT(strb); pipe_surface_reference(&strb->surface, NULL); pipe_texture_reference(&strb->texture, NULL); + pipe_sampler_view_reference(&strb->sampler_view, NULL); free(strb->data); free(strb); } @@ -368,6 +371,8 @@ st_render_texture(GLcontext *ctx, pipe_surface_reference(&strb->surface, NULL); + pipe_sampler_view_reference(&strb->sampler_view, st_get_stobj_sampler_view(stObj)); + assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ @@ -379,6 +384,8 @@ st_render_texture(GLcontext *ctx, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); + strb->format = pt->format; + strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); strb->Base.DataType = st_format_datatype(pt->format); @@ -612,8 +619,18 @@ check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb) static void st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) { + GLframebuffer *fb = ctx->DrawBuffer; + GLuint i; + (void) count; (void) buffers; + + /* add the renderbuffers on demand */ + for (i = 0; i < fb->_NumColorDrawBuffers; i++) { + gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i]; + st_manager_add_color_renderbuffer(ctx->st, fb, idx); + } + check_create_front_buffers(ctx, ctx->DrawBuffer); } @@ -624,8 +641,13 @@ st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) static void st_ReadBuffer(GLcontext *ctx, GLenum buffer) { + GLframebuffer *fb = ctx->ReadBuffer; + (void) buffer; - check_create_front_buffers(ctx, ctx->ReadBuffer); + + /* add the renderbuffer on demand */ + st_manager_add_color_renderbuffer(ctx->st, fb, fb->_ColorReadBufferIndex); + check_create_front_buffers(ctx, fb); } @@ -645,3 +667,14 @@ void st_init_fbo_functions(struct dd_function_table *functions) functions->DrawBuffers = st_DrawBuffers; functions->ReadBuffer = st_ReadBuffer; } + +struct pipe_sampler_view * +st_renderbuffer_get_sampler_view(struct st_renderbuffer *rb, + struct pipe_context *pipe) +{ + if (!rb->sampler_view) { + rb->sampler_view = st_sampler_view_from_texture(pipe, rb->texture); + } + + return rb->sampler_view; +} diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index bea6eb89c3e..7a45a608fe1 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -39,6 +39,7 @@ struct st_renderbuffer struct gl_renderbuffer Base; struct pipe_texture *texture; struct pipe_surface *surface; /* temporary view into texture */ + struct pipe_sampler_view *sampler_view; enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ GLboolean defined; /**< defined contents? */ @@ -55,6 +56,7 @@ struct st_renderbuffer /** Render to texture state */ struct pipe_texture *texture_save; struct pipe_surface *surface_save; + struct pipe_sampler_view *sampler_view_save; }; @@ -71,5 +73,9 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw); extern void st_init_fbo_functions(struct dd_function_table *functions); +extern struct pipe_sampler_view * +st_renderbuffer_get_sampler_view(struct st_renderbuffer *rb, + struct pipe_context *pipe); + #endif /* ST_CB_FBO_H */ diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 1329f807bc9..30e7afcf2a3 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -40,6 +40,7 @@ #include "st_cb_clear.h" #include "st_cb_fbo.h" #include "st_public.h" +#include "st_manager.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -74,12 +75,9 @@ display_front_buffer(struct st_context *st) = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); if (strb) { - struct pipe_surface *front_surf = strb->surface; - /* Hook for copying "fake" frontbuffer if necessary: */ - st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf, - st->pipe->priv ); + st_manager_flush_frontbuffer(st); /* st->frontbuffer_status = FRONT_STATUS_UNDEFINED; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 952d9ce9156..7afb275fe2f 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -45,6 +45,7 @@ #include "st_debug.h" #include "st_context.h" +#include "st_atom.h" #include "st_cb_readpixels.h" #include "st_cb_fbo.h" #include "st_public.h" @@ -63,7 +64,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, GLvoid *pixels) { struct gl_framebuffer *fb = ctx->ReadBuffer; - struct pipe_screen *screen = ctx->st->pipe->screen; + struct pipe_context *pipe = ctx->st->pipe; struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer); struct pipe_transfer *pt; ubyte *stmap; @@ -81,7 +82,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, width, height); /* map the stencil buffer */ - stmap = screen->transfer_map(screen, pt); + stmap = pipe->transfer_map(pipe, pt); /* width should never be > MAX_WIDTH since we did clipping earlier */ ASSERT(width <= MAX_WIDTH); @@ -161,8 +162,8 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, } /* unmap the stencil buffer */ - screen->transfer_unmap(screen, pt); - screen->tex_transfer_destroy(pt); + pipe->transfer_unmap(pipe, pt); + pipe->tex_transfer_destroy(pipe, pt); } @@ -234,13 +235,13 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, { struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *trans; const GLubyte *map; GLubyte *dst; GLint row, col, dy, dstStride; if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + /* convert GL Y to Gallium Y */ y = strb->texture->height0 - y - height; } @@ -252,17 +253,22 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, return GL_FALSE; } - map = screen->transfer_map(screen, trans); + map = pipe->transfer_map(pipe, trans); if (!map) { - screen->tex_transfer_destroy(trans); + pipe->tex_transfer_destroy(pipe, trans); return GL_FALSE; } + /* We always write to the user/dest buffer from low addr to high addr + * but the read order depends on renderbuffer orientation + */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + /* read source rows from bottom to top */ y = height - 1; dy = -1; } else { + /* read source rows from top to bottom */ y = 0; dy = 1; } @@ -311,8 +317,8 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, ; /* nothing */ } - screen->transfer_unmap(screen, trans); - screen->tex_transfer_destroy(trans); + pipe->transfer_unmap(pipe, trans); + pipe->tex_transfer_destroy(pipe, trans); } return GL_TRUE; @@ -331,7 +337,6 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLvoid *dest) { struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; GLfloat temp[MAX_WIDTH][4]; const GLbitfield transferOps = ctx->_ImageTransferState; GLsizei i, j; @@ -346,6 +351,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* XXX convolution not done yet */ assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0); + st_validate_state(ctx->st); + /* Do all needed clipping here, so that we can forget about it later */ if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) { /* The ReadPixels transfer is totally outside the window bounds */ @@ -396,6 +403,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + /* convert GL Y to Gallium Y */ y = strb->Base.Height - y - height; } @@ -436,7 +444,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / ((1 << 24) - 1); - pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0); + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0); y += yStep; for (j = 0; j < width; j++) { zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff)); @@ -451,7 +459,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, assert(format == GL_DEPTH_STENCIL_EXT); for (i = 0; i < height; i++) { GLuint *zshort = (GLuint *)dst; - pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0); + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, dst, 0); y += yStep; /* Reverse into 24/8 */ for (j = 0; j < width; j++) { @@ -468,7 +476,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / ((1 << 24) - 1); - pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0); + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0); y += yStep; for (j = 0; j < width; j++) { zfloat[j] = (float) (scale * ((ztemp[j] >> 8) & 0xffffff)); @@ -482,7 +490,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* XXX: unreachable code -- should be before st_read_stencil_pixels */ assert(format == GL_DEPTH_STENCIL_EXT); for (i = 0; i < height; i++) { - pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0); + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, dst, 0); y += yStep; dst += dstStride; } @@ -493,7 +501,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLushort ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / 0xffff; - pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0); + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0); y += yStep; for (j = 0; j < width; j++) { zfloat[j] = (float) (scale * ztemp[j]); @@ -508,7 +516,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / 0xffffffff; - pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0); + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0); y += yStep; for (j = 0; j < width; j++) { zfloat[j] = (float) (scale * ztemp[j]); @@ -522,7 +530,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* RGBA format */ /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { - pipe_get_tile_rgba(trans, 0, y, width, 1, df); + pipe_get_tile_rgba(pipe, trans, 0, y, width, 1, df); y += yStep; df += dfStride; if (!dfStride) { @@ -534,7 +542,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } } - screen->tex_transfer_destroy(trans); + pipe->tex_transfer_destroy(pipe, trans); _mesa_unmap_pbo_dest(ctx, &clippedPacking); } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 92eefca2e79..3fe01c4721b 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -63,6 +63,7 @@ #include "util/u_blit.h" #include "util/u_format.h" #include "util/u_surface.h" +#include "util/u_sampler.h" #include "util/u_math.h" @@ -123,6 +124,8 @@ st_DeleteTextureObject(GLcontext *ctx, struct st_texture_object *stObj = st_texture_object(texObj); if (stObj->pt) pipe_texture_reference(&stObj->pt, NULL); + if (stObj->sampler_view) + pipe_sampler_view_reference(&stObj->sampler_view, NULL); _mesa_delete_texture_object(ctx, texObj); } @@ -312,6 +315,8 @@ guess_and_alloc_texture(struct st_context *st, depth, usage); + stObj->pipe = st->pipe; + DBG("%s - success\n", __FUNCTION__); } @@ -371,10 +376,13 @@ compress_with_blit(GLcontext * ctx, { const GLuint dstImageOffsets[1] = {0}; struct st_texture_image *stImage = st_texture_image(texImage); - struct pipe_screen *screen = ctx->st->pipe->screen; + struct pipe_context *pipe = ctx->st->pipe; + struct pipe_screen *screen = pipe->screen; gl_format mesa_format; struct pipe_texture templ; struct pipe_texture *src_tex; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; struct pipe_surface *dst_surface; struct pipe_transfer *tex_xfer; void *map; @@ -421,7 +429,7 @@ compress_with_blit(GLcontext * ctx, 0, 0, 0, /* face, level are zero */ PIPE_TRANSFER_WRITE, 0, 0, width, height); /* x, y, w, h */ - map = screen->transfer_map(screen, tex_xfer); + map = pipe->transfer_map(pipe, tex_xfer); _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, map, /* dest ptr */ @@ -433,12 +441,19 @@ compress_with_blit(GLcontext * ctx, pixels, /* source data */ unpack); /* source data packing */ - screen->transfer_unmap(screen, tex_xfer); - screen->tex_transfer_destroy(tex_xfer); + pipe->transfer_unmap(pipe, tex_xfer); + pipe->tex_transfer_destroy(pipe, tex_xfer); + + /* Create temporary sampler view */ + u_sampler_view_default_template(&view_templ, + src_tex, + src_tex->format); + src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ); + /* copy / compress image */ util_blit_pixels_tex(ctx->st->blit, - src_tex, /* pipe_texture (src) */ + src_view, /* sampler view (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ @@ -450,6 +465,7 @@ compress_with_blit(GLcontext * ctx, pipe_surface_reference(&dst_surface, NULL); pipe_texture_reference(&src_tex, NULL); + pipe_sampler_view_reference(&src_view, NULL); return GL_TRUE; } @@ -555,6 +571,7 @@ st_TexImage(GLcontext * ctx, DBG("release it\n"); pipe_texture_reference(&stObj->pt, NULL); assert(!stObj->pt); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); stObj->teximage_realloc = FALSE; } } @@ -809,8 +826,11 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - struct pipe_screen *screen = ctx->st->pipe->screen; + struct pipe_context *pipe = ctx->st->pipe; + struct pipe_screen *screen = pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); + struct st_texture_object *stObj = st_texture_object(texObj); + struct pipe_sampler_view *src_view = st_get_stobj_sampler_view(stObj); const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_surface *dst_surface; @@ -827,7 +847,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, /* blit/render/decompress */ util_blit_pixels_tex(ctx->st->blit, - stImage->pt, /* pipe_texture (src) */ + src_view, /* pipe_texture (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ @@ -848,7 +868,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, if (st_equal_formats(stImage->pt->format, format, type)) { /* memcpy */ const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); - ubyte *map = screen->transfer_map(screen, tex_xfer); + ubyte *map = pipe->transfer_map(pipe, tex_xfer); GLuint row; for (row = 0; row < height; row++) { GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, @@ -856,7 +876,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, memcpy(dest, map, bytesPerRow); map += tex_xfer->stride; } - screen->transfer_unmap(screen, tex_xfer); + pipe->transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ @@ -871,7 +891,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ - pipe_get_tile_rgba(tex_xfer, 0, row, width, 1, rgba); + pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); @@ -880,7 +900,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, _mesa_unmap_pbo_dest(ctx, &ctx->Pack); - screen->tex_transfer_destroy(tex_xfer); + pipe->tex_transfer_destroy(pipe, tex_xfer); /* destroy the temp / dest surface */ util_destroy_rgba_surface(dst_texture, dst_surface); @@ -1258,7 +1278,6 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, GLsizei width, GLsizei height) { struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_transfer *src_trans; GLvoid *texDest; enum pipe_transfer_usage transfer_usage; @@ -1311,11 +1330,11 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, /* To avoid a large temp memory allocation, do copy row by row */ for (row = 0; row < height; row++, srcY += yStep) { uint data[MAX_WIDTH]; - pipe_get_tile_z(src_trans, 0, srcY, width, 1, data); + pipe_get_tile_z(pipe, src_trans, 0, srcY, width, 1, data); if (scaleOrBias) { _mesa_scale_and_bias_depth_uint(ctx, width, data); } - pipe_put_tile_z(stImage->transfer, 0, row, width, 1, data); + pipe_put_tile_z(pipe, stImage->transfer, 0, row, width, 1, data); } } else { @@ -1337,7 +1356,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. */ - pipe_get_tile_rgba(src_trans, 0, 0, width, height, tempSrc); + pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc); /* Store into texture memory. * Note that this does some special things such as pixel transfer @@ -1365,7 +1384,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, } st_texture_image_unmap(ctx->st, stImage); - screen->tex_transfer_destroy(src_trans); + pipe->tex_transfer_destroy(pipe, src_trans); } @@ -1594,6 +1613,7 @@ st_copy_texsubimage(GLcontext *ctx, } util_blit_pixels_writemask(ctx->st->blit, strb->surface, + st_renderbuffer_get_sampler_view(strb, pipe), srcX, srcY0, srcX + width, srcY1, dest_surface, @@ -1790,6 +1810,7 @@ st_finalize_texture(GLcontext *ctx, firstImage->pt != stObj->pt && firstImage->pt->last_level >= stObj->lastLevel) { pipe_texture_reference(&stObj->pt, firstImage->pt); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); } /* bytes per pixel block (blocks are usually 1x1) */ @@ -1809,6 +1830,7 @@ st_finalize_texture(GLcontext *ctx, stObj->pt->depth0 != firstImage->base.Depth2) { pipe_texture_reference(&stObj->pt, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER; } } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index de8beaf5e25..0885ad77c7c 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -30,9 +30,9 @@ #include "vbo/vbo.h" #include "shader/shader_api.h" #include "glapi/glapi.h" +#include "st_context.h" #include "st_public.h" #include "st_debug.h" -#include "st_context.h" #include "st_cb_accum.h" #include "st_cb_bitmap.h" #include "st_cb_blit.h" @@ -141,6 +141,14 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) for (i = 0; i < PIPE_MAX_SAMPLERS; i++) st->state.sampler_list[i] = &st->state.samplers[i]; + for (i = 0; i < 3; i++) { + memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element)); + st->velems_util_draw[i].src_offset = i * 4 * sizeof(float); + st->velems_util_draw[i].instance_divisor = 0; + st->velems_util_draw[i].vertex_buffer_index = 0; + st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + /* we want all vertex data to be placed in buffer objects */ vbo_use_buffer_objects(ctx); @@ -207,8 +215,8 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_drawtex(st); #endif - for (i = 0; i < Elements(st->state.sampler_texture); i++) { - pipe_texture_reference(&st->state.sampler_texture[i], NULL); + for (i = 0; i < Elements(st->state.sampler_views); i++) { + pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); } for (i = 0; i < Elements(st->state.constants); i++) { @@ -264,7 +272,8 @@ void st_destroy_context( struct st_context *st ) GLboolean st_make_current(struct st_context *st, struct st_framebuffer *draw, - struct st_framebuffer *read) + struct st_framebuffer *read, + void *winsys_drawable_handle ) { /* Call this periodically to detect when the user has begun using * GL rendering from multiple threads. @@ -272,10 +281,13 @@ st_make_current(struct st_context *st, _glapi_check_multithread(); if (st) { - if (!_mesa_make_current(st->ctx, &draw->Base, &read->Base)) + if (!_mesa_make_current(st->ctx, &draw->Base, &read->Base)) { + st->pipe->priv = NULL; return GL_FALSE; + } _mesa_check_init_viewport(st->ctx, draw->InitWidth, draw->InitHeight); + st->winsys_drawable_handle = winsys_drawable_handle; return GL_TRUE; } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 045c029c305..786beaec08b 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -31,6 +31,7 @@ #include "main/mtypes.h" #include "shader/prog_cache.h" #include "pipe/p_state.h" +#include "state_tracker/st_api.h" struct st_context; @@ -73,6 +74,8 @@ struct st_tracked_state { struct st_context { + struct st_context_iface iface; + GLcontext *ctx; struct pipe_context *pipe; @@ -94,7 +97,7 @@ struct st_context struct pipe_clip_state clip; struct pipe_buffer *constants[2]; struct pipe_framebuffer_state framebuffer; - struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_scissor_state scissor; struct pipe_viewport_state viewport; @@ -141,6 +144,7 @@ struct st_context struct st_fragment_program *combined_prog; GLuint combined_prog_sn; struct pipe_texture *pixelmap_texture; + struct pipe_sampler_view *pixelmap_sampler_view; boolean pixelmap_enabled; /**< use the pixelmap texture? */ } pixel_xfer; @@ -174,6 +178,9 @@ struct st_context unsigned vbuf_slot; } clear; + /** used for anything using util_draw_vertex_buffer */ + struct pipe_vertex_element velems_util_draw[3]; + void *passthrough_fs; /**< simple pass-through frag shader */ struct gen_mipmap_state *gen_mipmap; @@ -182,6 +189,7 @@ struct st_context struct cso_context *cso_context; int force_msaa; + void *winsys_drawable_handle; }; @@ -202,6 +210,11 @@ struct st_framebuffer GLframebuffer Base; void *Private; GLuint InitWidth, InitHeight; + + struct st_framebuffer_iface *iface; + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned num_statts; + int32_t revalidate; }; diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 32b9a473cfc..7f45e3f5484 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -57,6 +57,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_format.h" +#include "cso_cache/cso_context.h" static GLuint double_types[4] = { @@ -183,7 +184,7 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, /* this is an odd-ball case */ assert(type == GL_UNSIGNED_BYTE); assert(normalized); - return PIPE_FORMAT_A8R8G8B8_UNORM; + return PIPE_FORMAT_B8G8R8A8_UNORM; } if (normalized) { @@ -272,7 +273,8 @@ is_interleaved_arrays(const struct st_vertex_program *vp, } *userSpace = (num_client_arrays == vpv->num_inputs); - /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */ + /* debug_printf("user space: %s (%d arrays, %d inputs)\n", + (int)*userSpace ? "Yes" : "No", num_client_arrays, vp->num_inputs); */ return GL_TRUE; } @@ -292,6 +294,8 @@ get_arrays_bounds(const struct st_vertex_program *vp, const GLubyte *high_addr = NULL; GLuint attr; + /* debug_printf("get_arrays_bounds: Handling %u attrs\n", vpv->num_inputs); */ + for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; const GLint stride = arrays[mesaAttr]->StrideB; @@ -300,6 +304,9 @@ get_arrays_bounds(const struct st_vertex_program *vp, _mesa_sizeof_type(arrays[mesaAttr]->Type)); const GLubyte *end = start + (max_index * stride) + sz; + /* debug_printf("attr %u: stride %d size %u start %p end %p\n", + attr, stride, sz, start, end); */ + if (attr == 0) { low_addr = start; high_addr = end; @@ -347,7 +354,8 @@ setup_interleaved_attribs(GLcontext *ctx, const GLubyte *low, *high; get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high); - /*printf("buffer range: %p %p %d\n", low, high, high-low);*/ + /* debug_printf("buffer range: %p %p range %d max index %u\n", + low, high, high - low, max_index); */ offset0 = low; if (userSpace) { @@ -368,7 +376,6 @@ setup_interleaved_attribs(GLcontext *ctx, (unsigned) (arrays[mesaAttr]->Ptr - offset0); velements[attr].instance_divisor = 0; velements[attr].vertex_buffer_index = 0; - velements[attr].nr_components = arrays[mesaAttr]->Size; velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, arrays[mesaAttr]->Size, @@ -458,7 +465,6 @@ setup_non_interleaved_attribs(GLcontext *ctx, vbuffer[attr].max_index = max_index; velements[attr].instance_divisor = 0; velements[attr].vertex_buffer_index = attr; - velements[attr].nr_components = arrays[mesaAttr]->Size; velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, arrays[mesaAttr]->Size, @@ -564,6 +570,7 @@ st_draw_vbo(GLcontext *ctx, (void) check_uniforms; #endif + memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); /* * Setup the vbuffer[] and velements[] arrays. */ @@ -596,14 +603,13 @@ st_draw_vbo(GLcontext *ctx, for (i = 0; i < num_velements; i++) { printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); - printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components); printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format)); } } #endif pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); - pipe->set_vertex_elements(pipe, num_velements, velements); + cso_set_vertex_elements(ctx->st->cso_context, num_velements, velements); if (num_vbuffers == 0 || num_velements == 0) return; diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 087f2f22bbf..26a5b3fcd63 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -178,7 +178,6 @@ st_feedback_draw_vbo(GLcontext *ctx, vbuffers[attr].max_index = max_index; velements[attr].instance_divisor = 0; velements[attr].vertex_buffer_index = attr; - velements[attr].nr_components = arrays[mesaAttr]->Size; velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, arrays[mesaAttr]->Size, diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 79be833768f..290ee36b0fe 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -137,6 +137,9 @@ void st_init_limits(struct st_context *st) /* XXX separate query for early function return? */ st->ctx->Shader.EmitContReturn = screen->get_param(screen, PIPE_CAP_TGSI_CONT_SUPPORTED); + + /* Quads always follow GL provoking rules. */ + c->QuadsFollowProvokingVertexConvention = GL_FALSE; } @@ -169,6 +172,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_vertex_array_object = GL_TRUE; ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE; ctx->Extensions.ARB_vertex_program = GL_TRUE; + ctx->Extensions.ARB_window_pos = GL_TRUE; ctx->Extensions.EXT_blend_color = GL_TRUE; ctx->Extensions.EXT_blend_func_separate = GL_TRUE; @@ -193,9 +197,17 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.APPLE_vertex_array_object = GL_TRUE; + ctx->Extensions.MESA_pack_invert = GL_TRUE; + ctx->Extensions.NV_blend_square = GL_TRUE; ctx->Extensions.NV_texgen_reflection = GL_TRUE; ctx->Extensions.NV_texture_env_combine4 = GL_TRUE; + ctx->Extensions.NV_texture_rectangle = GL_TRUE; +#if 0 + /* possibly could support the following two */ + ctx->Extensions.NV_vertex_program = GL_TRUE; + ctx->Extensions.NV_vertex_program1_1 = GL_TRUE; +#endif #if FEATURE_OES_draw_texture ctx->Extensions.OES_draw_texture = GL_TRUE; @@ -233,7 +245,6 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; - ctx->Extensions.NV_texture_rectangle = GL_TRUE; } if (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS) > 1) { diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index 0a91183f89d..d3c43bbc68a 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -197,6 +197,7 @@ st_set_framebuffer_surface(struct st_framebuffer *stfb, /* replace the renderbuffer's surface/texture pointers */ pipe_surface_reference( &strb->surface, surf ); pipe_texture_reference( &strb->texture, surf->texture ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); if (ctx) { /* If ctx isn't set, we've likely not made current yet. diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index f67d7b4cb5c..030b0a0f065 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -79,22 +79,23 @@ st_destroy_generate_mipmap(struct st_context *st) static boolean st_render_mipmap(struct st_context *st, GLenum target, - struct pipe_texture *pt, + struct st_texture_object *stObj, uint baseLevel, uint lastLevel) { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; + struct pipe_sampler_view *psv = st_get_stobj_sampler_view(stObj); const uint face = _mesa_tex_target_to_face(target); assert(target != GL_TEXTURE_3D); /* not done yet */ /* check if we can render in the texture's format */ - if (!screen->is_format_supported(screen, pt->format, pt->target, + if (!screen->is_format_supported(screen, psv->format, psv->texture->target, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { return FALSE; } - util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel, + util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel, PIPE_TEX_FILTER_LINEAR); return TRUE; @@ -106,7 +107,6 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt = st_get_texobj_texture(texObj); const uint baseLevel = texObj->BaseLevel; const uint lastLevel = pt->last_level; @@ -142,8 +142,8 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, u_minify(pt->width0, dstLevel), u_minify(pt->height0, dstLevel)); - srcData = (ubyte *) screen->transfer_map(screen, srcTrans); - dstData = (ubyte *) screen->transfer_map(screen, dstTrans); + srcData = (ubyte *) pipe->transfer_map(pipe, srcTrans); + dstData = (ubyte *) pipe->transfer_map(pipe, dstTrans); srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->texture->format); dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->texture->format); @@ -161,11 +161,11 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, dstData, dstStride); /* stride in texels */ - screen->transfer_unmap(screen, srcTrans); - screen->transfer_unmap(screen, dstTrans); + pipe->transfer_unmap(pipe, srcTrans); + pipe->transfer_unmap(pipe, dstTrans); - screen->tex_transfer_destroy(srcTrans); - screen->tex_transfer_destroy(dstTrans); + pipe->tex_transfer_destroy(pipe, srcTrans); + pipe->tex_transfer_destroy(pipe, dstTrans); } } @@ -212,6 +212,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { struct st_context *st = ctx->st; + struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_texture *pt = st_get_texobj_texture(texObj); const uint baseLevel = texObj->BaseLevel; uint lastLevel; @@ -230,7 +231,6 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* The current gallium texture doesn't have space for all the * mipmap levels we need to generate. So allocate a new texture. */ - struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_texture *oldTex = stObj->pt; GLboolean needFlush; @@ -256,6 +256,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* release the old tex (will likely be freed too) */ pipe_texture_reference(&oldTex, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); pt = stObj->pt; } @@ -265,7 +266,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* Recall that the Mesa BaseLevel image is stored in the gallium * texture's level[0] position. So pass baseLevel=0 here. */ - if (!st_render_mipmap(st, target, pt, 0, lastLevel)) { + if (!st_render_mipmap(st, target, stObj, 0, lastLevel)) { fallback_generate_mipmap(ctx, target, texObj); } diff --git a/src/mesa/state_tracker/st_inlines.h b/src/mesa/state_tracker/st_inlines.h index e105870bc75..7fcde7b1a96 100644 --- a/src/mesa/state_tracker/st_inlines.h +++ b/src/mesa/state_tracker/st_inlines.h @@ -53,11 +53,11 @@ st_cond_flush_get_tex_transfer(struct st_context *st, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *context = st->pipe; st_teximage_flush_before_map(st, pt, face, level, usage); - return screen->get_tex_transfer(screen, pt, face, level, zslice, usage, - x, y, w, h); + return context->get_tex_transfer(context, pt, face, level, zslice, usage, + x, y, w, h); } static INLINE struct pipe_transfer * @@ -70,9 +70,9 @@ st_no_flush_get_tex_transfer(struct st_context *st, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *context = st->pipe; - return screen->get_tex_transfer(screen, pt, face, level, + return context->get_tex_transfer(context, pt, face, level, zslice, usage, x, y, w, h); } diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c new file mode 100644 index 00000000000..1b005c1ee17 --- /dev/null +++ b/src/mesa/state_tracker/st_manager.c @@ -0,0 +1,799 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "state_tracker/st_api.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_format.h" +#include "util/u_pointer.h" +#include "util/u_inlines.h" +#include "util/u_atomic.h" + +#include "main/mtypes.h" +#include "main/context.h" +#include "main/texobj.h" +#include "main/teximage.h" +#include "main/texstate.h" +#include "main/texfetch.h" +#include "main/fbobject.h" +#include "main/framebuffer.h" +#include "main/renderbuffer.h" +#include "st_texture.h" + +#include "st_context.h" +#include "st_format.h" +#include "st_cb_fbo.h" +#include "st_manager.h" + +/* these functions are defined in st_context.c */ +struct st_context * +st_create_context(struct pipe_context *pipe, + const __GLcontextModes *visual, + struct st_context *share); +void st_destroy_context(struct st_context *st); +void st_flush(struct st_context *st, uint pipeFlushFlags, + struct pipe_fence_handle **fence); + +/** + * Note that this function may fail. + */ +static INLINE struct st_framebuffer * +st_framebuffer(GLframebuffer *fb) +{ + /* FBO cannot be casted. See st_new_framebuffer */ + return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL); +} + +/** + * Map an attachment to a buffer index. + */ +static INLINE gl_buffer_index +attachment_to_buffer_index(enum st_attachment_type statt) +{ + gl_buffer_index index; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + index = BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + index = BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + index = BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + index = BUFFER_BACK_RIGHT; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + index = BUFFER_DEPTH; + break; + case ST_ATTACHMENT_ACCUM: + index = BUFFER_ACCUM; + break; + case ST_ATTACHMENT_SAMPLE: + default: + index = BUFFER_COUNT; + break; + } + + return index; +} + +/** + * Map a buffer index to an attachment. + */ +static INLINE enum st_attachment_type +buffer_index_to_attachment(gl_buffer_index index) +{ + enum st_attachment_type statt; + + switch (index) { + case BUFFER_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + case BUFFER_FRONT_RIGHT: + statt = ST_ATTACHMENT_FRONT_RIGHT; + break; + case BUFFER_BACK_RIGHT: + statt = ST_ATTACHMENT_BACK_RIGHT; + break; + case BUFFER_DEPTH: + statt = ST_ATTACHMENT_DEPTH_STENCIL; + break; + case BUFFER_ACCUM: + statt = ST_ATTACHMENT_ACCUM; + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + return statt; +} + +/** + * Validate a framebuffer to make sure up-to-date pipe_textures are used. + */ +static void +st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) +{ + struct pipe_screen *screen = st->pipe->screen; + struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; + uint width, height; + unsigned i; + boolean changed = FALSE; + + if (!p_atomic_read(&stfb->revalidate)) + return; + + /* validate the fb */ + if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures)) + return; + + width = stfb->Base.Width; + height = stfb->Base.Height; + + for (i = 0; i < stfb->num_statts; i++) { + struct st_renderbuffer *strb; + struct pipe_surface *ps; + gl_buffer_index idx; + + if (!textures[i]) + continue; + + idx = attachment_to_buffer_index(stfb->statts[i]); + if (idx >= BUFFER_COUNT) { + pipe_texture_reference(&textures[i], NULL); + continue; + } + + strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); + assert(strb); + if (strb->texture == textures[i]) { + pipe_texture_reference(&textures[i], NULL); + continue; + } + + ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); + if (ps) { + pipe_surface_reference(&strb->surface, ps); + pipe_texture_reference(&strb->texture, ps->texture); + /* ownership transfered */ + pipe_surface_reference(&ps, NULL); + + changed = TRUE; + + strb->Base.Width = strb->surface->width; + strb->Base.Height = strb->surface->height; + + width = strb->Base.Width; + height = strb->Base.Height; + } + + pipe_texture_reference(&textures[i], NULL); + } + + if (changed) { + st->dirty.st |= ST_NEW_FRAMEBUFFER; + _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height); + + assert(stfb->Base.Width == width); + assert(stfb->Base.Height == height); + } + + p_atomic_set(&stfb->revalidate, FALSE); +} + +/** + * Update the attachments to validate by looping the existing renderbuffers. + */ +static void +st_framebuffer_update_attachments(struct st_framebuffer *stfb) +{ + gl_buffer_index idx; + + stfb->num_statts = 0; + for (idx = 0; idx < BUFFER_COUNT; idx++) { + struct st_renderbuffer *strb; + enum st_attachment_type statt; + + strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); + if (!strb || strb->software) + continue; + + statt = buffer_index_to_attachment(idx); + if (statt != ST_ATTACHMENT_INVALID && + st_visual_have_buffers(stfb->iface->visual, 1 << statt)) + stfb->statts[stfb->num_statts++] = statt; + } + + p_atomic_set(&stfb->revalidate, TRUE); +} + +/** + * Add a renderbuffer to the framebuffer. + */ +static boolean +st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, + gl_buffer_index idx) +{ + struct gl_renderbuffer *rb; + enum pipe_format format; + int samples; + boolean sw; + + /* do not distinguish depth/stencil buffers */ + if (idx == BUFFER_STENCIL) + idx = BUFFER_DEPTH; + + switch (idx) { + case BUFFER_DEPTH: + format = stfb->iface->visual->depth_stencil_format; + sw = FALSE; + break; + case BUFFER_ACCUM: + format = stfb->iface->visual->accum_format; + sw = TRUE; + break; + default: + format = stfb->iface->visual->color_format; + sw = FALSE; + break; + } + + if (format == PIPE_FORMAT_NONE) + return FALSE; + + samples = stfb->iface->visual->samples; + if (!samples) + samples = st_get_msaa(); + + rb = st_new_renderbuffer_fb(format, samples, sw); + if (!rb) + return FALSE; + + if (idx != BUFFER_DEPTH) { + _mesa_add_renderbuffer(&stfb->Base, idx, rb); + } + else { + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) + _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb); + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) + _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb); + } + + return TRUE; +} + +/** + * Intialize a __GLcontextModes from a visual. + */ +static void +st_visual_to_context_mode(const struct st_visual *visual, + __GLcontextModes *mode) +{ + memset(mode, 0, sizeof(*mode)); + + if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK)) + mode->doubleBufferMode = GL_TRUE; + if (st_visual_have_buffers(visual, + ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK)) + mode->stereoMode = GL_TRUE; + + if (visual->color_format != PIPE_FORMAT_NONE) { + mode->rgbMode = GL_TRUE; + + mode->redBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + mode->greenBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 1); + mode->blueBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 2); + mode->alphaBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 3); + + mode->rgbBits = mode->redBits + + mode->greenBits + mode->blueBits + mode->alphaBits; + } + + if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { + mode->haveDepthBuffer = GL_TRUE; + mode->haveStencilBuffer = GL_TRUE; + + mode->depthBits = + util_format_get_component_bits(visual->depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, 0); + mode->stencilBits = + util_format_get_component_bits(visual->depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, 1); + } + + if (visual->accum_format != PIPE_FORMAT_NONE) { + mode->haveAccumBuffer = GL_TRUE; + + mode->accumRedBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + mode->accumGreenBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 1); + mode->accumBlueBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 2); + mode->accumAlphaBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 3); + } + + if (visual->samples) { + mode->sampleBuffers = 1; + mode->samples = visual->samples; + } +} + +/** + * Determine the default draw or read buffer from a visual. + */ +static void +st_visual_to_default_buffer(const struct st_visual *visual, + GLenum *buffer, GLint *index) +{ + enum st_attachment_type statt; + GLenum buf; + gl_buffer_index idx; + + statt = visual->render_buffer; + /* do nothing if an invalid render buffer is specified */ + if (statt == ST_ATTACHMENT_INVALID || + !st_visual_have_buffers(visual, 1 << statt)) + return; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + buf = GL_FRONT_LEFT; + idx = BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + buf = GL_BACK_LEFT; + idx = BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + buf = GL_FRONT_RIGHT; + idx = BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + buf = GL_BACK_RIGHT; + idx = BUFFER_BACK_RIGHT; + break; + default: + buf = GL_NONE; + idx = BUFFER_COUNT; + break; + } + + if (buf != GL_NONE) { + if (buffer) + *buffer = buf; + if (index) + *index = idx; + } +} + +/** + * Create a framebuffer from a manager interface. + */ +static struct st_framebuffer * +st_framebuffer_create(struct st_framebuffer_iface *stfbi) +{ + struct st_framebuffer *stfb; + __GLcontextModes mode; + gl_buffer_index idx; + + stfb = CALLOC_STRUCT(st_framebuffer); + if (!stfb) + return NULL; + + st_visual_to_context_mode(stfbi->visual, &mode); + _mesa_initialize_window_framebuffer(&stfb->Base, &mode); + + /* modify the draw/read buffers of the fb */ + st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0], + &stfb->Base._ColorDrawBufferIndexes[0]); + st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer, + &stfb->Base._ColorReadBufferIndex); + + stfb->iface = stfbi; + + /* add the color buffer */ + idx = stfb->Base._ColorDrawBufferIndexes[0]; + if (!st_framebuffer_add_renderbuffer(stfb, idx)) { + FREE(stfb); + return NULL; + } + + st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH); + st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM); + + st_framebuffer_update_attachments(stfb); + + stfb->Base.Initialized = GL_TRUE; + + return stfb; +} + +/** + * Reference a framebuffer. + */ +static void +st_framebuffer_reference(struct st_framebuffer **ptr, + struct st_framebuffer *stfb) +{ + GLframebuffer *fb = &stfb->Base; + _mesa_reference_framebuffer((GLframebuffer **) ptr, fb); +} + +static void +st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi) +{ + struct st_context *st = (struct st_context *) stctxi; + struct st_framebuffer *stfb; + + /* either draw or read winsys fb */ + stfb = st_framebuffer(st->ctx->WinSysDrawBuffer); + if (!stfb || stfb->iface != stfbi) + stfb = st_framebuffer(st->ctx->WinSysReadBuffer); + assert(stfb && stfb->iface == stfbi); + + p_atomic_set(&stfb->revalidate, TRUE); +} + +static void +st_context_flush(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct st_context *st = (struct st_context *) stctxi; + st_flush(st, flags, fence); + if (flags & PIPE_FLUSH_RENDER_CACHE) + st_manager_flush_frontbuffer(st); +} + +static boolean +st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target, + int level, enum pipe_format internal_format, + struct pipe_texture *tex, boolean mipmap) +{ + struct st_context *st = (struct st_context *) stctxi; + GLcontext *ctx = st->ctx; + struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + struct st_texture_object *stObj; + struct st_texture_image *stImage; + GLenum internalFormat; + + switch (target) { + case ST_TEXTURE_1D: + target = GL_TEXTURE_1D; + break; + case ST_TEXTURE_2D: + target = GL_TEXTURE_2D; + break; + case ST_TEXTURE_3D: + target = GL_TEXTURE_3D; + break; + case ST_TEXTURE_RECT: + target = GL_TEXTURE_RECTANGLE_ARB; + break; + default: + return FALSE; + break; + } + + if (util_format_get_component_bits(internal_format, + UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) + internalFormat = GL_RGBA; + else + internalFormat = GL_RGB; + + texObj = _mesa_select_tex_object(ctx, texUnit, target); + _mesa_lock_texture(ctx, texObj); + + stObj = st_texture_object(texObj); + /* switch to surface based */ + if (!stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_TRUE; + } + + texImage = _mesa_get_tex_image(ctx, texObj, target, level); + stImage = st_texture_image(texImage); + if (tex) { + _mesa_init_teximage_fields(ctx, target, texImage, + tex->width0, tex->height0, 1, 0, internalFormat); + texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, + GL_RGBA, GL_UNSIGNED_BYTE); + _mesa_set_fetch_functions(texImage, 2); + } + else { + _mesa_clear_texture_image(ctx, texImage); + } + + pipe_texture_reference(&stImage->pt, tex); + + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_unlock_texture(ctx, texObj); + + return TRUE; +} + +static void +st_context_destroy(struct st_context_iface *stctxi) +{ + struct st_context *st = (struct st_context *) stctxi; + st_destroy_context(st); +} + +static struct st_context_iface * +st_api_create_context(struct st_api *stapi, struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *shared_stctxi) +{ + struct st_context *shared_ctx = (struct st_context *) shared_stctxi; + struct st_context *st; + struct pipe_context *pipe; + __GLcontextModes mode; + + pipe = smapi->screen->context_create(smapi->screen, NULL); + if (!pipe) + return NULL; + + st_visual_to_context_mode(visual, &mode); + st = st_create_context(pipe, &mode, shared_ctx); + if (!st) { + pipe->destroy(pipe); + return NULL; + } + + st->iface.destroy = st_context_destroy; + + st->iface.notify_invalid_framebuffer = + st_context_notify_invalid_framebuffer; + st->iface.flush = st_context_flush; + + st->iface.teximage = st_context_teximage; + st->iface.copy = NULL; + + st->iface.st_context_private = (void *) smapi; + + return &st->iface; +} + +static boolean +st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct st_context *st = (struct st_context *) stctxi; + struct st_framebuffer *stdraw, *stread, *stfb; + boolean ret; + + _glapi_check_multithread(); + + if (st) { + /* reuse/create the draw fb */ + stfb = st_framebuffer(st->ctx->WinSysDrawBuffer); + if (stfb && stfb->iface == stdrawi) { + stdraw = NULL; + st_framebuffer_reference(&stdraw, stfb); + } + else { + stdraw = st_framebuffer_create(stdrawi); + } + + /* reuse/create the read fb */ + stfb = st_framebuffer(st->ctx->WinSysReadBuffer); + if (!stfb || stfb->iface != streadi) + stfb = stdraw; + if (stfb && stfb->iface == streadi) { + stread = NULL; + st_framebuffer_reference(&stread, stfb); + } + else { + stread = st_framebuffer_create(streadi); + } + + if (stdraw && stread) { + st_framebuffer_validate(stdraw, st); + if (stread != stdraw) + st_framebuffer_validate(stread, st); + + /* modify the draw/read buffers of the context */ + st_visual_to_default_buffer(stdraw->iface->visual, + &st->ctx->Color.DrawBuffer[0], NULL); + st_visual_to_default_buffer(stread->iface->visual, + &st->ctx->Pixel.ReadBuffer, NULL); + + ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); + } + else { + ret = FALSE; + } + + st_framebuffer_reference(&stdraw, NULL); + st_framebuffer_reference(&stread, NULL); + } + else { + ret = _mesa_make_current(NULL, NULL, NULL); + } + + return ret; +} + +static struct st_context_iface * +st_api_get_current(struct st_api *stapi) +{ + GET_CURRENT_CONTEXT(ctx); + struct st_context *st = (ctx) ? ctx->st : NULL; + + return (st) ? &st->iface : NULL; +} + +static boolean +st_api_is_visual_supported(struct st_api *stapi, + const struct st_visual *visual) +{ + return TRUE; +} + +static st_proc_t +st_api_get_proc_address(struct st_api *stapi, const char *procname) +{ + return (st_proc_t) _glapi_get_proc_address(procname); +} + +static void +st_api_destroy(struct st_api *stapi) +{ + FREE(stapi); +} + +/** + * Flush the front buffer if the current context renders to the front buffer. + */ +void +st_manager_flush_frontbuffer(struct st_context *st) +{ + struct st_framebuffer *stfb = st_framebuffer(st->ctx->DrawBuffer); + struct st_renderbuffer *strb = NULL; + + if (stfb) + strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + if (!strb) + return; + + /* st_public.h */ + if (!stfb->iface) { + struct pipe_surface *front_surf = strb->surface; + st->pipe->screen->flush_frontbuffer(st->pipe->screen, + front_surf, st->winsys_drawable_handle); + return; + } + + stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT); +} + +/** + * Re-validate the framebuffers. + */ +void +st_manager_validate_framebuffers(struct st_context *st) +{ + struct st_framebuffer *stdraw = st_framebuffer(st->ctx->DrawBuffer); + struct st_framebuffer *stread = st_framebuffer(st->ctx->ReadBuffer); + + /* st_public.h */ + if ((stdraw && !stdraw->iface) || (stread && !stread->iface)) { + struct pipe_screen *screen = st->pipe->screen; + if (screen->update_buffer) + screen->update_buffer(screen, st->pipe->priv); + return; + } + + if (stdraw) + st_framebuffer_validate(stdraw, st); + if (stread && stread != stdraw) + st_framebuffer_validate(stread, st); +} + +/** + * Add a color renderbuffer on demand. + */ +boolean +st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, + gl_buffer_index idx) +{ + struct st_framebuffer *stfb = st_framebuffer(fb); + + /* FBO or st_public.h */ + if (!stfb || !stfb->iface) + return FALSE; + + if (stfb->Base.Attachment[idx].Renderbuffer) + return TRUE; + + switch (idx) { + case BUFFER_FRONT_LEFT: + case BUFFER_BACK_LEFT: + case BUFFER_FRONT_RIGHT: + case BUFFER_BACK_RIGHT: + break; + default: + return FALSE; + break; + } + + if (!st_framebuffer_add_renderbuffer(stfb, idx)) + return FALSE; + + st_framebuffer_update_attachments(stfb); + st_invalidate_state(st->ctx, _NEW_BUFFERS); + + return TRUE; +} + +/** + * Create an st_api to manage the state tracker. + */ +struct st_api * +st_manager_create_api(void) +{ + struct st_api *stapi; + + stapi = CALLOC_STRUCT(st_api); + if (stapi) { + stapi->destroy = st_api_destroy; + stapi->get_proc_address = st_api_get_proc_address; + stapi->is_visual_supported = st_api_is_visual_supported; + + stapi->create_context = st_api_create_context; + stapi->make_current = st_api_make_current; + stapi->get_current = st_api_get_current; + } + + return stapi; +} diff --git a/src/mesa/state_tracker/st_manager.h b/src/mesa/state_tracker/st_manager.h new file mode 100644 index 00000000000..a3f51992237 --- /dev/null +++ b/src/mesa/state_tracker/st_manager.h @@ -0,0 +1,47 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef ST_MANAGER_H +#define ST_MANAGER_H + +#include "state_tracker/st_api.h" +#include "st_context.h" + +void +st_manager_flush_frontbuffer(struct st_context *st); + +void +st_manager_validate_framebuffers(struct st_context *st); + +boolean +st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, + gl_buffer_index idx); + +struct st_api * +st_manager_create_api(void); + +#endif /* ST_MANAGER_H */ diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h index 0824356cecc..4b40d6d0448 100644 --- a/src/mesa/state_tracker/st_public.h +++ b/src/mesa/state_tracker/st_public.h @@ -105,7 +105,8 @@ void st_unreference_framebuffer( struct st_framebuffer *stfb ); PUBLIC GLboolean st_make_current(struct st_context *st, struct st_framebuffer *draw, - struct st_framebuffer *read); + struct st_framebuffer *read, + void *winsys_drawable_handle); PUBLIC struct st_context *st_get_current(void); diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 5a45c4358a9..ef97d873e50 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -192,7 +192,6 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, GLuint x, GLuint y, GLuint w, GLuint h) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt = stImage->pt; DBG("%s \n", __FUNCTION__); @@ -202,7 +201,7 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, usage, x, y, w, h); if (stImage->transfer) - return screen->transfer_map(screen, stImage->transfer); + return pipe->transfer_map(pipe, stImage->transfer); else return NULL; } @@ -212,13 +211,13 @@ void st_texture_image_unmap(struct st_context *st, struct st_texture_image *stImage) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *pipe = st->pipe; DBG("%s\n", __FUNCTION__); - screen->transfer_unmap(screen, stImage->transfer); + pipe->transfer_unmap(pipe, stImage->transfer); - screen->tex_transfer_destroy(stImage->transfer); + pipe->tex_transfer_destroy(pipe, stImage->transfer); } @@ -238,8 +237,7 @@ st_surface_data(struct pipe_context *pipe, const void *src, unsigned src_stride, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { - struct pipe_screen *screen = pipe->screen; - void *map = screen->transfer_map(screen, dst); + void *map = pipe->transfer_map(pipe, dst); assert(dst->texture); util_copy_rect(map, @@ -250,7 +248,7 @@ st_surface_data(struct pipe_context *pipe, src, src_stride, srcx, srcy); - screen->transfer_unmap(screen, dst); + pipe->transfer_unmap(pipe, dst); } @@ -265,7 +263,6 @@ st_texture_image_data(struct st_context *st, GLuint src_row_stride, GLuint src_image_stride) { struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; GLuint depth = u_minify(dst->depth0, level); GLuint i; const GLubyte *srcUB = src; @@ -287,7 +284,7 @@ st_texture_image_data(struct st_context *st, u_minify(dst->width0, level), u_minify(dst->height0, level)); /* width, height */ - screen->tex_transfer_destroy(dst_transfer); + pipe->tex_transfer_destroy(pipe, dst_transfer); srcUB += src_image_stride; } @@ -531,14 +528,21 @@ st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex, /* save the renderbuffer's surface/texture info */ pipe_texture_reference(&strb->texture_save, strb->texture); pipe_surface_reference(&strb->surface_save, strb->surface); + pipe_sampler_view_reference(&strb->sampler_view_save, strb->sampler_view); /* plug in new surface/texture info */ pipe_texture_reference(&strb->texture, stImage->pt); + + /* XXX: Shouldn't we release reference to old surface here? + */ + strb->surface = screen->get_tex_surface(screen, strb->texture, face, level, slice, (PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE)); + pipe_sampler_view_reference(&strb->sampler_view, NULL); + st->dirty.st |= ST_NEW_FRAMEBUFFER; return 1; @@ -568,9 +572,11 @@ st_release_teximage(struct st_framebuffer *stfb, uint surfIndex, /* free tex surface, restore original */ pipe_surface_reference(&strb->surface, strb->surface_save); pipe_texture_reference(&strb->texture, strb->texture_save); + pipe_sampler_view_reference(&strb->sampler_view, strb->sampler_view_save); pipe_surface_reference(&strb->surface_save, NULL); pipe_texture_reference(&strb->texture_save, NULL); + pipe_sampler_view_reference(&strb->sampler_view, NULL); st->dirty.st |= ST_NEW_FRAMEBUFFER; diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index 60868ce0673..c62f7f2cc0d 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -29,6 +29,9 @@ #define ST_TEXTURE_H +#include "pipe/p_context.h" +#include "util/u_sampler.h" + #include "main/mtypes.h" struct pipe_context; @@ -68,6 +71,13 @@ struct st_texture_object */ struct pipe_texture *pt; + /* Default sampler view attached to this texture object. Created lazily + * on first binding. + */ + struct pipe_sampler_view *sampler_view; + + struct pipe_context *pipe; + GLboolean teximage_realloc; /* True if there is/was a surface bound to this texture object. It helps @@ -105,6 +115,35 @@ st_get_stobj_texture(struct st_texture_object *stObj) } +static INLINE struct pipe_sampler_view * +st_sampler_view_from_texture(struct pipe_context *pipe, + struct pipe_texture *texture) +{ + struct pipe_sampler_view templ; + + u_sampler_view_default_template(&templ, + texture, + texture->format); + + return pipe->create_sampler_view(pipe, texture, &templ); +} + + +static INLINE struct pipe_sampler_view * +st_get_stobj_sampler_view(struct st_texture_object *stObj) +{ + if (!stObj || !stObj->pt) { + return NULL; + } + + if (!stObj->sampler_view) { + stObj->sampler_view = st_sampler_view_from_texture(stObj->pipe, stObj->pt); + } + + return stObj->sampler_view; +} + + extern struct pipe_texture * st_texture_create(struct st_context *st, enum pipe_texture_target target, diff --git a/windows/VC8/mesa/mesa/mesa.vcproj b/windows/VC8/mesa/mesa/mesa.vcproj index f7c3c734466..5a5b93a7799 100644 --- a/windows/VC8/mesa/mesa/mesa.vcproj +++ b/windows/VC8/mesa/mesa/mesa.vcproj @@ -495,6 +495,10 @@ >
</File>
<File
+ RelativePath="..\..\..\..\src\mesa\glapi\glapi_entrypoint.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\..\src\mesa\glapi\glapi_getproc.c"
>
</File>
|