diff options
73 files changed, 1634 insertions, 325 deletions
@@ -181,7 +181,7 @@ ultrix-gcc: # Rules for making release tarballs -VERSION=7.5-devel +VERSION=7.6-devel DIRECTORY = Mesa-$(VERSION) LIB_NAME = MesaLib-$(VERSION) DEMO_NAME = MesaDemos-$(VERSION) diff --git a/SConstruct b/SConstruct index 1e5fd71adce..89144f7579d 100644 --- a/SConstruct +++ b/SConstruct @@ -41,16 +41,16 @@ else: default_drivers = 'all' default_winsys = 'all' -opts = Options('config.py') +opts = Variables('config.py') common.AddOptions(opts) -opts.Add(ListOption('statetrackers', 'state trackers to build', default_statetrackers, +opts.Add(ListVariable('statetrackers', 'state trackers to build', default_statetrackers, ['mesa', 'python'])) -opts.Add(ListOption('drivers', 'pipe drivers to build', default_drivers, +opts.Add(ListVariable('drivers', 'pipe drivers to build', default_drivers, ['softpipe', 'failover', 'i915simple', 'i965simple', 'cell', 'trace', 'r300'])) -opts.Add(ListOption('winsys', 'winsys drivers to build', default_winsys, +opts.Add(ListVariable('winsys', 'winsys drivers to build', default_winsys, ['xlib', 'intel', 'gdi', 'radeon'])) -opts.Add(EnumOption('MSVS_VERSION', 'MS Visual C++ version', None, allowed_values=('7.1', '8.0', '9.0'))) +opts.Add(EnumVariable('MSVS_VERSION', 'MS Visual C++ version', None, allowed_values=('7.1', '8.0', '9.0'))) env = Environment( options = opts, diff --git a/common.py b/common.py index f1c6372abde..e57429eb75e 100644 --- a/common.py +++ b/common.py @@ -46,13 +46,13 @@ else: def AddOptions(opts): try: - from SCons.Options.BoolOption import BoolOption - except ImportError: from SCons.Variables.BoolVariable import BoolVariable as BoolOption - try: - from SCons.Options.EnumOption import EnumOption except ImportError: + from SCons.Options.BoolOption import BoolOption + try: from SCons.Variables.EnumVariable import EnumVariable as EnumOption + except ImportError: + from SCons.Options.EnumOption import EnumOption opts.Add(BoolOption('debug', 'debug build', 'no')) opts.Add(BoolOption('profile', 'profile build', 'no')) #opts.Add(BoolOption('quiet', 'quiet command lines', 'no')) diff --git a/configs/default b/configs/default index b5ef80afb36..9c479fccdf9 100644 --- a/configs/default +++ b/configs/default @@ -9,7 +9,7 @@ CONFIG_NAME = default # Version info MESA_MAJOR=7 -MESA_MINOR=5 +MESA_MINOR=6 MESA_TINY=0 MESA_VERSION = $(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY) diff --git a/configs/linux-x86-64-debug b/configs/linux-x86-64-debug index 46e72c990af..6f631c0e879 100644 --- a/configs/linux-x86-64-debug +++ b/configs/linux-x86-64-debug @@ -4,4 +4,5 @@ include $(TOP)/configs/linux-x86-64 CONFIG_NAME = linux-x86-64-debug +OPT_FLAGS = -g DEFINES += -DDEBUG -DDEBUG_MATH diff --git a/docs/relnotes-7.6.html b/docs/relnotes-7.6.html new file mode 100644 index 00000000000..77ce013d436 --- /dev/null +++ b/docs/relnotes-7.6.html @@ -0,0 +1,61 @@ +<HTML> + +<TITLE>Mesa Release Notes</TITLE> + +<head><link rel="stylesheet" type="text/css" href="mesa.css"></head> + +<BODY> + +<body bgcolor="#eeeeee"> + +<H1>Mesa 7.6 Release Notes / date TBD</H1> + +<p> +Mesa 7.6 is a new development release. +People who are concerned with stability and reliability should stick +with a previous release or wait for Mesa 7.6.1. +</p> +<p> +Mesa 7.6 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> +<p> +Note that the Mesa project is no longer using odd/even version numbers +to indicate development/stable releases. +The so-called development releases have been fairly stable. +If you're especially concerned with stability you should probably look for +"point" releases such as 7.5.1 which will be a bug-fix release. +</p> + + +<h2>MD5 checksums</h2> +<pre> +tbd +</pre> + + +<h2>New features</h2> +<ul> +<li><a href="openvg.html">OpenVG</a> front-end (state tracker for Gallium). +This was written by Zack Rusin at Tungsten Graphics. +</ul> + + +<h2>Bug fixes</h2> +<ul> +<li>i965 DRI driver fixes, including support for "unlimited" size constant + buffers (GLSL uniforms) +</ul> + + +<h2>Changes</h2> +<ul> +</ul> + +</body> +</html> diff --git a/docs/relnotes.html b/docs/relnotes.html index 298352038cd..936f565236d 100644 --- a/docs/relnotes.html +++ b/docs/relnotes.html @@ -20,6 +20,7 @@ The release notes summarize what's new or changed in each Mesa release. </p> <UL> +<LI><A HREF="relnotes-7.6.html">7.6 release notes</A> <LI><A HREF="relnotes-7.5.html">7.5 release notes</A> <LI><A HREF="relnotes-7.4.1.html">7.4.1 release notes</A> <LI><A HREF="relnotes-7.4.html">7.4 release notes</A> diff --git a/progs/trivial/Makefile b/progs/trivial/Makefile index 69c71cbaf61..22de83fa790 100644 --- a/progs/trivial/Makefile +++ b/progs/trivial/Makefile @@ -30,6 +30,7 @@ SOURCES = \ fs-tri.c \ line-clip.c \ line-cull.c \ + line-flat.c \ line-smooth.c \ line-stipple-wide.c \ line-userclip-clip.c \ @@ -138,6 +139,7 @@ SOURCES = \ tristrip-flat.c \ tristrip.c \ vbo-drawarrays.c \ + vbo-noninterleaved.c \ vbo-drawelements.c \ vbo-drawrange.c \ vp-array.c \ @@ -145,6 +147,7 @@ SOURCES = \ vp-clip.c \ vp-line-clip.c \ vp-tri.c \ + vp-tri-invariant.c \ vp-tri-swap.c \ vp-tri-tex.c \ vp-tri-imm.c \ diff --git a/progs/trivial/SConscript b/progs/trivial/SConscript index 480630e210e..9a1f3575bdc 100644 --- a/progs/trivial/SConscript +++ b/progs/trivial/SConscript @@ -26,6 +26,7 @@ progs = [ 'fs-tri', 'line-clip', 'line-cull', + 'line-flat', 'line-smooth', 'line-stipple-wide', 'line-userclip-clip', @@ -134,6 +135,7 @@ progs = [ 'tristrip-flat', 'tristrip', 'vbo-drawarrays', + 'vbo-noninterleaved', 'vbo-drawelements', 'vbo-drawrange', 'vp-array', @@ -141,6 +143,7 @@ progs = [ 'vp-clip', 'vp-line-clip', 'vp-tri', + 'vp-tri-invariant', 'vp-tri-swap', 'vp-tri-tex', 'vp-tri-imm', diff --git a/progs/trivial/line-flat.c b/progs/trivial/line-flat.c new file mode 100644 index 00000000000..14f0ac07825 --- /dev/null +++ b/progs/trivial/line-flat.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the name of + * Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF + * ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <GL/glut.h> + + +#define CI_OFFSET_1 16 +#define CI_OFFSET_2 32 + + +GLenum doubleBuffer; + +static void Init(void) +{ + 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); + + glClearColor(0.0, 0.0, 1.0, 0.0); +} + +static void Reshape(int width, int height) +{ + + glViewport(0, 0, (GLint)width, (GLint)height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0); + glMatrixMode(GL_MODELVIEW); +} + +static void Key(unsigned char key, int x, int y) +{ + + switch (key) { + case 27: + exit(1); + default: + return; + } + + glutPostRedisplay(); +} + +static void Draw(void) +{ + glClear(GL_COLOR_BUFFER_BIT); + glShadeModel(GL_FLAT); + + glBegin(GL_LINES); + glColor3f(0,0,.7); + glVertex3f( 0.9, -0.9, -30.0); + glColor3f(.8,0,0); + glVertex3f( 0.9, 0.9, -30.0); + + glColor3f(.8,0,0); + glVertex3f( 0.9, 0.9, -30.0); + glColor3f(0,.9,0); + glVertex3f(-0.9, 0.0, -30.0); + + + glColor3f(0,.9,0); + glVertex3f(-0.9, 0.0, -30.0); + glColor3f(0,0,.7); + glVertex3f( 0.9, -0.9, -30.0); + glEnd(); + + glFlush(); + + if (doubleBuffer) { + glutSwapBuffers(); + } +} + +static GLenum Args(int argc, char **argv) +{ + GLint i; + + doubleBuffer = GL_FALSE; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-sb") == 0) { + doubleBuffer = GL_FALSE; + } else if (strcmp(argv[i], "-db") == 0) { + doubleBuffer = GL_TRUE; + } else { + fprintf(stderr, "%s (Bad option).\n", argv[i]); + return GL_FALSE; + } + } + return GL_TRUE; +} + +int main(int argc, char **argv) +{ + GLenum type; + + glutInit(&argc, argv); + + if (Args(argc, argv) == GL_FALSE) { + exit(1); + } + + glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250); + + type = GLUT_RGB; + type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; + glutInitDisplayMode(type); + + if (glutCreateWindow(*argv) == GL_FALSE) { + exit(1); + } + + Init(); + + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Draw); + glutMainLoop(); + return 0; +} diff --git a/progs/trivial/vbo-noninterleaved.c b/progs/trivial/vbo-noninterleaved.c new file mode 100644 index 00000000000..0672ca50ff1 --- /dev/null +++ b/progs/trivial/vbo-noninterleaved.c @@ -0,0 +1,139 @@ +/* Basic VBO */ + +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <GL/glew.h> +#include <GL/glut.h> + + +struct { + GLfloat pos[4][4]; + GLfloat col[4][4]; +} verts = +{ + /* Position: a quad + */ + { + { 0.9, -0.9, 0.0, 1.0 }, + { 0.9, 0.9, 0.0, 1.0 }, + { -0.9, 0.9, 0.0, 1.0 }, + { -0.9, -0.9, 0.0, 1.0 }, + }, + + /* Color: all red + */ + { + { 1.0, 0.0, 0.0, 1.0 }, + { 1.0, 0.0, 0.0, 1.0 }, + { 1.0, 0.0, 0.0, 1.0 }, + { 1.0, 0.0, 0.0, 1.0 }, + }, + + +}; + +GLuint arrayObj, elementObj; + +static void Init( void ) +{ + GLint errno; + GLuint prognum; + + static const char *prog1 = + "!!ARBvp1.0\n" + "MOV result.color, vertex.color;\n" + "MOV result.position, vertex.position;\n" + "END\n"; + + glGenProgramsARB(1, &prognum); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum); + glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(prog1), (const GLubyte *) prog1); + + assert(glIsProgramARB(prognum)); + errno = glGetError(); + printf("glGetError = %d\n", errno); + if (errno != GL_NO_ERROR) + { + GLint errorpos; + + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos); + printf("errorpos: %d\n", errorpos); + printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)); + } + + + glEnableClientState( GL_VERTEX_ARRAY ); + glEnableClientState( GL_COLOR_ARRAY ); + + glGenBuffersARB(1, &arrayObj); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, arrayObj); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), &verts, GL_STATIC_DRAW_ARB); + + glVertexPointer( 4, GL_FLOAT, sizeof(verts.pos[0]), 0 ); + glColorPointer( 4, GL_FLOAT, sizeof(verts.col[0]), (void *)(4*4*sizeof(float)) ); + +} + + + +static void Display( void ) +{ + glClearColor(0.3, 0.3, 0.3, 1); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glEnable(GL_VERTEX_PROGRAM_ARB); + +// glDrawArrays( GL_TRIANGLES, 0, 3 ); +// glDrawArrays( GL_TRIANGLES, 1, 3 ); + glDrawArrays( GL_QUADS, 0, 4 ); + + glFlush(); +} + + +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, -0.5, 1000.0); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + /*glTranslatef( 0.0, 0.0, -15.0 );*/ +} + + +static void Key( unsigned char key, int x, int y ) +{ + (void) x; + (void) y; + switch (key) { + case 27: + exit(0); + break; + } + glutPostRedisplay(); +} + + + + +int main( int argc, char *argv[] ) +{ + glutInit( &argc, argv ); + glutInitWindowPosition( 0, 0 ); + glutInitWindowSize( 250, 250 ); + glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH ); + glutCreateWindow(argv[0]); + glewInit(); + glutReshapeFunc( Reshape ); + glutKeyboardFunc( Key ); + glutDisplayFunc( Display ); + Init(); + glutMainLoop(); + return 0; +} diff --git a/progs/trivial/vp-tri-invariant.c b/progs/trivial/vp-tri-invariant.c new file mode 100644 index 00000000000..ff241393659 --- /dev/null +++ b/progs/trivial/vp-tri-invariant.c @@ -0,0 +1,147 @@ +/* Test glGenProgramsNV(), glIsProgramNV(), glLoadProgramNV() */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include <GL/glew.h> +#include <GL/glut.h> + + +#define CI_OFFSET_1 16 +#define CI_OFFSET_2 32 + + +GLenum doubleBuffer; + +static void Init(void) +{ + GLint errno; + GLuint prognum; + + static const char *prog1 = + "!!ARBvp1.0\n" + "OPTION ARB_position_invariant ;" + "MOV result.color, vertex.color;\n" + "END\n"; + + + glGenProgramsARB(1, &prognum); + + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum); + glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(prog1), (const GLubyte *) prog1); + + errno = glGetError(); + printf("glGetError = %d\n", errno); + if (errno != GL_NO_ERROR) + { + GLint errorpos; + + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos); + printf("errorpos: %d\n", errorpos); + printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)); + } + + 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); + + glClearColor(0.0, 0.0, 1.0, 0.0); +} + +static void Reshape(int width, int height) +{ + + glViewport(0, 0, (GLint)width, (GLint)height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); +/* glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0); */ + glMatrixMode(GL_MODELVIEW); +} + +static void Key(unsigned char key, int x, int y) +{ + + switch (key) { + case 27: + exit(1); + default: + return; + } + + glutPostRedisplay(); +} + +static void Draw(void) +{ + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_VERTEX_PROGRAM_ARB); + + glBegin(GL_TRIANGLES); + glColor3f(0,0,.7); + glVertex3f( 0.9, -0.9, -0.0); + glColor3f(.8,0,0); + glVertex3f( 0.9, 0.9, -0.0); + glColor3f(0,.9,0); + glVertex3f(-0.9, 0.0, -0.0); + glEnd(); + + glFlush(); + + if (doubleBuffer) { + glutSwapBuffers(); + } +} + +static GLenum Args(int argc, char **argv) +{ + GLint i; + + doubleBuffer = GL_FALSE; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-sb") == 0) { + doubleBuffer = GL_FALSE; + } else if (strcmp(argv[i], "-db") == 0) { + doubleBuffer = GL_TRUE; + } else { + fprintf(stderr, "%s (Bad option).\n", argv[i]); + return GL_FALSE; + } + } + return GL_TRUE; +} + +int main(int argc, char **argv) +{ + GLenum type; + + glutInit(&argc, argv); + + if (Args(argc, argv) == GL_FALSE) { + exit(1); + } + + glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250); + + type = GLUT_RGB | GLUT_ALPHA; + type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; + glutInitDisplayMode(type); + + if (glutCreateWindow(*argv) == GL_FALSE) { + exit(1); + } + + glewInit(); + Init(); + + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Draw); + glutMainLoop(); + return 0; +} diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 6f3e1e0289b..8ef0ea8011f 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -187,6 +187,7 @@ struct pt_emit *draw_pt_emit_create( struct draw_context *draw ); struct pt_fetch; void draw_pt_fetch_prepare( struct pt_fetch *fetch, + unsigned vertex_input_count, unsigned vertex_size ); void draw_pt_fetch_run( struct pt_fetch *fetch, diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c index 505d32f2c32..65c3a34c347 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c @@ -26,6 +26,7 @@ **************************************************************************/ #include "util/u_memory.h" +#include "util/u_math.h" #include "draw/draw_context.h" #include "draw/draw_private.h" #include "draw/draw_vbuf.h" @@ -56,9 +57,11 @@ struct pt_fetch { * */ void draw_pt_fetch_prepare( struct pt_fetch *fetch, + unsigned vs_input_count, unsigned vertex_size ) { struct draw_context *draw = fetch->draw; + unsigned nr_inputs; unsigned i, nr = 0; unsigned dst_offset = 0; struct translate_key key; @@ -89,8 +92,11 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch, dst_offset += 4 * sizeof(float); } + assert( draw->pt.nr_vertex_elements >= vs_input_count ); - for (i = 0; i < draw->pt.nr_vertex_elements; i++) { + nr_inputs = MIN2( vs_input_count, draw->pt.nr_vertex_elements ); + + for (i = 0; i < nr_inputs; i++) { key.element[nr].input_format = draw->pt.vertex_element[i].src_format; key.element[nr].input_buffer = draw->pt.vertex_element[i].vertex_buffer_index; key.element[nr].input_offset = draw->pt.vertex_element[i].src_offset; diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index 11ac90fc563..df6c265b7ec 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -77,8 +77,8 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, draw_pt_fetch_prepare( fpme->fetch, + vs->info.num_inputs, fpme->vertex_size ); - /* XXX: it's not really gl rasterization rules we care about here, * but gl vs dx9 clip spaces. */ diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index dbbc33fffa7..f2368dde5c2 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -114,6 +114,12 @@ vs_exec_run_linear( struct draw_vertex_shader *shader, #endif for (slot = 0; slot < shader->info.num_inputs; slot++) { +#if 0 + assert(!util_is_inf_or_nan(input[slot][0])); + assert(!util_is_inf_or_nan(input[slot][1])); + assert(!util_is_inf_or_nan(input[slot][2])); + assert(!util_is_inf_or_nan(input[slot][3])); +#endif machine->Inputs[slot].xyzw[0].f[j] = input[slot][0]; machine->Inputs[slot].xyzw[1].f[j] = input[slot][1]; machine->Inputs[slot].xyzw[2].f[j] = input[slot][2]; diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index 044e8e1dd3e..4698efa69cf 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c @@ -531,16 +531,17 @@ fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list) pipe_mutex_lock(fenced_list->mutex); - debug_printf("%10s %7s %10s %s\n", - "buffer", "reference.count", "fence", "signalled"); + debug_printf("%10s %7s %7s %10s %s\n", + "buffer", "size", "refcount", "fence", "signalled"); curr = fenced_list->unfenced.next; next = curr->next; while(curr != &fenced_list->unfenced) { fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); assert(!fenced_buf->fence); - debug_printf("%10p %7u\n", + debug_printf("%10p %7u %7u\n", fenced_buf, + fenced_buf->base.base.size, fenced_buf->base.base.reference.count); curr = next; next = curr->next; @@ -552,8 +553,9 @@ fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list) int signaled; fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head); signaled = ops->fence_signalled(ops, fenced_buf->fence, 0); - debug_printf("%10p %7u %10p %s\n", + debug_printf("%10p %7u %7u %10p %s\n", fenced_buf, + fenced_buf->base.base.size, fenced_buf->base.base.reference.count, fenced_buf->fence, signaled == 0 ? "y" : "n"); diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c index f1a05be46e4..cedf745bdac 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c @@ -40,6 +40,7 @@ #include "util/u_memory.h" #include "util/u_double_list.h" #include "util/u_time.h" +#include "util/u_debug_stack.h" #include "pb_buffer.h" #include "pb_bufmgr.h" @@ -48,6 +49,10 @@ #ifdef DEBUG +#define PB_DEBUG_CREATE_BACKTRACE 8 +#define PB_DEBUG_MAP_BACKTRACE 8 + + /** * Convenience macro (type safe). */ @@ -69,6 +74,14 @@ struct pb_debug_buffer size_t underflow_size; size_t overflow_size; + + struct debug_stack_frame create_backtrace[PB_DEBUG_CREATE_BACKTRACE]; + + pipe_mutex mutex; + unsigned map_count; + struct debug_stack_frame map_backtrace[PB_DEBUG_MAP_BACKTRACE]; + + struct list_head head; }; @@ -80,6 +93,9 @@ struct pb_debug_manager size_t underflow_size; size_t overflow_size; + + pipe_mutex mutex; + struct list_head list; }; @@ -189,6 +205,9 @@ pb_debug_buffer_check(struct pb_debug_buffer *buf) max_ofs == buf->overflow_size - 1 ? "+" : ""); } + if(underflow || overflow) + debug_backtrace_dump(buf->create_backtrace, PB_DEBUG_CREATE_BACKTRACE); + debug_assert(!underflow && !overflow); /* re-fill if not aborted */ @@ -207,11 +226,18 @@ static void pb_debug_buffer_destroy(struct pb_buffer *_buf) { struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + struct pb_debug_manager *mgr = buf->mgr; assert(!pipe_is_referenced(&buf->base.base.reference)); pb_debug_buffer_check(buf); + pipe_mutex_lock(mgr->mutex); + LIST_DEL(&buf->head); + pipe_mutex_unlock(mgr->mutex); + + pipe_mutex_destroy(buf->mutex); + pb_reference(&buf->buffer, NULL); FREE(buf); } @@ -230,6 +256,13 @@ pb_debug_buffer_map(struct pb_buffer *_buf, if(!map) return NULL; + if(map) { + pipe_mutex_lock(buf->mutex); + ++buf->map_count; + debug_backtrace_capture(buf->map_backtrace, 1, PB_DEBUG_MAP_BACKTRACE); + pipe_mutex_unlock(buf->mutex); + } + return (uint8_t *)map + buf->underflow_size; } @@ -238,6 +271,13 @@ static void pb_debug_buffer_unmap(struct pb_buffer *_buf) { struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + + pipe_mutex_lock(buf->mutex); + assert(buf->map_count); + if(buf->map_count) + --buf->map_count; + pipe_mutex_unlock(buf->mutex); + pb_unmap(buf->buffer); pb_debug_buffer_check(buf); @@ -262,6 +302,14 @@ pb_debug_buffer_validate(struct pb_buffer *_buf, { struct pb_debug_buffer *buf = pb_debug_buffer(_buf); + pipe_mutex_lock(buf->mutex); + if(buf->map_count) { + debug_printf("%s: attempting to validate a mapped buffer\n", __FUNCTION__); + debug_printf("last map backtrace is\n"); + debug_backtrace_dump(buf->map_backtrace, PB_DEBUG_MAP_BACKTRACE); + } + pipe_mutex_unlock(buf->mutex); + pb_debug_buffer_check(buf); return pb_validate(buf->buffer, vl, flags); @@ -288,6 +336,31 @@ pb_debug_buffer_vtbl = { }; +static void +pb_debug_manager_dump(struct pb_debug_manager *mgr) +{ + struct list_head *curr, *next; + struct pb_debug_buffer *buf; + + pipe_mutex_lock(mgr->mutex); + + curr = mgr->list.next; + next = curr->next; + while(curr != &mgr->list) { + buf = LIST_ENTRY(struct pb_debug_buffer, curr, head); + + debug_printf("buffer = %p\n", buf); + debug_printf(" .size = %p\n", buf->base.base.size); + debug_backtrace_dump(buf->create_backtrace, PB_DEBUG_CREATE_BACKTRACE); + + curr = next; + next = curr->next; + } + + pipe_mutex_unlock(mgr->mutex); +} + + static struct pb_buffer * pb_debug_manager_create_buffer(struct pb_manager *_mgr, size_t size, @@ -312,6 +385,13 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr, &real_desc); if(!buf->buffer) { FREE(buf); +#if 0 + pipe_mutex_lock(mgr->mutex); + debug_printf("%s: failed to create buffer\n", __FUNCTION__); + if(!LIST_IS_EMPTY(&mgr->list)) + pb_debug_manager_dump(mgr); + pipe_mutex_unlock(mgr->mutex); +#endif return NULL; } @@ -331,8 +411,16 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr, buf->underflow_size = mgr->underflow_size; buf->overflow_size = buf->buffer->base.size - buf->underflow_size - size; + debug_backtrace_capture(buf->create_backtrace, 1, PB_DEBUG_CREATE_BACKTRACE); + pb_debug_buffer_fill(buf); + pipe_mutex_init(buf->mutex); + + pipe_mutex_lock(mgr->mutex); + LIST_ADDTAIL(&buf->head, &mgr->list); + pipe_mutex_unlock(mgr->mutex); + return &buf->base; } @@ -351,6 +439,15 @@ static void pb_debug_manager_destroy(struct pb_manager *_mgr) { struct pb_debug_manager *mgr = pb_debug_manager(_mgr); + + pipe_mutex_lock(mgr->mutex); + if(!LIST_IS_EMPTY(&mgr->list)) { + debug_printf("%s: unfreed buffers\n", __FUNCTION__); + pb_debug_manager_dump(mgr); + } + pipe_mutex_unlock(mgr->mutex); + + pipe_mutex_destroy(mgr->mutex); mgr->provider->destroy(mgr->provider); FREE(mgr); } @@ -375,7 +472,10 @@ pb_debug_manager_create(struct pb_manager *provider, mgr->provider = provider; mgr->underflow_size = underflow_size; mgr->overflow_size = overflow_size; - + + pipe_mutex_init(mgr->mutex); + LIST_INITHEAD(&mgr->list); + return &mgr->base; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.c b/src/gallium/auxiliary/tgsi/tgsi_transform.c index 062c1be938a..bc9c18fd4a7 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_transform.c +++ b/src/gallium/auxiliary/tgsi/tgsi_transform.c @@ -198,3 +198,30 @@ tgsi_transform_shader(const struct tgsi_token *tokens_in, return ctx->ti; } + + +#include "tgsi_text.h" + +extern int tgsi_transform_foo( struct tgsi_token *tokens_out, + uint max_tokens_out ); + +/* This function exists only so that tgsi_text_translate() doesn't get + * magic-ed out of the libtgsi.a archive by the build system. Don't + * remove unless you know this has been fixed - check on mingw/scons + * builds as well. + */ +int +tgsi_transform_foo( struct tgsi_token *tokens_out, + uint max_tokens_out ) +{ + const char *text = + "FRAG1.1\n" + "DCL IN[0], COLOR, CONSTANT\n" + "DCL OUT[0], COLOR\n" + " 0: MOV OUT[0], IN[0]\n" + " 1: END"; + + return tgsi_text_translate( text, + tokens_out, + max_tokens_out ); +} diff --git a/src/gallium/auxiliary/util/u_debug_stack.c b/src/gallium/auxiliary/util/u_debug_stack.c index e9891fde8a3..528a1c394be 100644 --- a/src/gallium/auxiliary/util/u_debug_stack.c +++ b/src/gallium/auxiliary/util/u_debug_stack.c @@ -62,6 +62,8 @@ debug_backtrace_capture(struct debug_stack_frame *backtrace, #ifdef PIPE_ARCH_X86 while(nr_frames) { + const void **next_frame_pointer; + if(!frame_pointer) break; @@ -72,7 +74,14 @@ debug_backtrace_capture(struct debug_stack_frame *backtrace, --nr_frames; } - frame_pointer = (const void **)frame_pointer[0]; + next_frame_pointer = (const void **)frame_pointer[0]; + + /* Limit the stack walk to avoid referencing undefined memory */ + if((uintptr_t)next_frame_pointer <= (uintptr_t)frame_pointer || + (uintptr_t)next_frame_pointer > (uintptr_t)frame_pointer + 64*1024) + break; + + frame_pointer = next_frame_pointer; } #endif diff --git a/src/gallium/drivers/nv04/nv04_miptree.c b/src/gallium/drivers/nv04/nv04_miptree.c index 4da833c25e8..93f752faec9 100644 --- a/src/gallium/drivers/nv04/nv04_miptree.c +++ b/src/gallium/drivers/nv04/nv04_miptree.c @@ -31,7 +31,8 @@ nv04_miptree_layout(struct nv04_miptree *nv04mt) for (l = 0; l <= pt->last_level; l++) { - nv04mt->level[l].image_offset = offset; + nv04mt->level[l].image_offset = + CALLOC(nr_faces, sizeof(unsigned)); offset += nv04mt->level[l].pitch * pt->height[l]; } diff --git a/src/gallium/drivers/nv04/nv04_state.h b/src/gallium/drivers/nv04/nv04_state.h index 0d51439e3ff..399f750dbe7 100644 --- a/src/gallium/drivers/nv04/nv04_state.h +++ b/src/gallium/drivers/nv04/nv04_state.h @@ -37,7 +37,7 @@ struct nv04_miptree { struct { uint pitch; - uint image_offset; + uint *image_offset; } level[PIPE_MAX_TEXTURE_LEVELS]; }; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 82e23c413c8..47c24f30862 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -132,6 +132,7 @@ enum pipe_texture_target { #define PIPE_TEX_FACE_NEG_Y 3 #define PIPE_TEX_FACE_POS_Z 4 #define PIPE_TEX_FACE_NEG_Z 5 +#define PIPE_TEX_FACE_MAX 6 #define PIPE_TEX_WRAP_REPEAT 0 #define PIPE_TEX_WRAP_CLAMP 1 @@ -158,14 +159,6 @@ enum pipe_texture_target { #define PIPE_TEX_COMPARE_NONE 0 #define PIPE_TEX_COMPARE_R_TO_TEXTURE 1 -#define PIPE_TEX_FACE_POS_X 0 -#define PIPE_TEX_FACE_NEG_X 1 -#define PIPE_TEX_FACE_POS_Y 2 -#define PIPE_TEX_FACE_NEG_Y 3 -#define PIPE_TEX_FACE_POS_Z 4 -#define PIPE_TEX_FACE_NEG_Z 5 -#define PIPE_TEX_FACE_MAX 6 - #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 */ diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx.c b/src/gallium/state_trackers/glx/xlib/fakeglx.c index 65e7048188e..85e7ecfb9e8 100644 --- a/src/gallium/state_trackers/glx/xlib/fakeglx.c +++ b/src/gallium/state_trackers/glx/xlib/fakeglx.c @@ -97,6 +97,9 @@ struct fake_glx_context { +#define DEFAULT_DIRECT GL_TRUE + + /**********************************************************************/ /*** GLX Visual Code ***/ /**********************************************************************/ @@ -1059,7 +1062,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, return NULL; } - glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.isDirect = DEFAULT_DIRECT; glxCtx->glxContext.currentDpy = dpy; glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ @@ -1296,9 +1299,9 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) static Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx ) { - (void) dpy; + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; (void) ctx; - return False; + return glxCtx->glxContext.isDirect; } @@ -2055,7 +2058,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, return NULL; } - glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.isDirect = DEFAULT_DIRECT; glxCtx->glxContext.currentDpy = dpy; glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ @@ -2277,7 +2280,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re return NULL; } - glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.isDirect = DEFAULT_DIRECT; glxCtx->glxContext.currentDpy = dpy; glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index a3d16516531..79c2230588f 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -1100,26 +1100,19 @@ XMesaContext XMesaGetCurrentContext( void ) - - - -/* - * Copy the back buffer to the front buffer. If there's no back buffer - * this is a no-op. +/** + * Swap front and back color buffers and have winsys display front buffer. + * If there's no front color buffer no swap actually occurs. */ PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { - struct pipe_surface *surf; + struct pipe_surface *frontLeftSurf; - /* If we're swapping the buffer associated with the current context - * we have to flush any pending rendering commands first. - */ - st_notify_swapbuffers(b->stfb); + st_swapbuffers(b->stfb, &frontLeftSurf, NULL); - st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf); - if (surf) { - driver.display_surface(b, surf); + if (frontLeftSurf) { + driver.display_surface(b, frontLeftSurf); } xmesa_check_and_update_buffer_size(NULL, b); diff --git a/src/gallium/state_trackers/wgl/icd/stw_icd.c b/src/gallium/state_trackers/wgl/icd/stw_icd.c index 3711982fd26..b259ea91f58 100644 --- a/src/gallium/state_trackers/wgl/icd/stw_icd.c +++ b/src/gallium/state_trackers/wgl/icd/stw_icd.c @@ -583,7 +583,7 @@ DrvSwapLayerBuffers( if (DBG) debug_printf( "%s\n", __FUNCTION__ ); - return FALSE; + return stw_swap_layer_buffers( hdc, fuPlanes ); } BOOL APIENTRY diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.c b/src/gallium/state_trackers/wgl/shared/stw_context.c index 0b5dd78ec63..473e3308c6c 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_context.c +++ b/src/gallium/state_trackers/wgl/shared/stw_context.c @@ -276,12 +276,12 @@ stw_get_current_context( void ) struct stw_context *ctx; if(!glcurctx) - return NULL; + return 0; ctx = (struct stw_context *)glcurctx->DriverCtx; assert(ctx); if(!ctx) - return NULL; + return 0; return ctx->hglrc; } diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c index 4348b8f3262..f66f4295424 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c @@ -237,6 +237,18 @@ stw_swap_buffers( } +BOOL +stw_swap_layer_buffers( + HDC hdc, + UINT fuPlanes ) +{ + if(fuPlanes & WGL_SWAP_MAIN_PLANE) + return stw_swap_buffers(hdc); + + return FALSE; +} + + boolean stw_framebuffer_init_thread(void) { diff --git a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c index 9e642cbdd48..8d6955f3903 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c +++ b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c @@ -158,7 +158,7 @@ stw_pixelformat_add( pfi->pfd.iPixelType = PFD_TYPE_RGBA; - pfi->pfd.cColorBits = color->bits.red + color->bits.green + color->bits.blue; + pfi->pfd.cColorBits = color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha; pfi->pfd.cRedBits = color->bits.red; pfi->pfd.cRedShift = color->shift.red; pfi->pfd.cGreenBits = color->bits.green; diff --git a/src/gallium/state_trackers/wgl/shared/stw_public.h b/src/gallium/state_trackers/wgl/shared/stw_public.h index 39d377c16b5..59d709a6d40 100644 --- a/src/gallium/state_trackers/wgl/shared/stw_public.h +++ b/src/gallium/state_trackers/wgl/shared/stw_public.h @@ -50,6 +50,9 @@ BOOL stw_make_current( HDC hdc, UINT_PTR hglrc ); BOOL stw_swap_buffers( HDC hdc ); +BOOL +stw_swap_layer_buffers( HDC hdc, UINT fuPlanes ); + PROC stw_get_proc_address( LPCSTR lpszProc ); int stw_pixelformat_describe( HDC hdc, diff --git a/src/gallium/state_trackers/wgl/wgl/stw_wgl.c b/src/gallium/state_trackers/wgl/wgl/stw_wgl.c index e06d2640b47..30e42e0ec5f 100644 --- a/src/gallium/state_trackers/wgl/wgl/stw_wgl.c +++ b/src/gallium/state_trackers/wgl/wgl/stw_wgl.c @@ -100,10 +100,7 @@ wglSwapLayerBuffers( HDC hdc, UINT fuPlanes ) { - (void) hdc; - (void) fuPlanes; - - return FALSE; + return stw_swap_layer_buffers( hdc, fuPlanes ); } WINGDIAPI PROC APIENTRY diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c index b52f427e4a7..c10e3c00ffc 100644 --- a/src/gallium/winsys/egl_xlib/egl_xlib.c +++ b/src/gallium/winsys/egl_xlib/egl_xlib.c @@ -588,7 +588,9 @@ find_supported_apis(void) EGLint mask = 0; void *handle; - handle = dlopen(NULL, 0); + handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); + if(!handle) + return mask; if (dlsym(handle, "st_api_OpenGL_ES1")) mask |= EGL_OPENGL_ES_BIT; diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c index 1f9f363df92..367d2a3b648 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -73,7 +73,7 @@ i915InvalidateState(GLcontext * ctx, GLuint new_state) p->params_uptodate = 0; } - if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM)) + if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) i915_update_fog(ctx); } diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index aef2ff5f86f..838e718d0d5 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -245,6 +245,9 @@ struct brw_vs_ouput_sizes { }; +/** Number of general purpose registers (VS, WM, etc) */ +#define BRW_MAX_GRF 128 + /** Number of texture sampler units */ #define BRW_MAX_TEX_UNIT 16 @@ -450,8 +453,6 @@ struct brw_context struct { struct brw_state_flags dirty; - struct brw_tracked_state **atoms; - GLuint nr_atoms; GLuint nr_color_regions; struct intel_region *color_regions[MAX_DRAW_BUFFERS]; @@ -471,7 +472,8 @@ struct brw_context int validated_bo_count; } state; - struct brw_cache cache; + struct brw_cache cache; /** non-surface items */ + struct brw_cache surface_cache; /* surface items */ struct brw_cached_batch_item *cached_batch_items; struct { @@ -555,11 +557,6 @@ struct brw_context GLuint vs_size; GLuint total_size; - /* Dynamic tracker which changes to reflect the state referenced - * by active fp and vp program parameters: - */ - struct brw_tracked_state tracked_state; - dri_bo *curbe_bo; /** Offset within curbe_bo of space for current curbe entry */ GLuint curbe_offset; diff --git a/src/mesa/drivers/dri/i965/brw_curbe.c b/src/mesa/drivers/dri/i965/brw_curbe.c index 9197fede2d8..05a685af3da 100644 --- a/src/mesa/drivers/dri/i965/brw_curbe.c +++ b/src/mesa/drivers/dri/i965/brw_curbe.c @@ -36,6 +36,7 @@ #include "main/macros.h" #include "main/enums.h" #include "shader/prog_parameter.h" +#include "shader/prog_print.h" #include "shader/prog_statevars.h" #include "intel_batchbuffer.h" #include "intel_regions.h" @@ -188,13 +189,6 @@ static void prepare_constant_buffer(struct brw_context *brw) GLfloat *buf; GLuint i; - /* Update our own dependency flags. This works because this - * function will also be called whenever fp or vp changes. - */ - brw->curbe.tracked_state.dirty.mesa = (_NEW_TRANSFORM|_NEW_PROJECTION); - brw->curbe.tracked_state.dirty.mesa |= vp->program.Base.Parameters->StateFlags; - brw->curbe.tracked_state.dirty.mesa |= fp->program.Base.Parameters->StateFlags; - if (sz == 0) { if (brw->curbe.last_buf) { free(brw->curbe.last_buf); @@ -363,11 +357,7 @@ update_constant_buffer(struct brw_context *brw, } if (0) { - int i; - for (i = 0; i < params->NumParameters; i++) { - float *p = params->ParameterValues[i]; - printf("%d: %f %f %f %f\n", i, p[0], p[1], p[2], p[3]); - } + _mesa_print_parameter_list(params); } } } @@ -380,7 +370,7 @@ update_vertex_constant_buffer(struct brw_context *brw) struct brw_vertex_program *vp = (struct brw_vertex_program *) brw->vertex_program; if (0) { - printf("update VS constants in buffer %p\n", vp->const_buffer); + printf("update VS constants in buffer %p vp = %p\n", vp->const_buffer, vp); printf("program %u\n", vp->program.Base.Id); } if (vp->use_const_buffer) @@ -394,6 +384,10 @@ update_fragment_constant_buffer(struct brw_context *brw) { struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; + if (0) { + printf("update WM constants in buffer %p\n", fp->const_buffer); + printf("program %u\n", fp->program.Base.Id); + } if (fp->use_const_buffer) update_constant_buffer(brw, fp->program.Base.Parameters, fp->const_buffer); } @@ -428,7 +422,7 @@ static void emit_constant_buffer(struct brw_context *brw) */ const struct brw_tracked_state brw_constant_buffer = { .dirty = { - .mesa = (_NEW_TRANSFORM|_NEW_PROJECTION), /* plus fp and vp flags */ + .mesa = _NEW_PROGRAM_CONSTANTS, .brw = (BRW_NEW_FRAGMENT_PROGRAM | BRW_NEW_VERTEX_PROGRAM | BRW_NEW_URB_FENCE | /* Implicit - hardware requires this, not used above */ diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index 81b0a45998f..7ea2fc113ca 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -135,8 +135,8 @@ dri_bo *brw_search_cache( struct brw_cache *cache, void *aux_return); void brw_state_cache_check_size( struct brw_context *brw ); -void brw_init_cache( struct brw_context *brw ); -void brw_destroy_cache( struct brw_context *brw ); +void brw_init_caches( struct brw_context *brw ); +void brw_destroy_caches( struct brw_context *brw ); /*********************************************************************** * brw_state_batch.c diff --git a/src/mesa/drivers/dri/i965/brw_state_cache.c b/src/mesa/drivers/dri/i965/brw_state_cache.c index d5b51664066..320d886c992 100644 --- a/src/mesa/drivers/dri/i965/brw_state_cache.c +++ b/src/mesa/drivers/dri/i965/brw_state_cache.c @@ -56,9 +56,9 @@ * incorrect program is run for the other instance. */ +#include "main/imports.h" #include "brw_state.h" #include "intel_batchbuffer.h" -#include "main/imports.h" /* XXX: Fixme - have to include these to get the sizes of the prog_key * structs: @@ -69,8 +69,10 @@ #include "brw_sf.h" #include "brw_gs.h" -static GLuint hash_key( const void *key, GLuint key_size, - dri_bo **reloc_bufs, GLuint nr_reloc_bufs) + +static GLuint +hash_key(const void *key, GLuint key_size, + dri_bo **reloc_bufs, GLuint nr_reloc_bufs) { GLuint *ikey = (GLuint *)key; GLuint hash = 0, i; @@ -95,6 +97,7 @@ static GLuint hash_key( const void *key, GLuint key_size, return hash; } + /** * Marks a new buffer as being chosen for the given cache id. */ @@ -111,6 +114,7 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id, cache->brw->state.dirty.cache |= 1 << cache_id; } + static struct brw_cache_item * search_cache(struct brw_cache *cache, enum brw_cache_id cache_id, GLuint hash, const void *key, GLuint key_size, @@ -143,7 +147,8 @@ search_cache(struct brw_cache *cache, enum brw_cache_id cache_id, } -static void rehash( struct brw_cache *cache ) +static void +rehash(struct brw_cache *cache) { struct brw_cache_item **items; struct brw_cache_item *c, *next; @@ -164,15 +169,17 @@ static void rehash( struct brw_cache *cache ) cache->size = size; } + /** * Returns the buffer object matching cache_id and key, or NULL. */ -dri_bo *brw_search_cache( struct brw_cache *cache, - enum brw_cache_id cache_id, - const void *key, - GLuint key_size, - dri_bo **reloc_bufs, GLuint nr_reloc_bufs, - void *aux_return ) +dri_bo * +brw_search_cache(struct brw_cache *cache, + enum brw_cache_id cache_id, + const void *key, + GLuint key_size, + dri_bo **reloc_bufs, GLuint nr_reloc_bufs, + void *aux_return) { struct brw_cache_item *item; GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs); @@ -192,6 +199,7 @@ dri_bo *brw_search_cache( struct brw_cache *cache, return item->bo; } + dri_bo * brw_upload_cache( struct brw_cache *cache, enum brw_cache_id cache_id, @@ -265,7 +273,9 @@ brw_upload_cache( struct brw_cache *cache, return bo; } -/* This doesn't really work with aux data. Use search/upload instead + +/** + * This doesn't really work with aux data. Use search/upload instead */ dri_bo * brw_cache_data_sz(struct brw_cache *cache, @@ -296,6 +306,7 @@ brw_cache_data_sz(struct brw_cache *cache, return bo; } + /** * Wrapper around brw_cache_data_sz using the cache_id's canonical key size. * @@ -319,21 +330,22 @@ enum pool_type { DW_GENERAL_STATE }; + static void -brw_init_cache_id( struct brw_context *brw, - const char *name, - enum brw_cache_id id, - GLuint key_size, - GLuint aux_size) +brw_init_cache_id(struct brw_cache *cache, + const char *name, + enum brw_cache_id id, + GLuint key_size, + GLuint aux_size) { - struct brw_cache *cache = &brw->cache; - cache->name[id] = strdup(name); cache->key_size[id] = key_size; cache->aux_size[id] = aux_size; } -void brw_init_cache( struct brw_context *brw ) + +static void +brw_init_non_surface_cache(struct brw_context *brw) { struct brw_cache *cache = &brw->cache; @@ -342,114 +354,136 @@ void brw_init_cache( struct brw_context *brw ) cache->size = 7; cache->n_items = 0; cache->items = (struct brw_cache_item **) - _mesa_calloc(cache->size * - sizeof(struct brw_cache_item)); + _mesa_calloc(cache->size * sizeof(struct brw_cache_item)); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "CC_VP", BRW_CC_VP, sizeof(struct brw_cc_viewport), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "CC_UNIT", BRW_CC_UNIT, sizeof(struct brw_cc_unit_state), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "WM_PROG", BRW_WM_PROG, sizeof(struct brw_wm_prog_key), sizeof(struct brw_wm_prog_data)); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "SAMPLER_DEFAULT_COLOR", BRW_SAMPLER_DEFAULT_COLOR, sizeof(struct brw_sampler_default_color), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "SAMPLER", BRW_SAMPLER, 0, /* variable key/data size */ 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "WM_UNIT", BRW_WM_UNIT, sizeof(struct brw_wm_unit_state), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "SF_PROG", BRW_SF_PROG, sizeof(struct brw_sf_prog_key), sizeof(struct brw_sf_prog_data)); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "SF_VP", BRW_SF_VP, sizeof(struct brw_sf_viewport), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "SF_UNIT", BRW_SF_UNIT, sizeof(struct brw_sf_unit_state), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "VS_UNIT", BRW_VS_UNIT, sizeof(struct brw_vs_unit_state), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "VS_PROG", BRW_VS_PROG, sizeof(struct brw_vs_prog_key), sizeof(struct brw_vs_prog_data)); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "CLIP_UNIT", BRW_CLIP_UNIT, sizeof(struct brw_clip_unit_state), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "CLIP_PROG", BRW_CLIP_PROG, sizeof(struct brw_clip_prog_key), sizeof(struct brw_clip_prog_data)); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "GS_UNIT", BRW_GS_UNIT, sizeof(struct brw_gs_unit_state), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "GS_PROG", BRW_GS_PROG, sizeof(struct brw_gs_prog_key), sizeof(struct brw_gs_prog_data)); +} + + +static void +brw_init_surface_cache(struct brw_context *brw) +{ + struct brw_cache *cache = &brw->surface_cache; - brw_init_cache_id(brw, + cache->brw = brw; + + cache->size = 7; + cache->n_items = 0; + cache->items = (struct brw_cache_item **) + _mesa_calloc(cache->size * sizeof(struct brw_cache_item)); + + brw_init_cache_id(cache, "SS_SURFACE", BRW_SS_SURFACE, sizeof(struct brw_surface_state), 0); - brw_init_cache_id(brw, + brw_init_cache_id(cache, "SS_SURF_BIND", BRW_SS_SURF_BIND, 0, 0); } + +void +brw_init_caches(struct brw_context *brw) +{ + brw_init_non_surface_cache(brw); + brw_init_surface_cache(brw); +} + + static void -brw_clear_cache( struct brw_context *brw ) +brw_clear_cache(struct brw_context *brw, struct brw_cache *cache) { struct brw_cache_item *c, *next; GLuint i; @@ -457,8 +491,8 @@ brw_clear_cache( struct brw_context *brw ) if (INTEL_DEBUG & DEBUG_STATE) _mesa_printf("%s\n", __FUNCTION__); - for (i = 0; i < brw->cache.size; i++) { - for (c = brw->cache.items[i]; c; c = next) { + for (i = 0; i < cache->size; i++) { + for (c = cache->items[i]; c; c = next) { int j; next = c->next; @@ -468,10 +502,10 @@ brw_clear_cache( struct brw_context *brw ) free((void *)c->key); free(c); } - brw->cache.items[i] = NULL; + cache->items[i] = NULL; } - brw->cache.n_items = 0; + cache->n_items = 0; if (brw->curbe.last_buf) { _mesa_free(brw->curbe.last_buf); @@ -483,25 +517,40 @@ brw_clear_cache( struct brw_context *brw ) brw->state.dirty.cache |= ~0; } -void brw_state_cache_check_size( struct brw_context *brw ) + +void +brw_state_cache_check_size(struct brw_context *brw) { /* un-tuned guess. We've got around 20 state objects for a total of around * 32k, so 1000 of them is around 1.5MB. */ if (brw->cache.n_items > 1000) - brw_clear_cache(brw); + brw_clear_cache(brw, &brw->cache); + + if (brw->surface_cache.n_items > 1000) + brw_clear_cache(brw, &brw->surface_cache); } -void brw_destroy_cache( struct brw_context *brw ) + +static void +brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache) { GLuint i; - brw_clear_cache(brw); + brw_clear_cache(brw, cache); for (i = 0; i < BRW_MAX_CACHE; i++) { - dri_bo_unreference(brw->cache.last_bo[i]); - free(brw->cache.name[i]); + dri_bo_unreference(cache->last_bo[i]); + free(cache->name[i]); } - free(brw->cache.items); - brw->cache.items = NULL; - brw->cache.size = 0; + free(cache->items); + cache->items = NULL; + cache->size = 0; +} + + +void +brw_destroy_caches(struct brw_context *brw) +{ + brw_destroy_cache(brw, &brw->cache); + brw_destroy_cache(brw, &brw->surface_cache); } diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c index 5de1450e612..2641bcb2aa8 100644 --- a/src/mesa/drivers/dri/i965/brw_state_upload.c +++ b/src/mesa/drivers/dri/i965/brw_state_upload.c @@ -59,7 +59,6 @@ const struct brw_tracked_state *atoms[] = &brw_curbe_offsets, &brw_recalculate_urb_fence, - &brw_cc_vp, &brw_cc_unit, @@ -88,54 +87,26 @@ const struct brw_tracked_state *atoms[] = &brw_line_stipple, &brw_aa_line_parameters, - /* Ordering of the commands below is documented as fixed. - */ -#if 0 - &brw_pipelined_state_pointers, - &brw_urb_fence, - &brw_constant_buffer_state, -#else + &brw_psp_urb_cbs, -#endif &brw_drawing_rect, &brw_indices, &brw_vertices, - NULL, /* brw_constant_buffer */ + &brw_constant_buffer }; void brw_init_state( struct brw_context *brw ) { - GLuint i; - - brw_init_cache(brw); - - brw->state.atoms = _mesa_malloc(sizeof(atoms)); - brw->state.nr_atoms = sizeof(atoms)/sizeof(*atoms); - _mesa_memcpy(brw->state.atoms, atoms, sizeof(atoms)); - - /* Patch in a pointer to the dynamic state atom: - */ - for (i = 0; i < brw->state.nr_atoms; i++) - if (brw->state.atoms[i] == NULL) - brw->state.atoms[i] = &brw->curbe.tracked_state; - - _mesa_memcpy(&brw->curbe.tracked_state, - &brw_constant_buffer, - sizeof(brw_constant_buffer)); + brw_init_caches(brw); } void brw_destroy_state( struct brw_context *brw ) { - if (brw->state.atoms) { - _mesa_free(brw->state.atoms); - brw->state.atoms = NULL; - } - - brw_destroy_cache(brw); + brw_destroy_caches(brw); brw_destroy_batch_cache(brw); } @@ -218,6 +189,7 @@ static struct dirty_bit_map mesa_bits[] = { DEFINE_BIT(_NEW_MULTISAMPLE), DEFINE_BIT(_NEW_TRACK_MATRIX), DEFINE_BIT(_NEW_PROGRAM), + DEFINE_BIT(_NEW_PROGRAM_CONSTANTS), {0, 0, 0} }; @@ -336,7 +308,7 @@ void brw_validate_state( struct brw_context *brw ) /* do prepare stage for all atoms */ for (i = 0; i < Elements(atoms); i++) { - const struct brw_tracked_state *atom = brw->state.atoms[i]; + const struct brw_tracked_state *atom = atoms[i]; if (brw->intel.Fallback) break; @@ -367,8 +339,8 @@ void brw_upload_state(struct brw_context *brw) _mesa_memset(&examined, 0, sizeof(examined)); prev = *state; - for (i = 0; i < brw->state.nr_atoms; i++) { - const struct brw_tracked_state *atom = brw->state.atoms[i]; + for (i = 0; i < Elements(atoms); i++) { + const struct brw_tracked_state *atom = atoms[i]; struct brw_state_flags generated; assert(atom->dirty.mesa || @@ -397,7 +369,7 @@ void brw_upload_state(struct brw_context *brw) } else { for (i = 0; i < Elements(atoms); i++) { - const struct brw_tracked_state *atom = brw->state.atoms[i]; + const struct brw_tracked_state *atom = atoms[i]; if (brw->intel.Fallback) break; diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index b69616d6e52..3fdc48583bf 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -69,13 +69,18 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c ) { GLuint i, reg = 0, mrf; -#if 0 - if (c->vp->program.Base.Parameters->NumParameters >= 6) - c->vp->use_const_buffer = 1; + /* Determine whether to use a real constant buffer or use a block + * of GRF registers for constants. The later is faster but only + * works if everything fits in the GRF. + * XXX this heuristic/check may need some fine tuning... + */ + if (c->vp->program.Base.Parameters->NumParameters + + c->vp->program.Base.NumTemporaries + 20 > BRW_MAX_GRF) + c->vp->use_const_buffer = GL_TRUE; else -#endif c->vp->use_const_buffer = GL_FALSE; - /*printf("use_const_buffer = %d\n", c->use_const_buffer);*/ + + /*printf("use_const_buffer = %d\n", c->vp->use_const_buffer);*/ /* r0 -- reserved as usual */ diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h index f0d31fc1ddc..2f80a60c12b 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.h +++ b/src/mesa/drivers/dri/i965/brw_wm.h @@ -240,15 +240,18 @@ struct brw_wm_compile { GLuint max_wm_grf; GLuint last_scratch; + GLuint cur_inst; /**< index of current instruction */ + /** Mapping from Mesa registers to hardware registers */ struct { GLboolean inited; struct brw_reg reg; } wm_regs[PROGRAM_PAYLOAD+1][256][4]; + GLboolean used_grf[BRW_WM_MAX_GRF]; + GLuint first_free_grf; struct brw_reg stack; struct brw_reg emit_mask_reg; - GLuint reg_index; /**< Index of next free GRF register */ GLuint tmp_regs[BRW_WM_MAX_GRF]; GLuint tmp_index; GLuint tmp_max; diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c index 117460842a3..39ea95f6fc2 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c +++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c @@ -1,5 +1,7 @@ #include "main/macros.h" #include "shader/prog_parameter.h" +#include "shader/prog_print.h" +#include "shader/prog_optimize.h" #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" @@ -42,6 +44,76 @@ GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp) } + +static void +reclaim_temps(struct brw_wm_compile *c); + + +/** Mark GRF register as used. */ +static void +prealloc_grf(struct brw_wm_compile *c, int r) +{ + c->used_grf[r] = GL_TRUE; +} + + +/** Mark given GRF register as not in use. */ +static void +release_grf(struct brw_wm_compile *c, int r) +{ + /*assert(c->used_grf[r]);*/ + c->used_grf[r] = GL_FALSE; + c->first_free_grf = MIN2(c->first_free_grf, r); +} + + +/** Return index of a free GRF, mark it as used. */ +static int +alloc_grf(struct brw_wm_compile *c) +{ + GLuint r; + for (r = c->first_free_grf; r < BRW_WM_MAX_GRF; r++) { + if (!c->used_grf[r]) { + c->used_grf[r] = GL_TRUE; + c->first_free_grf = r + 1; /* a guess */ + return r; + } + } + + /* no free temps, try to reclaim some */ + reclaim_temps(c); + c->first_free_grf = 0; + + /* try alloc again */ + for (r = c->first_free_grf; r < BRW_WM_MAX_GRF; r++) { + if (!c->used_grf[r]) { + c->used_grf[r] = GL_TRUE; + c->first_free_grf = r + 1; /* a guess */ + return r; + } + } + + for (r = 0; r < BRW_WM_MAX_GRF; r++) { + assert(c->used_grf[r]); + } + /*printf("Really out of temp regs!\n");*/ + return 60; +} + + +/** Return number of GRF registers used */ +static int +num_grf_used(const struct brw_wm_compile *c) +{ + int r; + for (r = BRW_WM_MAX_GRF - 1; r >= 0; r--) + if (c->used_grf[r]) + return r + 1; + return 0; +} + + + /** * Record the mapping of a Mesa register to a hardware register. */ @@ -68,11 +140,18 @@ static int get_scalar_dst_index(const struct prog_instruction *inst) static struct brw_reg alloc_tmp(struct brw_wm_compile *c) { struct brw_reg reg; - if(c->tmp_index == c->tmp_max) - c->tmp_regs[ c->tmp_max++ ] = c->reg_index++; - + + /* if we need to allocate another temp, grow the tmp_regs[] array */ + if (c->tmp_index == c->tmp_max) { + c->tmp_regs[ c->tmp_max++ ] = alloc_grf(c); + } + + /* form the GRF register */ reg = brw_vec8_grf(c->tmp_regs[ c->tmp_index++ ], 0); + /*printf("alloc_temp %d\n", reg.nr);*/ + assert(reg.nr < BRW_WM_MAX_GRF); return reg; + } /** @@ -130,35 +209,26 @@ get_reg(struct brw_wm_compile *c, int file, int index, int component, return brw_null_reg(); } + assert(index < 256); /* see if we've already allocated a HW register for this Mesa register */ if (c->wm_regs[file][index][component].inited) { - /* yes, re-use */ - reg = c->wm_regs[file][index][component].reg; + /* yes, re-use */ + reg = c->wm_regs[file][index][component].reg; } else { /* no, allocate new register */ - reg = brw_vec8_grf(c->reg_index, 0); - } + int grf = alloc_grf(c); + if (grf < 0) { + /* totally out of temps */ + grf = 70; /* XXX !!!! */ + } - /* if this is a new register allocation, record it in the table */ - if (!c->wm_regs[file][index][component].inited) { - set_reg(c, file, index, component, reg); - c->reg_index++; - } + reg = brw_vec8_grf(grf, 0); + /*printf("Alloc new grf %d for %d.%d\n", reg.nr, index, component);*/ - if (c->reg_index >= BRW_WM_MAX_GRF - 12) { - /* ran out of temporary registers! */ -#if 1 - /* This is a big hack for now. - * Return bad register index, just don't hang the GPU. - */ - _mesa_fprintf(stderr, "out of regs %d\n", c->reg_index); - c->reg_index = BRW_WM_MAX_GRF - 13; -#else - return brw_null_reg(); -#endif + set_reg(c, file, index, component, reg); } - + if (neg & (1 << component)) { reg = negate(reg); } @@ -168,6 +238,46 @@ get_reg(struct brw_wm_compile *c, int file, int index, int component, } + +/** + * This is called if we run out of GRF registers. Examine the live intervals + * of temp regs in the program and free those which won't be used again. + */ +static void +reclaim_temps(struct brw_wm_compile *c) +{ + GLint intBegin[MAX_PROGRAM_TEMPS]; + GLint intEnd[MAX_PROGRAM_TEMPS]; + int index; + + /*printf("Reclaim temps:\n");*/ + + _mesa_find_temp_intervals(c->prog_instructions, c->nr_fp_insns, + intBegin, intEnd); + + for (index = 0; index < MAX_PROGRAM_TEMPS; index++) { + if (intEnd[index] != -1 && intEnd[index] < c->cur_inst) { + /* program temp[i] can be freed */ + int component; + /*printf(" temp[%d] is dead\n", index);*/ + for (component = 0; component < 4; component++) { + if (c->wm_regs[PROGRAM_TEMPORARY][index][component].inited) { + int r = c->wm_regs[PROGRAM_TEMPORARY][index][component].reg.nr; + release_grf(c, r); + /* + printf(" Reclaim temp %d, reg %d at inst %d\n", + index, r, c->cur_inst); + */ + c->wm_regs[PROGRAM_TEMPORARY][index][component].inited = GL_FALSE; + } + } + } + } +} + + + + /** * Preallocate registers. This sets up the Mesa to hardware register * mapping for certain registers, such as constants (uniforms/state vars) @@ -179,6 +289,10 @@ static void prealloc_reg(struct brw_wm_compile *c) struct brw_reg reg; int nr_interp_regs = 0; GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted | c->fp_deriv_emitted; + GLuint reg_index = 0; + + memset(c->used_grf, GL_FALSE, sizeof(c->used_grf)); + c->first_free_grf = 0; for (i = 0; i < 4; i++) { if (i < c->key.nr_depth_regs) @@ -187,14 +301,20 @@ static void prealloc_reg(struct brw_wm_compile *c) reg = brw_vec8_grf(0, 0); set_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, i, reg); } - c->reg_index += 2 * c->key.nr_depth_regs; + reg_index += 2 * c->key.nr_depth_regs; /* constants */ { - const int nr_params = c->fp->program.Base.Parameters->NumParameters; + const GLuint nr_params = c->fp->program.Base.Parameters->NumParameters; + const GLuint nr_temps = c->fp->program.Base.NumTemporaries; /* use a real constant buffer, or just use a section of the GRF? */ - c->fp->use_const_buffer = GL_FALSE; /* (nr_params > 8);*/ + /* XXX this heuristic may need adjustment... */ + if ((nr_params + nr_temps) * 4 + reg_index > 80) + c->fp->use_const_buffer = GL_TRUE; + else + c->fp->use_const_buffer = GL_FALSE; + /*printf("WM use_const_buffer = %d\n", c->fp->use_const_buffer);*/ if (c->fp->use_const_buffer) { /* We'll use a real constant buffer and fetch constants from @@ -216,7 +336,7 @@ static void prealloc_reg(struct brw_wm_compile *c) for (i = 0; i < nr_params; i++) { /* loop over XYZW channels */ for (j = 0; j < 4; j++, index++) { - reg = brw_vec1_grf(c->reg_index + index / 8, index % 8); + reg = brw_vec1_grf(reg_index + index / 8, index % 8); /* Save pointer to parameter/constant value. * Constants will be copied in prepare_constant_buffer() */ @@ -226,7 +346,7 @@ static void prealloc_reg(struct brw_wm_compile *c) } /* number of constant regs used (each reg is float[8]) */ c->nr_creg = 2 * ((4 * nr_params + 15) / 16); - c->reg_index += c->nr_creg; + reg_index += c->nr_creg; } } @@ -234,20 +354,24 @@ static void prealloc_reg(struct brw_wm_compile *c) for (i = 0; i < FRAG_ATTRIB_MAX; i++) { if (inputs & (1<<i)) { nr_interp_regs++; - reg = brw_vec8_grf(c->reg_index, 0); + reg = brw_vec8_grf(reg_index, 0); for (j = 0; j < 4; j++) set_reg(c, PROGRAM_PAYLOAD, i, j, reg); - c->reg_index += 2; + reg_index += 2; } } c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2; c->prog_data.urb_read_length = nr_interp_regs * 2; c->prog_data.curb_read_length = c->nr_creg; - c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0); - c->reg_index++; - c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0); - c->reg_index += 2; + c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, reg_index, 0); + reg_index++; + c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, reg_index, 0); + reg_index += 2; + + /* mark GRF regs [0..reg_index-1] as in-use */ + for (i = 0; i < reg_index; i++) + prealloc_grf(c, i); /* An instruction may reference up to three constants. * They'll be found in these registers. @@ -256,7 +380,7 @@ static void prealloc_reg(struct brw_wm_compile *c) if (c->fp->use_const_buffer) { for (i = 0; i < 3; i++) { c->current_const[i].index = -1; - c->current_const[i].reg = alloc_tmp(c); + c->current_const[i].reg = brw_vec8_grf(alloc_grf(c), 0); } } #if 0 @@ -2595,7 +2719,6 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) struct brw_compile *p = &c->func; struct brw_indirect stack_index = brw_indirect(0, 0); - c->reg_index = 0; prealloc_reg(c); brw_set_compression_control(p, BRW_COMPRESSION_NONE); brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack)); @@ -2603,6 +2726,8 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) for (i = 0; i < c->nr_fp_insns; i++) { const struct prog_instruction *inst = &c->prog_instructions[i]; + c->cur_inst = i; + #if 0 _mesa_printf("Inst %d: ", i); _mesa_print_instruction(inst); @@ -2833,17 +2958,13 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) _mesa_printf("unsupported IR in fragment shader %d\n", inst->Opcode); } + if (inst->CondUpdate) brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); else brw_set_predicate_control(p, BRW_PREDICATE_NONE); } post_wm_emit(c); - - if (c->reg_index >= BRW_WM_MAX_GRF) { - _mesa_problem(NULL, "Ran out of registers in brw_wm_emit_glsl()"); - /* XXX we need to do some proper error recovery here */ - } } @@ -2867,6 +2988,6 @@ void brw_wm_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c) brw_wm_print_program(c, "brw_wm_glsl_emit done"); } - c->prog_data.total_grf = c->reg_index; + c->prog_data.total_grf = num_grf_used(c); c->prog_data.total_scratch = 0; } diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index 805df8a4af4..f646ee7fc3a 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -268,7 +268,7 @@ brw_create_texture_surface( struct brw_context *brw, surf.ss0.cube_neg_z = 1; } - bo = brw_upload_cache(&brw->cache, BRW_SS_SURFACE, + bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, key, sizeof(*key), &key->bo, key->bo ? 1 : 0, &surf, sizeof(surf), @@ -321,10 +321,11 @@ brw_update_texture_surface( GLcontext *ctx, GLuint unit ) key.tiling = intelObj->mt->region->tiling; dri_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = brw_search_cache(&brw->cache, BRW_SS_SURFACE, - &key, sizeof(key), - &key.bo, key.bo ? 1 : 0, - NULL); + brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &key, sizeof(key), + &key.bo, key.bo ? 1 : 0, + NULL); if (brw->wm.surf_bo[surf] == NULL) { brw->wm.surf_bo[surf] = brw_create_texture_surface(brw, &key); } @@ -362,7 +363,7 @@ brw_create_constant_surface( struct brw_context *brw, surf.ss3.pitch = (key->pitch * key->cpp) - 1; /* ignored?? */ brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */ - bo = brw_upload_cache(&brw->cache, BRW_SS_SURFACE, + bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, key, sizeof(*key), &key->bo, key->bo ? 1 : 0, &surf, sizeof(surf), @@ -427,7 +428,8 @@ brw_update_wm_constant_surface( GLcontext *ctx, */ dri_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = brw_search_cache(&brw->cache, BRW_SS_SURFACE, + brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, &key, sizeof(key), &key.bo, key.bo ? 1 : 0, NULL); @@ -456,17 +458,14 @@ brw_update_vs_constant_surface( GLcontext *ctx, assert(surf == 0); - /* free old const buffer if too small */ - if (const_buffer && const_buffer->size < size) { - dri_bo_unreference(const_buffer); - const_buffer = NULL; - } + /* We always create a new VS constant buffer so that several can be + * in flight at a time. Free the old one first... + */ + dri_bo_unreference(const_buffer); - /* alloc new buffer if needed */ - if (!const_buffer) { - const_buffer = - drm_intel_bo_alloc(intel->bufmgr, "vp_const_buffer", size, 64); - } + /* alloc new buffer */ + const_buffer = + drm_intel_bo_alloc(intel->bufmgr, "vp_const_buffer", size, 64); memset(&key, 0, sizeof(key)); @@ -487,7 +486,8 @@ brw_update_vs_constant_surface( GLcontext *ctx, */ dri_bo_unreference(brw->vs.surf_bo[surf]); - brw->vs.surf_bo[surf] = brw_search_cache(&brw->cache, BRW_SS_SURFACE, + brw->vs.surf_bo[surf] = brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, &key, sizeof(key), &key.bo, key.bo ? 1 : 0, NULL); @@ -569,10 +569,11 @@ brw_update_renderbuffer_surface(struct brw_context *brw, dri_bo_unreference(brw->wm.surf_bo[unit]); brw->wm.surf_bo[unit] = NULL; if (cached) - brw->wm.surf_bo[unit] = brw_search_cache(&brw->cache, BRW_SS_SURFACE, - &key, sizeof(key), - ®ion_bo, 1, - NULL); + brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &key, sizeof(key), + ®ion_bo, 1, + NULL); if (brw->wm.surf_bo[unit] == NULL) { struct brw_surface_state surf; @@ -598,7 +599,8 @@ brw_update_renderbuffer_surface(struct brw_context *brw, surf.ss0.writedisable_alpha = !key.color_mask[3]; /* Key size will never match key size for textures, so we're safe. */ - brw->wm.surf_bo[unit] = brw_upload_cache(&brw->cache, BRW_SS_SURFACE, + brw->wm.surf_bo[unit] = brw_upload_cache(&brw->surface_cache, + BRW_SS_SURFACE, &key, sizeof(key), ®ion_bo, 1, &surf, sizeof(surf), @@ -630,7 +632,7 @@ brw_wm_get_binding_table(struct brw_context *brw) assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF); - bind_bo = brw_search_cache(&brw->cache, BRW_SS_SURF_BIND, + bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, NULL, 0, brw->wm.surf_bo, brw->wm.nr_surfaces, NULL); @@ -646,7 +648,7 @@ brw_wm_get_binding_table(struct brw_context *brw) else data[i] = 0; - bind_bo = brw_upload_cache( &brw->cache, BRW_SS_SURF_BIND, + bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND, NULL, 0, brw->wm.surf_bo, brw->wm.nr_surfaces, data, data_size, @@ -746,7 +748,7 @@ brw_vs_get_binding_table(struct brw_context *brw) assert(brw->vs.nr_surfaces <= BRW_VS_MAX_SURF); - bind_bo = brw_search_cache(&brw->cache, BRW_SS_SURF_BIND, + bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, NULL, 0, brw->vs.surf_bo, brw->vs.nr_surfaces, NULL); @@ -762,7 +764,7 @@ brw_vs_get_binding_table(struct brw_context *brw) else data[i] = 0; - bind_bo = brw_upload_cache( &brw->cache, BRW_SS_SURF_BIND, + bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND, NULL, 0, brw->vs.surf_bo, brw->vs.nr_surfaces, data, data_size, @@ -787,8 +789,7 @@ brw_vs_get_binding_table(struct brw_context *brw) /** - * Vertex shader surfaces. Just constant buffer for now. Could add vertex - * shader textures in the future. + * Vertex shader surfaces (constant buffer). */ static void prepare_vs_surfaces(struct brw_context *brw ) { @@ -824,8 +825,12 @@ prepare_surfaces(struct brw_context *brw) const struct brw_tracked_state brw_wm_surfaces = { .dirty = { - .mesa = _NEW_COLOR | _NEW_TEXTURE | _NEW_BUFFERS | _NEW_PROGRAM, - .brw = BRW_NEW_CONTEXT, + .mesa = (_NEW_COLOR | + _NEW_TEXTURE | + _NEW_BUFFERS | + _NEW_PROGRAM | + _NEW_PROGRAM_CONSTANTS), + .brw = (BRW_NEW_CONTEXT), .cache = 0 }, .prepare = prepare_surfaces, diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c index ecac5bf0207..4f4ea45b74f 100644 --- a/src/mesa/drivers/dri/intel/intel_buffers.c +++ b/src/mesa/drivers/dri/intel/intel_buffers.c @@ -157,7 +157,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) /* Do this here, not core Mesa, since this function is called from * many places within the driver. */ - if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { + if (ctx->NewState & _NEW_BUFFERS) { /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ _mesa_update_framebuffer(ctx); /* this updates the DrawBuffer's Width/Height if it's a FBO */ @@ -326,7 +326,8 @@ intelDrawBuffer(GLcontext * ctx, GLenum mode) const GLboolean was_front_buffer_rendering = intel->is_front_buffer_rendering; - intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT); + intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) + || (mode == GL_FRONT); /* If we weren't front-buffer rendering before but we are now, make sure * that the front-buffer has actually been allocated. diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c index 2fcc87c0f5a..81ee1ed022c 100644 --- a/src/mesa/drivers/dri/r200/r200_state.c +++ b/src/mesa/drivers/dri/r200/r200_state.c @@ -2480,11 +2480,11 @@ void r200ValidateState( GLcontext *ctx ) r200ContextPtr rmesa = R200_CONTEXT(ctx); GLuint new_state = rmesa->NewGLState; - if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { + if (new_state & _NEW_BUFFERS) { r200UpdateDrawBuffer(ctx); } - if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) { + if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) { r200UpdateTextureState( ctx ); new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */ r200UpdateLocalViewer( ctx ); @@ -2523,6 +2523,7 @@ void r200ValidateState( GLcontext *ctx ) } if (new_state & (_NEW_PROGRAM| + _NEW_PROGRAM_CONSTANTS | /* need to test for pretty much anything due to possible parameter bindings */ _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM| _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX| diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c index 873cde44144..2f45429cf27 100644 --- a/src/mesa/drivers/dri/r300/r300_fragprog.c +++ b/src/mesa/drivers/dri/r300/r300_fragprog.c @@ -470,7 +470,8 @@ void r300TranslateFragmentShader(r300ContextPtr r300, fp->translated = GL_TRUE; if (fp->error || (RADEON_DEBUG & DEBUG_PIXEL)) r300FragmentProgramDump(fp, &fp->code); - r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM); + r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM | + _NEW_PROGRAM_CONSTANTS); } update_params(r300, fp); diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index 79f0b3625ca..07299f3b36f 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -1109,7 +1109,7 @@ void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state) struct gl_program_parameter_list *paramList; GLuint i; - if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM))) + if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS))) return; fp = (struct r300_fragment_program *)ctx->FragmentProgram._Current; @@ -2357,11 +2357,12 @@ void r300UpdateShaders(r300ContextPtr rmesa) hw_tcl_on = future_hw_tcl_on = 0; r300ResetHwState(rmesa); - r300UpdateStateParameters(ctx, _NEW_PROGRAM); + r300UpdateStateParameters(ctx, _NEW_PROGRAM | + _NEW_PROGRAM_CONSTANTS); return; } } - r300UpdateStateParameters(ctx, _NEW_PROGRAM); + r300UpdateStateParameters(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); } static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx, @@ -2588,7 +2589,7 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state) _tnl_InvalidateState(ctx, new_state); _ae_invalidate_state(ctx, new_state); - if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { + if (new_state & _NEW_BUFFERS) { r300UpdateDrawBuffer(ctx); } diff --git a/src/mesa/drivers/dri/r300/r500_fragprog.c b/src/mesa/drivers/dri/r300/r500_fragprog.c index 292573de893..300559d0b4d 100644 --- a/src/mesa/drivers/dri/r300/r500_fragprog.c +++ b/src/mesa/drivers/dri/r300/r500_fragprog.c @@ -501,7 +501,8 @@ void r500TranslateFragmentShader(r300ContextPtr r300, _mesa_reference_program(r300->radeon.glCtx, &compiler.program, 0); - r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM); + r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM | + _NEW_PROGRAM_CONSTANTS); if (RADEON_DEBUG & DEBUG_PIXEL) { if (fp->translated) { diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c index b6561001e76..4432f85691e 100644 --- a/src/mesa/drivers/dri/radeon/radeon_state.c +++ b/src/mesa/drivers/dri/radeon/radeon_state.c @@ -2255,7 +2255,7 @@ void radeonValidateState( GLcontext *ctx ) radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLuint new_state = rmesa->NewGLState; - if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { + if (new_state & _NEW_BUFFERS) { radeonUpdateDrawBuffer(ctx); } diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index 305df548fa2..9a01465bdf9 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -912,8 +912,9 @@ xmesa_update_state( GLcontext *ctx, GLbitfield new_state ) /* * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect * renderbuffer span/clear funcs. + * Check _NEW_COLOR to detect dither enable/disable. */ - if (new_state & (_NEW_COLOR | _NEW_PIXEL | _NEW_BUFFERS)) { + if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) { XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); struct xmesa_renderbuffer *front_xrb, *back_xrb; diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index c5f13345f04..d8b5f3b1f4a 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -443,7 +443,7 @@ _mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex) fb->ColorReadBuffer = buffer; fb->_ColorReadBufferIndex = bufferIndex; - ctx->NewState |= _NEW_PIXEL; + ctx->NewState |= _NEW_BUFFERS; } diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 016284de9aa..d780f91f048 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1522,4 +1522,17 @@ _mesa_Flush(void) } +/** + * Set mvp_with_dp4 flag. If a driver has a preference for DP4 over + * MUL/MAD, or vice versa, call this function to register that. + * Otherwise we default to MUL/MAD. + */ +void +_mesa_set_mvp_with_dp4( GLcontext *ctx, + GLboolean flag ) +{ + ctx->mvp_with_dp4 = flag; +} + + /*@}*/ diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h index ecc1cec7799..5b57d88029c 100644 --- a/src/mesa/main/context.h +++ b/src/mesa/main/context.h @@ -151,6 +151,10 @@ extern struct _glapi_table * _mesa_get_dispatch(GLcontext *ctx); +void +_mesa_set_mvp_with_dp4( GLcontext *ctx, + GLboolean flag ); + /** \name Miscellaneous */ /*@{*/ diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c index 1ce5685af45..43325b13529 100644 --- a/src/mesa/main/ffvertex_prog.c +++ b/src/mesa/main/ffvertex_prog.c @@ -315,12 +315,6 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) */ #define DISASSEM 0 -/* Should be tunable by the driver - do we want to do matrix - * multiplications with DP4's or with MUL/MAD's? SSE works better - * with the latter, drivers may differ. - */ -#define PREFER_DP4 0 - /* Use uregs to represent registers internally, translate to Mesa's * expected formats on emit. @@ -348,6 +342,7 @@ struct tnl_program { const struct state_key *state; struct gl_vertex_program *program; GLint max_inst; /** number of instructions allocated for program */ + GLboolean mvp_with_dp4; GLuint temp_in_use; GLuint temp_reserved; @@ -775,7 +770,7 @@ static struct ureg get_eye_position( struct tnl_program *p ) p->eye_position = reserve_temp(p); - if (PREFER_DP4) { + if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 0, modelview ); @@ -881,7 +876,7 @@ static void build_hpos( struct tnl_program *p ) struct ureg hpos = register_output( p, VERT_RESULT_HPOS ); struct ureg mvp[4]; - if (PREFER_DP4) { + if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, 0, mvp ); emit_matrix_transform_vec4( p, hpos, mvp, pos ); @@ -1574,7 +1569,7 @@ static void build_texture_transform( struct tnl_program *p ) struct ureg in = (!is_undef(out_texgen) ? out_texgen : register_input(p, VERT_ATTRIB_TEX0+i)); - if (PREFER_DP4) { + if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, 0, texmat ); emit_matrix_transform_vec4( p, out, texmat, in ); @@ -1708,6 +1703,7 @@ static void build_tnl_program( struct tnl_program *p ) static void create_new_program( const struct state_key *key, struct gl_vertex_program *program, + GLboolean mvp_with_dp4, GLuint max_temps) { struct tnl_program p; @@ -1721,6 +1717,7 @@ create_new_program( const struct state_key *key, p.transformed_normal = undef; p.identity = undef; p.temp_in_use = 0; + p.mvp_with_dp4 = mvp_with_dp4; if (max_temps >= sizeof(int) * 8) p.temp_reserved = 0; @@ -1776,6 +1773,7 @@ _mesa_get_fixed_func_vertex_program(GLcontext *ctx) return NULL; create_new_program( &key, prog, + ctx->mvp_with_dp4, ctx->Const.VertexProgram.MaxTemps ); #if 0 diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 30c7cca3b5a..587dc801466 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1028,7 +1028,7 @@ struct gl_stencil_attrib /** * An index for each type of texture object. These correspond to the GL - * target target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc. + * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc. * Note: the order is from highest priority to lowest priority. */ typedef enum @@ -2050,6 +2050,9 @@ struct gl_shared_state /** Default texture objects (shared by all texture units) */ struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS]; + /** Fallback texture used when a bound texture is incomplete */ + struct gl_texture_object *FallbackTex; + /** * \name Thread safety and statechange notification for texture * objects. @@ -2977,6 +2980,12 @@ struct __GLcontextRec /** software compression/decompression supported or not */ GLboolean Mesa_DXTn; + /** + * Use dp4 (rather than mul/mad) instructions for position + * transformation? + */ + GLboolean mvp_with_dp4; + /** Core tnl module support */ struct gl_tnl_module TnlModule; diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index b63f747fe8d..0024efc0e64 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -662,6 +662,59 @@ _mesa_test_texobj_completeness( const GLcontext *ctx, } } + +/** + * Return pointer to a default/fallback texture. + * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1). + * That's the value a sampler should get when sampling from an + * incomplete texture. + */ +struct gl_texture_object * +_mesa_get_fallback_texture(GLcontext *ctx) +{ + if (!ctx->Shared->FallbackTex) { + /* create fallback texture now */ + static GLubyte texels[8 * 8][4]; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLuint i; + + for (i = 0; i < 8 * 8; i++) { + texels[i][0] = + texels[i][1] = + texels[i][2] = 0x0; + texels[i][3] = 0xff; + } + + /* create texture object */ + texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D); + assert(texObj->RefCount == 1); + texObj->MinFilter = GL_NEAREST; + texObj->MagFilter = GL_NEAREST; + + /* create level[0] texture image */ + texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0); + + /* init the image fields */ + _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage, + 8, 8, 1, 0, GL_RGBA); + + /* set image data */ + ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA, + 8, 8, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texels, + &ctx->DefaultPacking, texObj, texImage); + + _mesa_test_texobj_completeness(ctx, texObj); + assert(texObj->_Complete); + + ctx->Shared->FallbackTex = texObj; + } + return ctx->Shared->FallbackTex; +} + + + /*@}*/ diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h index d5374c5d6c4..2599c0816a9 100644 --- a/src/mesa/main/texobj.h +++ b/src/mesa/main/texobj.h @@ -65,6 +65,9 @@ extern void _mesa_test_texobj_completeness( const GLcontext *ctx, struct gl_texture_object *obj ); +extern struct gl_texture_object * +_mesa_get_fallback_texture(GLcontext *ctx); + extern void _mesa_unlock_context_textures( GLcontext *ctx ); diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index 73f8a5339ec..32d55ba8d58 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -561,8 +561,13 @@ update_texture_state( GLcontext *ctx ) } if (!texUnit->_ReallyEnabled) { - _mesa_reference_texobj(&texUnit->_Current, NULL); - continue; + /* If we get here it means the shader (or fixed-function state) + * is expecting a texture object, but there isn't one (or it's + * incomplete). Use the fallback texture. + */ + struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx); + texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX; + _mesa_reference_texobj(&texUnit->_Current, texObj); } /* if we get here, we know this texture unit is enabled */ diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h index ba027465d48..d4d3dd1a94e 100644 --- a/src/mesa/main/version.h +++ b/src/mesa/main/version.h @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 7.5 + * Version: 7.6 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 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"), @@ -29,9 +30,9 @@ /* Mesa version */ #define MESA_MAJOR 7 -#define MESA_MINOR 5 +#define MESA_MINOR 6 #define MESA_PATCH 0 -#define MESA_VERSION_STRING "7.5" +#define MESA_VERSION_STRING "7.6-devel" /* To make version comparison easy */ #define MESA_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c index 981565ab8f1..317d623a228 100644 --- a/src/mesa/shader/arbprogram.c +++ b/src/mesa/shader/arbprogram.c @@ -74,8 +74,6 @@ _mesa_BindProgram(GLenum target, GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - /* Error-check target and get curProg */ if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */ (ctx->Extensions.NV_vertex_program || @@ -132,6 +130,9 @@ _mesa_BindProgram(GLenum target, GLuint id) return; } + /* signal new program (and its new constants) */ + FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + /* bind newProg */ if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, @@ -489,7 +490,7 @@ _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if (target == GL_FRAGMENT_PROGRAM_ARB && ctx->Extensions.ARB_fragment_program) { @@ -537,7 +538,7 @@ _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, GLfloat * dest; ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if (count <= 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)"); @@ -631,7 +632,7 @@ _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index, struct gl_program *prog; ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if ((target == GL_FRAGMENT_PROGRAM_NV && ctx->Extensions.NV_fragment_program) || @@ -685,7 +686,7 @@ _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if (count <= 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)"); diff --git a/src/mesa/shader/nvprogram.c b/src/mesa/shader/nvprogram.c index 5142c2a4a59..8ba521182b8 100644 --- a/src/mesa/shader/nvprogram.c +++ b/src/mesa/shader/nvprogram.c @@ -706,7 +706,7 @@ _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); prog = _mesa_lookup_program(ctx, id); if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 6ba2e76ff96..be903106a08 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -547,15 +547,13 @@ update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic) /** - * Find the live intervals for each temporary register in the program. - * For register R, the interval [A,B] indicates that R is referenced - * from instruction A through instruction B. - * Special consideration is needed for loops and subroutines. - * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason + * Find first/last instruction that references each temporary register. */ -static GLboolean -find_live_intervals(struct gl_program *prog, - struct interval_list *liveIntervals) +GLboolean +_mesa_find_temp_intervals(const struct prog_instruction *instructions, + GLuint numInstructions, + GLint intBegin[MAX_PROGRAM_TEMPS], + GLint intEnd[MAX_PROGRAM_TEMPS]) { struct loop_info { @@ -563,26 +561,15 @@ find_live_intervals(struct gl_program *prog, }; struct loop_info loopStack[MAX_LOOP_NESTING]; GLuint loopStackDepth = 0; - GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS]; GLuint i; - /* - * Note: we'll return GL_FALSE below if we find relative indexing - * into the TEMP register file. We can't handle that yet. - * We also give up on subroutines for now. - */ - - if (dbg) { - _mesa_printf("Optimize: Begin find intervals\n"); - } - for (i = 0; i < MAX_PROGRAM_TEMPS; i++){ intBegin[i] = intEnd[i] = -1; } /* Scan instructions looking for temporary registers */ - for (i = 0; i < prog->NumInstructions; i++) { - const struct prog_instruction *inst = prog->Instructions + i; + for (i = 0; i < numInstructions; i++) { + const struct prog_instruction *inst = instructions + i; if (inst->Opcode == OPCODE_BGNLOOP) { loopStack[loopStackDepth].Start = i; loopStack[loopStackDepth].End = inst->BranchTarget; @@ -595,7 +582,7 @@ find_live_intervals(struct gl_program *prog, return GL_FALSE; } else { - const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); + const GLuint numSrc = 3;/*_mesa_num_inst_src_regs(inst->Opcode);*/ GLuint j; for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { @@ -624,6 +611,39 @@ find_live_intervals(struct gl_program *prog, } } + return GL_TRUE; +} + + +/** + * Find the live intervals for each temporary register in the program. + * For register R, the interval [A,B] indicates that R is referenced + * from instruction A through instruction B. + * Special consideration is needed for loops and subroutines. + * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason + */ +static GLboolean +find_live_intervals(struct gl_program *prog, + struct interval_list *liveIntervals) +{ + GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS]; + GLuint i; + + /* + * Note: we'll return GL_FALSE below if we find relative indexing + * into the TEMP register file. We can't handle that yet. + * We also give up on subroutines for now. + */ + + if (dbg) { + _mesa_printf("Optimize: Begin find intervals\n"); + } + + /* build intermediate arrays */ + if (!_mesa_find_temp_intervals(prog->Instructions, prog->NumInstructions, + intBegin, intEnd)) + return GL_FALSE; + /* Build live intervals list from intermediate arrays */ liveIntervals->Num = 0; for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { @@ -792,8 +812,6 @@ _mesa_reallocate_registers(struct gl_program *prog) } - - /** * Apply optimizations to the given program to eliminate unnecessary * instructions, temp regs, etc. diff --git a/src/mesa/shader/prog_optimize.h b/src/mesa/shader/prog_optimize.h index d102cfd9fc1..43894a27237 100644 --- a/src/mesa/shader/prog_optimize.h +++ b/src/mesa/shader/prog_optimize.h @@ -25,7 +25,19 @@ #ifndef PROG_OPT_H #define PROG_OPT_H + +#include "main/config.h" + + struct gl_program; +struct prog_instruction; + + +extern GLboolean +_mesa_find_temp_intervals(const struct prog_instruction *instructions, + GLuint numInstructions, + GLint intBegin[MAX_PROGRAM_TEMPS], + GLint intEnd[MAX_PROGRAM_TEMPS]); extern void _mesa_optimize_program(GLcontext *ctx, struct gl_program *program); diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index 9967f2978de..e6f9a910690 100644 --- a/src/mesa/shader/prog_print.c +++ b/src/mesa/shader/prog_print.c @@ -941,6 +941,10 @@ _mesa_write_shader_to_file(const struct gl_shader *shader) fprintf(f, "/*\n"); _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE); fprintf(f, "*/\n"); + fprintf(f, "/* Parameters / constants */\n"); + fprintf(f, "/*\n"); + _mesa_fprint_parameter_list(f, shader->Program->Parameters); + fprintf(f, "*/\n"); } fclose(f); diff --git a/src/mesa/shader/programopt.c b/src/mesa/shader/programopt.c index ecd98dc85c5..f70c75cec8e 100644 --- a/src/mesa/shader/programopt.c +++ b/src/mesa/shader/programopt.c @@ -45,8 +45,8 @@ * into a vertex program. * May be used to implement the position_invariant option. */ -void -_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) +static void +_mesa_insert_mvp_dp4_code(GLcontext *ctx, struct gl_vertex_program *vprog) { struct prog_instruction *newInst; const GLuint origLen = vprog->Base.NumInstructions; @@ -113,6 +113,121 @@ _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) } +static void +_mesa_insert_mvp_mad_code(GLcontext *ctx, struct gl_vertex_program *vprog) +{ + struct prog_instruction *newInst; + const GLuint origLen = vprog->Base.NumInstructions; + const GLuint newLen = origLen + 4; + GLuint hposTemp; + GLuint i; + + /* + * Setup state references for the modelview/projection matrix. + * XXX we should check if these state vars are already declared. + */ + static const gl_state_index mvpState[4][STATE_LENGTH] = { + { STATE_MVP_MATRIX, 0, 0, 0, STATE_MATRIX_TRANSPOSE }, + { STATE_MVP_MATRIX, 0, 1, 1, STATE_MATRIX_TRANSPOSE }, + { STATE_MVP_MATRIX, 0, 2, 2, STATE_MATRIX_TRANSPOSE }, + { STATE_MVP_MATRIX, 0, 3, 3, STATE_MATRIX_TRANSPOSE }, + }; + GLint mvpRef[4]; + + for (i = 0; i < 4; i++) { + mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters, + mvpState[i]); + } + + /* Alloc storage for new instructions */ + newInst = _mesa_alloc_instructions(newLen); + if (!newInst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glProgramString(inserting position_invariant code)"); + return; + } + + /* TEMP hposTemp; */ + hposTemp = vprog->Base.NumTemporaries++; + + /* + * Generated instructions: + * emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]); + * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp); + * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp); + * emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp); + */ + _mesa_init_instructions(newInst, 4); + + newInst[0].Opcode = OPCODE_MUL; + newInst[0].DstReg.File = PROGRAM_TEMPORARY; + newInst[0].DstReg.Index = hposTemp; + newInst[0].DstReg.WriteMask = WRITEMASK_XYZW; + newInst[0].SrcReg[0].File = PROGRAM_INPUT; + newInst[0].SrcReg[0].Index = VERT_ATTRIB_POS; + newInst[0].SrcReg[0].Swizzle = SWIZZLE_XXXX; + newInst[0].SrcReg[1].File = PROGRAM_STATE_VAR; + newInst[0].SrcReg[1].Index = mvpRef[0]; + newInst[0].SrcReg[1].Swizzle = SWIZZLE_NOOP; + + for (i = 1; i <= 2; i++) { + newInst[i].Opcode = OPCODE_MAD; + newInst[i].DstReg.File = PROGRAM_TEMPORARY; + newInst[i].DstReg.Index = hposTemp; + newInst[i].DstReg.WriteMask = WRITEMASK_XYZW; + newInst[i].SrcReg[0].File = PROGRAM_INPUT; + newInst[i].SrcReg[0].Index = VERT_ATTRIB_POS; + newInst[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(i,i,i,i); + newInst[i].SrcReg[1].File = PROGRAM_STATE_VAR; + newInst[i].SrcReg[1].Index = mvpRef[i]; + newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; + newInst[i].SrcReg[2].File = PROGRAM_TEMPORARY; + newInst[i].SrcReg[2].Index = hposTemp; + newInst[1].SrcReg[2].Swizzle = SWIZZLE_NOOP; + } + + newInst[3].Opcode = OPCODE_MAD; + newInst[3].DstReg.File = PROGRAM_OUTPUT; + newInst[3].DstReg.Index = VERT_RESULT_HPOS; + newInst[3].DstReg.WriteMask = WRITEMASK_XYZW; + newInst[3].SrcReg[0].File = PROGRAM_INPUT; + newInst[3].SrcReg[0].Index = VERT_ATTRIB_POS; + newInst[3].SrcReg[0].Swizzle = SWIZZLE_WWWW; + newInst[3].SrcReg[1].File = PROGRAM_STATE_VAR; + newInst[3].SrcReg[1].Index = mvpRef[3]; + newInst[3].SrcReg[1].Swizzle = SWIZZLE_NOOP; + newInst[3].SrcReg[2].File = PROGRAM_TEMPORARY; + newInst[3].SrcReg[2].Index = hposTemp; + newInst[3].SrcReg[2].Swizzle = SWIZZLE_NOOP; + + + /* Append original instructions after new instructions */ + _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen); + + /* free old instructions */ + _mesa_free_instructions(vprog->Base.Instructions, origLen); + + /* install new instructions */ + vprog->Base.Instructions = newInst; + vprog->Base.NumInstructions = newLen; + vprog->Base.InputsRead |= VERT_BIT_POS; + vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS); +} + + +void +_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) +{ + if (ctx->mvp_with_dp4) + _mesa_insert_mvp_dp4_code( ctx, vprog ); + else + _mesa_insert_mvp_mad_code( ctx, vprog ); +} + + + + + /** * Append extra instructions onto the given fragment program to implement diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 644cd39185c..8f414a08891 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -1487,7 +1487,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program) return; } - FLUSH_VERTICES(ctx, _NEW_PROGRAM); + FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); if (program) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); @@ -1789,7 +1789,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, return; } - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); uniform = &shProg->Uniforms->Uniforms[location]; @@ -1929,7 +1929,7 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, return; } - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); uniform = &shProg->Uniforms->Uniforms[location]; diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index df0f0931eab..f23186c73de 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -123,6 +123,7 @@ update_framebuffer_state( struct st_context *st ) framebuffer->cbufs[framebuffer->nr_cbufs] = strb->surface; framebuffer->nr_cbufs++; } + strb->defined = GL_TRUE; /* we'll be drawing something */ } } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index e003b6db5cf..c249f3b3578 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -125,6 +125,8 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, strb->Base.Height = height; init_renderbuffer_bits(strb, template.format); + strb->defined = GL_FALSE; /* undefined contents now */ + /* Probably need dedicated flags for surface usage too: */ surface_usage = (PIPE_BUFFER_USAGE_GPU_READ | @@ -462,6 +464,134 @@ st_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) } +/** + * Copy back color buffer to front color buffer. + */ +static void +copy_back_to_front(struct st_context *st, + struct gl_framebuffer *fb, + gl_buffer_index frontIndex, + gl_buffer_index backIndex) + +{ + struct st_framebuffer *stfb = (struct st_framebuffer *) fb; + struct pipe_surface *surf_front, *surf_back; + + (void) st_get_framebuffer_surface(stfb, frontIndex, &surf_front); + (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back); + + if (surf_front && surf_back) { + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); + } +} + + +/** + * Check if we're drawing into, or read from, a front color buffer. If the + * front buffer is missing, create it now. + * + * The back color buffer must exist since we'll use its format/samples info + * for creating the front buffer. + * + * \param frontIndex either BUFFER_FRONT_LEFT or BUFFER_FRONT_RIGHT + * \param backIndex either BUFFER_BACK_LEFT or BUFFER_BACK_RIGHT + */ +static void +check_create_front_buffer(GLcontext *ctx, struct gl_framebuffer *fb, + gl_buffer_index frontIndex, + gl_buffer_index backIndex) +{ + if (fb->Attachment[frontIndex].Renderbuffer == NULL) { + GLboolean create = GL_FALSE; + + /* check if drawing to or reading from front buffer */ + if (fb->_ColorReadBufferIndex == frontIndex) { + create = GL_TRUE; + } + else { + GLuint b; + for (b = 0; b < fb->_NumColorDrawBuffers; b++) { + if (fb->_ColorDrawBufferIndexes[b] == frontIndex) { + create = GL_TRUE; + break; + } + } + } + + if (create) { + struct st_renderbuffer *back; + struct gl_renderbuffer *front; + enum pipe_format colorFormat; + uint samples; + + if (0) + _mesa_debug(ctx, "Allocate new front buffer\n"); + + /* get back renderbuffer info */ + back = st_renderbuffer(fb->Attachment[backIndex].Renderbuffer); + colorFormat = back->format; + samples = back->Base.NumSamples; + + /* create front renderbuffer */ + front = st_new_renderbuffer_fb(colorFormat, samples); + _mesa_add_renderbuffer(fb, frontIndex, front); + + /* alloc texture/surface for new front buffer */ + front->AllocStorage(ctx, front, front->InternalFormat, + fb->Width, fb->Height); + + /* initialize the front color buffer contents by copying + * the back buffer. + */ + copy_back_to_front(ctx->st, fb, frontIndex, backIndex); + } + } +} + + +/** + * If front left/right color buffers are missing, create them now. + */ +static void +check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb) +{ + /* check if we need to create the front left buffer now */ + check_create_front_buffer(ctx, fb, BUFFER_FRONT_LEFT, BUFFER_BACK_LEFT); + + if (fb->Visual.stereoMode) { + check_create_front_buffer(ctx, fb, BUFFER_FRONT_RIGHT, BUFFER_BACK_RIGHT); + } + + st_invalidate_state(ctx, _NEW_BUFFERS); +} + + +/** + * Called via glDrawBuffer. + */ +static void +st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) +{ + (void) count; + (void) buffers; + check_create_front_buffers(ctx, ctx->DrawBuffer); +} + + +/** + * Called via glReadBuffer. + */ +static void +st_ReadBuffer(GLcontext *ctx, GLenum buffer) +{ + (void) buffer; + check_create_front_buffers(ctx, ctx->ReadBuffer); +} + + void st_init_fbo_functions(struct dd_function_table *functions) { functions->NewFramebuffer = st_new_framebuffer; @@ -474,4 +604,7 @@ void st_init_fbo_functions(struct dd_function_table *functions) /* no longer needed by core Mesa, drivers handle resizes... functions->ResizeBuffers = st_resize_buffers; */ + + functions->DrawBuffers = st_DrawBuffers; + functions->ReadBuffer = st_ReadBuffer; } diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index 44fa9fe9a4f..fd77d0a95b0 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -44,6 +44,7 @@ struct st_renderbuffer struct pipe_texture *texture; struct pipe_surface *surface; /* temporary view into texture */ enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ + GLboolean defined; /**< defined contents? */ struct st_texture_object *rtt; /**< GL render to texture's texture */ int rtt_level, rtt_face, rtt_slice; diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index fbaffd154f9..8ceeeabcd37 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -47,10 +47,19 @@ #include "util/u_blit.h" +/** Check if we have a front color buffer and if it's been drawn to. */ static INLINE GLboolean is_front_buffer_dirty(struct st_context *st) { - return st->frontbuffer_status == FRONT_STATUS_DIRTY; + if (st->frontbuffer_status == FRONT_STATUS_DIRTY) { + return GL_TRUE; + } + else { + GLframebuffer *fb = st->ctx->DrawBuffer; + struct st_renderbuffer *strb + = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + return strb && strb->defined; + } } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 92a630eff97..2a1f21c51ca 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -177,6 +177,12 @@ struct st_context *st_create_context(struct pipe_context *pipe, ctx = _mesa_create_context(visual, shareCtx, &funcs, NULL); + /* XXX: need a capability bit in gallium to query if the pipe + * driver prefers DP4 or MUL/MAD for vertex transformation. + */ + if (debug_get_bool_option("MESA_MVP_DP4", FALSE)) + _mesa_set_mvp_with_dp4( ctx, GL_TRUE ); + return st_create_context_priv(ctx, pipe); } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 6ffed56d9a0..18adb35e872 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -45,6 +45,7 @@ struct blit_state; struct bitmap_cache; +/** XXX we'd like to get rid of these */ #define FRONT_STATUS_UNDEFINED 0 #define FRONT_STATUS_DIRTY 1 #define FRONT_STATUS_COPY_OF_BACK 2 @@ -111,7 +112,7 @@ struct st_context struct gl_fragment_program *fragment_program; } cb; - GLuint frontbuffer_status; /**< one of FRONT_STATUS_ */ + GLuint frontbuffer_status; /**< one of FRONT_STATUS_ (XXX to be removed) */ char vendor[100]; char renderer[100]; diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index daaad65ccaf..ef800291ccd 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -58,19 +58,19 @@ st_create_framebuffer( const __GLcontextModes *visual, _mesa_initialize_framebuffer(&stfb->Base, visual); - { - /* fake frontbuffer */ - /* XXX allocation should only happen in the unusual case - it's actually needed */ + if (visual->doubleBufferMode) { struct gl_renderbuffer *rb = st_new_renderbuffer_fb(colorFormat, samples); - _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb); + _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb); } - - if (visual->doubleBufferMode) { + else { + /* Only allocate front buffer right now if we're single buffered. + * If double-buffered, allocate front buffer on demand later. + * See check_create_front_buffers(). + */ struct gl_renderbuffer *rb = st_new_renderbuffer_fb(colorFormat, samples); - _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb); + _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb); } if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) { @@ -293,6 +293,115 @@ st_notify_swapbuffers(struct st_framebuffer *stfb) } +/** + * Swap the front/back color buffers. Exchange the front/back pointers + * and update some derived state. + * No need to call st_notify_swapbuffers() first. + * + * For a single-buffered framebuffer, no swap occurs, but we still return + * the pointer(s) to the front color buffer(s). + * + * \param front_left returns pointer to front-left renderbuffer after swap + * \param front_right returns pointer to front-right renderbuffer after swap + */ +void +st_swapbuffers(struct st_framebuffer *stfb, + struct pipe_surface **front_left, + struct pipe_surface **front_right) +{ + struct gl_framebuffer *fb = &stfb->Base; + + GET_CURRENT_CONTEXT(ctx); + + if (ctx && ctx->DrawBuffer == &stfb->Base) { + st_flush( ctx->st, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL ); + } + + if (!fb->Visual.doubleBufferMode) { + /* single buffer mode - return pointers to front surfaces */ + if (front_left) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + *front_left = strb->surface; + } + if (front_right) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer); + *front_right = strb ? strb->surface : NULL; + } + return; + } + + /* swap left buffers */ + if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer && + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) { + struct gl_renderbuffer *rbTemp; + rbTemp = fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer = + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer; + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer = rbTemp; + if (front_left) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + *front_left = strb->surface; + } + /* mark back buffer contents as undefined */ + { + struct st_renderbuffer *back = + st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + back->defined = GL_FALSE; + } + } + else { + /* no front buffer, display the back buffer */ + if (front_left) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + *front_left = strb->surface; + } + } + + /* swap right buffers (for stereo) */ + if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer && + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) { + struct gl_renderbuffer *rbTemp; + rbTemp = fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer; + fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer = + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer; + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer = rbTemp; + if (front_right) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer); + *front_right = strb->surface; + } + /* mark back buffer contents as undefined */ + { + struct st_renderbuffer *back = + st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); + back->defined = GL_FALSE; + } + } + else { + /* no front right buffer, display back right buffer (if exists) */ + if (front_right) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); + *front_right = strb ? strb->surface : NULL; + } + } + + /* Update the _ColorDrawBuffers[] array and _ColorReadBuffer pointer */ + _mesa_update_framebuffer(ctx); + + /* Make sure we draw into the new back surface */ + st_invalidate_state(ctx, _NEW_BUFFERS); +} + + void *st_framebuffer_private( struct st_framebuffer *stfb ) { return stfb->Private; diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h index 290b8a974e6..174fbc63941 100644 --- a/src/mesa/state_tracker/st_public.h +++ b/src/mesa/state_tracker/st_public.h @@ -103,6 +103,10 @@ void st_finish( struct st_context *st ); void st_notify_swapbuffers(struct st_framebuffer *stfb); +void st_swapbuffers(struct st_framebuffer *stfb, + struct pipe_surface **front_left, + struct pipe_surface **front_right); + int st_set_teximage(struct pipe_texture *pt, int target); /** Redirect rendering into stfb's surface to a texture image */ |