diff options
Diffstat (limited to 'src/mesa')
207 files changed, 4280 insertions, 3159 deletions
diff --git a/src/mesa/Makefile b/src/mesa/Makefile index 25e7cce425c..48f79a5d550 100644 --- a/src/mesa/Makefile +++ b/src/mesa/Makefile @@ -7,7 +7,7 @@ MESA_LIBS := libmesa.a libmesagallium.a DEPENDS := depend MESA_OBJ_DIR := . - +DRICORE_OBJ_DIR := objs-dricore include sources.mak @@ -15,27 +15,35 @@ include sources.mak MESA_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_OBJECTS)) MESA_GALLIUM_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_GALLIUM_OBJECTS)) +DRICORE_OBJECTS := $(addprefix $(DRICORE_OBJ_DIR)/, $(MESA_OBJECTS)) + # define preprocessor flags MESA_CPPFLAGS := $(API_DEFINES) $(DEFINES) # append include dirs -MESA_CPPFLAGS += $(INCLUDE_DIRS) $(TALLOC_CFLAGS) +MESA_CPPFLAGS += $(INCLUDE_DIRS) + +DRICORE_CPPFLAGS = $(MESA_CPPFLAGS) # tidy compiler flags CFLAGS := $(filter-out $(DEFINES), $(CFLAGS)) CXXFLAGS := $(filter-out $(DEFINES), $(CXXFLAGS)) # LLVM is needed for the state tracker -MESA_CFLAGS := $(LLVM_CFLAGS) +MESA_CFLAGS := $(LLVM_CFLAGS) $(CFLAGS) +DRICORE_CFLAGS := $(LLVM_CFLAGS) $(DRI_CFLAGS) + +MESA_CXXFLAGS := $(LLVM_CFLAGS) $(CXXFLAGS) +DRICORE_CXXFLAGS := $(LLVM_CFLAGS) $(DRI_CXXFLAGS) define mesa-cc-c @mkdir -p $(dir $@) - $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CFLAGS) + $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) endef define mesa-cxx-c @mkdir -p $(dir $@) - $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CXXFLAGS) + $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $($(1)_CXXFLAGS) endef $(MESA_OBJ_DIR)/%.o: %.c @@ -47,9 +55,18 @@ $(MESA_OBJ_DIR)/%.o: %.cpp $(MESA_OBJ_DIR)/%.o: %.S $(call mesa-cc-c,MESA) +$(DRICORE_OBJ_DIR)/%.o: %.c + $(call mesa-cc-c,DRICORE) + +$(DRICORE_OBJ_DIR)/%.o: %.cpp + $(call mesa-cxx-c,DRICORE) + +$(DRICORE_OBJ_DIR)/%.o: %.S + $(call mesa-cc-c,DRICORE) + # Default: build dependencies, then asm_subdirs, GLSL built-in lib, # then convenience libs (.a) and finally the device drivers: -default: $(DEPENDS) asm_subdirs $(MESA_LIBS) driver_subdirs +default: $(DEPENDS) asm_subdirs $(MESA_LIBS) $(DRICORE_LIBS) driver_subdirs main/api_exec_es1.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py main/APIspec.py $(PYTHON2) $(PYTHON_FLAGS) main/es_generator.py -S main/APIspec.xml -V GLES1.1 > $@ @@ -64,13 +81,20 @@ main/api_exec_es2.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py m libmesa.a: $(MESA_OBJECTS) $(GLSL_LIBS) @ $(MKLIB) -o mesa -static $(MESA_OBJECTS) $(GLSL_LIBS) +# Shared dricore library for classic DRI drivers +$(TOP)/$(LIB_DIR)/libdricore.so: $(DRICORE_OBJECTS) $(DRICORE_GLSL_LIBS) + @$(MKLIB) -o $@ -linker '$(CXX)' -ldflags '$(LDFLAGS)' \ + -cplusplus -noprefix \ + -install $(TOP)/$(LIB_DIR) -id $(DRI_DRIVER_INSTALL_DIR)/[email protected] \ + $(DRICORE_LIB_DEPS) $(DRICORE_OBJECTS) + # Make archive of subset of core mesa object files for gallium libmesagallium.a: $(MESA_GALLIUM_OBJECTS) $(GLSL_LIBS) @ $(MKLIB) -o mesagallium -static $(MESA_GALLIUM_OBJECTS) $(GLSL_LIBS) ###################################################################### # Device drivers -driver_subdirs: $(MESA_LIBS) +driver_subdirs: $(MESA_LIBS) $(DRICORE_LIBS) @ (cd drivers && $(MAKE)) @@ -102,9 +126,12 @@ depend: $(ALL_SOURCES) new_install: (cd drivers && $(MAKE) install) +ifneq (,$(DRICORE_LIBS)) +DRICORE_INSTALL_TARGET = install-dricore +endif # XXX replace this with new_install above someday -install: default +install: default $(DRICORE_INSTALL_TARGET) @for driver in $(DRIVER_DIRS) ; do \ case "$$driver" in \ osmesa) if [ "$(DRIVER_DIRS)" = osmesa ]; then \ @@ -166,13 +193,22 @@ install-osmesa: default osmesa.pc install-dri: default cd drivers/dri && $(MAKE) install +# We don't need MINSTALL here because we're not installing symbolic links +install-dricore: default + $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) + $(INSTALL) -m 755 $(DRICORE_LIBS) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) # Emacs tags tags: etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h -clean: +clean-dricore: + -rm -f libdricore.so + -rm -f $(DRICORE_LIBS) + -rm -rf $(DRICORE_OBJ_DIR) + +clean: clean-dricore -rm -f */*.o -rm -f */*/*.o -rm -f depend depend.bak libmesa.a libmesagallium.a diff --git a/src/mesa/SConscript b/src/mesa/SConscript index cc4ad09fa33..ea04fb1a0ee 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -12,12 +12,18 @@ env.Append(CPPPATH = [ '#/src/mesa', ]) +env.Append(CPPDEFINES = [ + 'FEATURE_GL=1', +]) + if env['platform'] == 'windows': env.Append(CPPDEFINES = [ '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers ]) - env.Prepend(CPPPATH = ['#src/talloc']) + if not env['gles']: + # prevent _glapi_* from being declared __declspec(dllimport) + env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS']) else: env.Append(CPPDEFINES = [ 'IN_DRI_DRIVER', # enable the remap table (for DRI drivers) @@ -240,6 +246,61 @@ mesa_sources = ( statetracker_sources ) +if env['gles']: + from sys import executable as python_cmd + + env.Append(CPPDEFINES = ['FEATURE_ES1=1', 'FEATURE_ES2=1']) + + # generate GLES sources + gles_sources = [] + gles_sources += env.CodeGenerate( + target = 'main/api_exec_es1.c', + script = 'main/es_generator.py', + source = 'main/APIspec.xml', + command = python_cmd + ' $SCRIPT -S $SOURCE -V GLES1.1 > $TARGET' + ) + gles_sources += env.CodeGenerate( + target = 'main/api_exec_es2.c', + script = 'main/es_generator.py', + source = 'main/APIspec.xml', + command = python_cmd + ' $SCRIPT -S $SOURCE -V GLES2.0 > $TARGET' + ) + + # generate GLES headers + GLAPI = '#src/mapi/glapi/' + gles_headers = [] + gles_headers += env.CodeGenerate( + target = 'es1api/main/glapidispatch.h', + script = GLAPI + 'gen/gl_table.py', + source = GLAPI + 'gen-es/es1_API.xml', + command = python_cmd + ' $SCRIPT -c -m remap_table -f $SOURCE > $TARGET', + ) + gles_headers += env.CodeGenerate( + target = 'es1api/main/remap_helper.h', + script = GLAPI + 'gen/remap_helper.py', + source = GLAPI + 'gen-es/es1_API.xml', + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET', + ) + gles_headers += env.CodeGenerate( + target = 'es2api/main/glapidispatch.h', + script = GLAPI + 'gen/gl_table.py', + source = GLAPI + 'gen-es/es2_API.xml', + command = python_cmd + ' $SCRIPT -c -m remap_table -f $SOURCE > $TARGET', + ) + gles_headers += env.CodeGenerate( + target = 'es2api/main/remap_helper.h', + script = GLAPI + 'gen/remap_helper.py', + source = GLAPI + 'gen-es/es2_API.xml', + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET', + ) + + env.Depends(gles_sources, gles_headers) + + # gles_sources #include gles_headers with full path + env.Append(CPPPATH = [gles_headers[0].dir.up().up()]) + + mesa_sources += gles_sources + # # Assembly sources # diff --git a/src/mesa/drivers/beos/GLView.cpp b/src/mesa/drivers/beos/GLView.cpp index ee3415b3d1a..57c4614f32d 100644 --- a/src/mesa/drivers/beos/GLView.cpp +++ b/src/mesa/drivers/beos/GLView.cpp @@ -50,7 +50,6 @@ extern "C" { #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" @@ -319,7 +318,8 @@ BGLView::BGLView(BRect rect, char *name, functions.Viewport = md->Viewport; // create core context - struct gl_context *ctx = _mesa_create_context(visual, NULL, &functions, md); + struct gl_context *ctx = _mesa_create_context(API_OPENGL, visual, + NULL, &functions, md); if (! ctx) { _mesa_destroy_visual(visual); delete md; diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index 3c6ecb83f0a..5389a500111 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -184,6 +184,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->RenderTexture = _mesa_render_texture; driver->FinishRenderTexture = _mesa_finish_render_texture; driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; + driver->ValidateFramebuffer = _mesa_validate_framebuffer; driver->BlitFramebuffer = _swrast_BlitFramebuffer; diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template index 4ecddbc0483..d1a119379ed 100644 --- a/src/mesa/drivers/dri/Makefile.template +++ b/src/mesa/drivers/dri/Makefile.template @@ -1,7 +1,5 @@ # -*-makefile-*- -MESA_MODULES = $(TOP)/src/mesa/libmesa.a - COMMON_GALLIUM_SOURCES = \ ../common/utils.c \ ../common/vblank.c \ @@ -11,8 +9,7 @@ COMMON_GALLIUM_SOURCES = \ COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \ ../../common/driverfuncs.c \ ../common/texmem.c \ - ../common/drirenderbuffer.c \ - ../common/dri_metaops.c + ../common/drirenderbuffer.c INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES) @@ -39,13 +36,13 @@ CXXFLAGS += $(API_DEFINES) ##### RULES ##### .c.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DRIVER_DEFINES) $< -o $@ .cpp.o: - $(CC) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(DRI_CXXFLAGS) $(DRIVER_DEFINES) $< -o $@ .S.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DRIVER_DEFINES) $< -o $@ ##### TARGETS ##### @@ -57,10 +54,10 @@ default: subdirs lib lib: symlinks subdirs depend @$(MAKE) $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME) -$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) Makefile \ +$(LIBNAME): $(OBJECTS) $(EXTRA_MODULES) $(MESA_MODULES) Makefile \ $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o $(MKLIB) -o [email protected] -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \ - $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS) + $(OBJECTS) $(EXTRA_MODULES) $(DRI_LIB_DEPS) $(CXX) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS) @rm -f [email protected] mv -f [email protected] $@ diff --git a/src/mesa/drivers/dri/common/dri_metaops.c b/src/mesa/drivers/dri/common/dri_metaops.c deleted file mode 100644 index e0bc3b88ecd..00000000000 --- a/src/mesa/drivers/dri/common/dri_metaops.c +++ /dev/null @@ -1,291 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * Copyright 2009 Intel Corporation. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "main/arbprogram.h" -#include "main/arrayobj.h" -#include "main/bufferobj.h" -#include "main/context.h" -#include "main/enable.h" -#include "main/matrix.h" -#include "main/texstate.h" -#include "main/varray.h" -#include "main/viewport.h" -#include "program/program.h" -#include "dri_metaops.h" - -void -meta_set_passthrough_transform(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - meta->saved_vp_x = ctx->Viewport.X; - meta->saved_vp_y = ctx->Viewport.Y; - meta->saved_vp_width = ctx->Viewport.Width; - meta->saved_vp_height = ctx->Viewport.Height; - meta->saved_matrix_mode = ctx->Transform.MatrixMode; - - meta->internal_viewport_call = GL_TRUE; - _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height); - meta->internal_viewport_call = GL_FALSE; - - _mesa_MatrixMode(GL_PROJECTION); - _mesa_PushMatrix(); - _mesa_LoadIdentity(); - _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1); - - _mesa_MatrixMode(GL_MODELVIEW); - _mesa_PushMatrix(); - _mesa_LoadIdentity(); -} - -void -meta_restore_transform(struct dri_metaops *meta) -{ - _mesa_MatrixMode(GL_PROJECTION); - _mesa_PopMatrix(); - _mesa_MatrixMode(GL_MODELVIEW); - _mesa_PopMatrix(); - - _mesa_MatrixMode(meta->saved_matrix_mode); - - meta->internal_viewport_call = GL_TRUE; - _mesa_Viewport(meta->saved_vp_x, meta->saved_vp_y, - meta->saved_vp_width, meta->saved_vp_height); - meta->internal_viewport_call = GL_FALSE; -} - - -/** - * Set up a vertex program to pass through the position and first texcoord - * for pixel path. - */ -void -meta_set_passthrough_vertex_program(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - static const char *vp = - "!!ARBvp1.0\n" - "TEMP vertexClip;\n" - "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n" - "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n" - "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n" - "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n" - "MOV result.position, vertexClip;\n" - "MOV result.texcoord[0], vertex.texcoord[0];\n" - "MOV result.color, vertex.color;\n" - "END\n"; - - assert(meta->saved_vp == NULL); - - _mesa_reference_vertprog(ctx, &meta->saved_vp, - ctx->VertexProgram.Current); - if (meta->passthrough_vp == NULL) { - GLuint prog_name; - _mesa_GenPrograms(1, &prog_name); - _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name); - _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB, - GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(vp), (const GLubyte *)vp); - _mesa_reference_vertprog(ctx, &meta->passthrough_vp, - ctx->VertexProgram.Current); - _mesa_DeletePrograms(1, &prog_name); - } - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, - meta->passthrough_vp); - ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, - &meta->passthrough_vp->Base); - - meta->saved_vp_enable = ctx->VertexProgram.Enabled; - _mesa_Enable(GL_VERTEX_PROGRAM_ARB); -} - -/** - * Restores the previous vertex program after - * meta_set_passthrough_vertex_program() - */ -void -meta_restore_vertex_program(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, - meta->saved_vp); - _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL); - ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, - &ctx->VertexProgram.Current->Base); - - if (!meta->saved_vp_enable) - _mesa_Disable(GL_VERTEX_PROGRAM_ARB); -} - -/** - * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the - * program object. - */ -void -meta_set_fragment_program(struct dri_metaops *meta, - struct gl_fragment_program **prog, - const char *prog_string) -{ - struct gl_context *ctx = meta->ctx; - assert(meta->saved_fp == NULL); - - _mesa_reference_fragprog(ctx, &meta->saved_fp, - ctx->FragmentProgram.Current); - if (*prog == NULL) { - GLuint prog_name; - _mesa_GenPrograms(1, &prog_name); - _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name); - _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, - GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(prog_string), (const GLubyte *)prog_string); - _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current); - /* Note that DeletePrograms unbinds the program on us */ - _mesa_DeletePrograms(1, &prog_name); - } - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog); - ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base)); - - meta->saved_fp_enable = ctx->FragmentProgram.Enabled; - _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB); -} - -/** - * Restores the previous fragment program after - * meta_set_fragment_program() - */ -void -meta_restore_fragment_program(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, - meta->saved_fp); - _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL); - ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, - &ctx->FragmentProgram.Current->Base); - - if (!meta->saved_fp_enable) - _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB); -} - -static const float default_texcoords[4][2] = { { 0.0, 0.0 }, - { 1.0, 0.0 }, - { 1.0, 1.0 }, - { 0.0, 1.0 } }; - -void -meta_set_default_texrect(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - struct gl_client_array *old_texcoord_array; - - meta->saved_active_texture = ctx->Texture.CurrentUnit; - if (meta->saved_array_vbo == NULL) { - _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, - ctx->Array.ArrayBufferObj); - } - - old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0]; - meta->saved_texcoord_type = old_texcoord_array->Type; - meta->saved_texcoord_size = old_texcoord_array->Size; - meta->saved_texcoord_stride = old_texcoord_array->Stride; - meta->saved_texcoord_enable = old_texcoord_array->Enabled; - meta->saved_texcoord_ptr = old_texcoord_array->Ptr; - _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, - old_texcoord_array->BufferObj); - - _mesa_ClientActiveTextureARB(GL_TEXTURE0); - - if (meta->texcoord_vbo == NULL) { - GLuint vbo_name; - - _mesa_GenBuffersARB(1, &vbo_name); - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name); - _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords), - default_texcoords, GL_STATIC_DRAW_ARB); - _mesa_reference_buffer_object(ctx, &meta->texcoord_vbo, - ctx->Array.ArrayBufferObj); - } else { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, - meta->texcoord_vbo->Name); - } - _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL); - - _mesa_Enable(GL_TEXTURE_COORD_ARRAY); -} - -void -meta_restore_texcoords(struct dri_metaops *meta) -{ - struct gl_context *ctx = meta->ctx; - - /* Restore the old TexCoordPointer */ - if (meta->saved_texcoord_vbo) { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, - meta->saved_texcoord_vbo->Name); - _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, NULL); - } else { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - } - - _mesa_TexCoordPointer(meta->saved_texcoord_size, - meta->saved_texcoord_type, - meta->saved_texcoord_stride, - meta->saved_texcoord_ptr); - if (!meta->saved_texcoord_enable) - _mesa_Disable(GL_TEXTURE_COORD_ARRAY); - - _mesa_ClientActiveTextureARB(GL_TEXTURE0 + - meta->saved_active_texture); - - if (meta->saved_array_vbo) { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, - meta->saved_array_vbo->Name); - _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, NULL); - } else { - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - } -} - - -void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta) -{ - meta->ctx = ctx; -} - -void meta_destroy_metaops(struct dri_metaops *meta) -{ - -} diff --git a/src/mesa/drivers/dri/common/dri_metaops.h b/src/mesa/drivers/dri/common/dri_metaops.h deleted file mode 100644 index aa7d4baa6e9..00000000000 --- a/src/mesa/drivers/dri/common/dri_metaops.h +++ /dev/null @@ -1,81 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * Copyright 2009 Intel Corporation. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef DRI_METAOPS_H -#define DRI_METAOPS_H - - -struct dri_metaops { - struct gl_context *ctx; - GLboolean internal_viewport_call; - struct gl_fragment_program *bitmap_fp; - struct gl_vertex_program *passthrough_vp; - struct gl_buffer_object *texcoord_vbo; - - struct gl_fragment_program *saved_fp; - GLboolean saved_fp_enable; - struct gl_vertex_program *saved_vp; - GLboolean saved_vp_enable; - - struct gl_fragment_program *tex2d_fp; - - GLboolean saved_texcoord_enable; - struct gl_buffer_object *saved_array_vbo, *saved_texcoord_vbo; - GLenum saved_texcoord_type; - GLsizei saved_texcoord_size, saved_texcoord_stride; - const void *saved_texcoord_ptr; - int saved_active_texture; - - GLint saved_vp_x, saved_vp_y; - GLsizei saved_vp_width, saved_vp_height; - GLenum saved_matrix_mode; -}; - - -void meta_set_passthrough_transform(struct dri_metaops *meta); - -void meta_restore_transform(struct dri_metaops *meta); - -void meta_set_passthrough_vertex_program(struct dri_metaops *meta); - -void meta_restore_vertex_program(struct dri_metaops *meta); - -void meta_set_fragment_program(struct dri_metaops *meta, - struct gl_fragment_program **prog, - const char *prog_string); - -void meta_restore_fragment_program(struct dri_metaops *meta); - -void meta_set_default_texrect(struct dri_metaops *meta); - -void meta_restore_texcoords(struct dri_metaops *meta); - -void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta); -void meta_destroy_metaops(struct dri_metaops *meta); - -#endif diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index bf8cf6eec07..82638fa7207 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -481,6 +481,22 @@ dri2CreateNewDrawable(__DRIscreen *screen, return pdraw; } +static __DRIbuffer * +dri2AllocateBuffer(__DRIscreen *screen, + unsigned int attachment, unsigned int format, + int width, int height) +{ + return (*screen->DriverAPI.AllocateBuffer)(screen, attachment, format, + width, height); +} + +static void +dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) +{ + (*screen->DriverAPI.ReleaseBuffer)(screen, buffer); +} + + static int dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) { @@ -930,7 +946,9 @@ const __DRIdri2Extension driDRI2Extension = { dri2CreateNewDrawable, dri2CreateNewContext, dri2GetAPIMask, - dri2CreateNewContextForAPI + dri2CreateNewContextForAPI, + dri2AllocateBuffer, + dri2ReleaseBuffer }; const __DRI2configQueryExtension dri2ConfigQueryExtension = { diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index ffffb99b301..3d3d5c9cd24 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -223,6 +223,12 @@ struct __DriverAPIRec { /* DRI2 Entry point */ const __DRIconfig **(*InitScreen2) (__DRIscreen * priv); + + __DRIbuffer *(*AllocateBuffer) (__DRIscreen *screenPrivate, + unsigned int attachment, + unsigned int format, + int width, int height); + void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer); }; extern const struct __DriverAPIRec driDriverAPI; diff --git a/src/mesa/drivers/dri/common/drisw_util.c b/src/mesa/drivers/dri/common/drisw_util.c index 1529c23b16d..1bdb6d8939e 100644 --- a/src/mesa/drivers/dri/common/drisw_util.c +++ b/src/mesa/drivers/dri/common/drisw_util.c @@ -121,6 +121,48 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, return pcp; } +static __DRIcontext * +driCreateNewContextForAPI(__DRIscreen *psp, int api, + const __DRIconfig *config, + __DRIcontext *shared, void *data) +{ + __DRIcontext *pcp; + void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + gl_api mesa_api; + + switch (api) { + case __DRI_API_OPENGL: + mesa_api = API_OPENGL; + break; + case __DRI_API_GLES: + mesa_api = API_OPENGLES; + break; + case __DRI_API_GLES2: + mesa_api = API_OPENGLES2; + break; + default: + return NULL; + } + + pcp = CALLOC_STRUCT(__DRIcontextRec); + if (!pcp) + return NULL; + + pcp->loaderPrivate = data; + + pcp->driScreenPriv = psp; + pcp->driDrawablePriv = NULL; + pcp->driReadablePriv = NULL; + + if (!driDriverAPI.CreateContext(mesa_api, + &config->modes, pcp, shareCtx)) { + FREE(pcp); + return NULL; + } + + return pcp; +} + static void driDestroyContext(__DRIcontext *pcp) { @@ -269,5 +311,6 @@ const __DRIcoreExtension driCoreExtension = { const __DRIswrastExtension driSWRastExtension = { { __DRI_SWRAST, __DRI_SWRAST_VERSION }, driCreateNewScreen, - driCreateNewDrawable + driCreateNewDrawable, + driCreateNewContextForAPI }; diff --git a/src/mesa/drivers/dri/i810/i810context.c b/src/mesa/drivers/dri/i810/i810context.c index dc58e91e8c1..90dbb6bbe80 100644 --- a/src/mesa/drivers/dri/i810/i810context.c +++ b/src/mesa/drivers/dri/i810/i810context.c @@ -204,7 +204,7 @@ i810CreateContext( gl_api api, shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - imesa->glCtx = _mesa_create_context(mesaVis, shareCtx, + imesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx, &functions, (void*) imesa); if (!imesa->glCtx) { FREE(imesa); diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index ebdefeac874..19f08077599 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -364,7 +364,7 @@ i830_emit_invarient_state(struct intel_context *intel) #define emit( intel, state, size ) \ - intel_batchbuffer_data(intel->batch, state, size, false) + intel_batchbuffer_data(intel, state, size, false) static GLuint get_dirty(struct i830_hw_state *state) @@ -428,7 +428,7 @@ i830_emit_state(struct intel_context *intel) * scheduling is allowed, rather than assume that it is whenever a * batchbuffer fills up. */ - intel_batchbuffer_require_space(intel->batch, + intel_batchbuffer_require_space(intel, get_state_size(state) + INTEL_PRIM_EMIT_SIZE, false); count = 0; @@ -436,7 +436,7 @@ i830_emit_state(struct intel_context *intel) aper_count = 0; dirty = get_dirty(state); - aper_array[aper_count++] = intel->batch->buf; + aper_array[aper_count++] = intel->batch.bo; if (dirty & I830_UPLOAD_BUFFERS) { aper_array[aper_count++] = state->draw_region->buffer; if (state->depth_region) @@ -453,7 +453,7 @@ i830_emit_state(struct intel_context *intel) if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) { if (count == 0) { count++; - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); goto again; } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "i830 emit state"); @@ -556,9 +556,7 @@ i830_emit_state(struct intel_context *intel) } } - intel->batch->dirty_state &= ~dirty; assert(get_dirty(state) == 0); - assert((intel->batch->dirty_state & (1<<1)) == 0); } static void diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c index 474252b640d..7389a1d57a9 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -188,9 +188,17 @@ i915CreateContext(int api, * FINISHME: vertex shaders? */ ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].EmitCondCodes = GL_TRUE; - ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoIfs = GL_TRUE; - ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoNoise = GL_TRUE; - ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoPow = GL_TRUE; + + struct gl_shader_compiler_options *const fs_options = + & ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; + fs_options->EmitNoIfs = GL_TRUE; + fs_options->EmitNoNoise = GL_TRUE; + fs_options->EmitNoPow = GL_TRUE; + fs_options->EmitNoMainReturn = GL_TRUE; + fs_options->EmitNoIndirectInput = GL_TRUE; + fs_options->EmitNoIndirectOutput = GL_TRUE; + fs_options->EmitNoIndirectUniform = GL_TRUE; + fs_options->EmitNoIndirectTemp = GL_TRUE; ctx->Const.MaxDrawBuffers = 1; diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h index 2c80ded075b..601620275f4 100644 --- a/src/mesa/drivers/dri/i915/i915_context.h +++ b/src/mesa/drivers/dri/i915/i915_context.h @@ -29,7 +29,6 @@ #define I915CONTEXT_INC #include "intel_context.h" -#include "i915_reg.h" #define I915_FALLBACK_TEXTURE 0x1000 #define I915_FALLBACK_COLORMASK 0x2000 @@ -51,6 +50,7 @@ #define I915_UPLOAD_INVARIENT 0x40 #define I915_UPLOAD_DEFAULTS 0x80 #define I915_UPLOAD_RASTER_RULES 0x100 +#define I915_UPLOAD_BLEND 0x200 #define I915_UPLOAD_TEX(i) (0x00010000<<(i)) #define I915_UPLOAD_TEX_ALL (0x00ff0000) #define I915_UPLOAD_TEX_0_SHIFT 16 @@ -77,17 +77,19 @@ #define I915_DEST_SETUP_SIZE 18 #define I915_CTXREG_STATE4 0 -#define I915_CTXREG_LI 1 -#define I915_CTXREG_LIS2 2 -#define I915_CTXREG_LIS4 3 -#define I915_CTXREG_LIS5 4 -#define I915_CTXREG_LIS6 5 -#define I915_CTXREG_IAB 6 -#define I915_CTXREG_BLENDCOLOR0 7 -#define I915_CTXREG_BLENDCOLOR1 8 -#define I915_CTXREG_BF_STENCIL_OPS 9 -#define I915_CTXREG_BF_STENCIL_MASKS 10 -#define I915_CTX_SETUP_SIZE 11 +#define I915_CTXREG_LI 1 +#define I915_CTXREG_LIS2 2 +#define I915_CTXREG_LIS4 3 +#define I915_CTXREG_LIS5 4 +#define I915_CTXREG_LIS6 5 +#define I915_CTXREG_BF_STENCIL_OPS 6 +#define I915_CTXREG_BF_STENCIL_MASKS 7 +#define I915_CTX_SETUP_SIZE 8 + +#define I915_BLENDREG_IAB 0 +#define I915_BLENDREG_BLENDCOLOR0 1 +#define I915_BLENDREG_BLENDCOLOR1 2 +#define I915_BLEND_SETUP_SIZE 3 #define I915_FOGREG_COLOR 0 #define I915_FOGREG_MODE0 1 @@ -123,6 +125,12 @@ enum { #define I915_MAX_CONSTANT 32 #define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT)) +#define I915_MAX_TEX_INDIRECT 4 +#define I915_MAX_TEX_INSN 32 +#define I915_MAX_ALU_INSN 64 +#define I915_MAX_DECL_INSN 27 +#define I915_MAX_TEMPORARY 16 + #define I915_MAX_INSN (I915_MAX_DECL_INSN + \ I915_MAX_TEX_INSN + \ I915_MAX_ALU_INSN) @@ -216,6 +224,7 @@ struct i915_fragment_program struct i915_hw_state { GLuint Ctx[I915_CTX_SETUP_SIZE]; + GLuint Blend[I915_BLEND_SETUP_SIZE]; GLuint Buffer[I915_DEST_SETUP_SIZE]; GLuint Stipple[I915_STP_SETUP_SIZE]; GLuint Fog[I915_FOG_SETUP_SIZE]; @@ -260,8 +269,12 @@ struct i915_context struct i915_fragment_program *current_program; + drm_intel_bo *current_vb_bo; + unsigned int current_vertex_size; + struct i915_hw_state state; uint32_t last_draw_offset; + GLuint last_sampler; }; diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c index 1c6e9845172..25f4fc3c8b1 100644 --- a/src/mesa/drivers/dri/i915/i915_fragprog.c +++ b/src/mesa/drivers/dri/i915/i915_fragprog.c @@ -306,6 +306,7 @@ static void calc_live_regs( struct i915_fragment_program *p ) { const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; GLuint regsUsed = 0xffff0000; + uint8_t live_components[16] = { 0, }; GLint i; for (i = program->Base.NumInstructions - 1; i >= 0; i--) { @@ -314,13 +315,26 @@ static void calc_live_regs( struct i915_fragment_program *p ) int a; /* Register is written to: unmark as live for this and preceeding ops */ - if (inst->DstReg.File == PROGRAM_TEMPORARY) - regsUsed &= ~(1 << inst->DstReg.Index); + if (inst->DstReg.File == PROGRAM_TEMPORARY) { + live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask; + if (live_components[inst->DstReg.Index] == 0) + regsUsed &= ~(1 << inst->DstReg.Index); + } for (a = 0; a < opArgs; a++) { /* Register is read from: mark as live for this and preceeding ops */ - if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) + if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) { + unsigned c; + regsUsed |= 1 << inst->SrcReg[a].Index; + + for (c = 0; c < 4; c++) { + const unsigned field = GET_SWZ(inst->SrcReg[a].Swizzle, c); + + if (field <= SWIZZLE_W) + live_components[inst->SrcReg[a].Index] |= (1U << field); + } + } } p->usedRegs[i] = regsUsed; @@ -795,18 +809,18 @@ upload_program(struct i915_fragment_program *p) flags = get_result_flags(inst); dst = get_result_vector(p, inst); - /* dst = src1 >= src2 */ + /* tmp = src1 >= src2 */ i915_emit_arith(p, A0_SGE, - dst, + tmp, flags, 0, src_vector(p, &inst->SrcReg[0], program), src_vector(p, &inst->SrcReg[1], program), 0); - /* tmp = src1 <= src2 */ + /* dst = src1 <= src2 */ i915_emit_arith(p, A0_SGE, - tmp, + dst, flags, 0, negate(src_vector(p, &inst->SrcReg[0], program), 1, 1, 1, 1), @@ -944,18 +958,18 @@ upload_program(struct i915_fragment_program *p) flags = get_result_flags(inst); dst = get_result_vector(p, inst); - /* dst = src1 < src2 */ + /* tmp = src1 < src2 */ i915_emit_arith(p, A0_SLT, - dst, + tmp, flags, 0, src_vector(p, &inst->SrcReg[0], program), src_vector(p, &inst->SrcReg[1], program), 0); - /* tmp = src1 > src2 */ + /* dst = src1 > src2 */ i915_emit_arith(p, A0_SLT, - tmp, + dst, flags, 0, negate(src_vector(p, &inst->SrcReg[0], program), 1, 1, 1, 1), @@ -1408,6 +1422,10 @@ i915ValidateFragmentProgram(struct i915_context *i915) intel->vertex_attr_count, intel->ViewportMatrix.m, 0); + assert(intel->prim.current_offset == intel->prim.start_offset); + intel->prim.start_offset = (intel->prim.current_offset + intel->vertex_size-1) / intel->vertex_size * intel->vertex_size; + intel->prim.current_offset = intel->prim.start_offset; + intel->vertex_size >>= 2; i915->state.Ctx[I915_CTXREG_LIS2] = s2; diff --git a/src/mesa/drivers/dri/i915/i915_program.c b/src/mesa/drivers/dri/i915/i915_program.c index ca1949b223e..507adf1d3dc 100644 --- a/src/mesa/drivers/dri/i915/i915_program.c +++ b/src/mesa/drivers/dri/i915/i915_program.c @@ -538,6 +538,7 @@ i915_upload_program(struct i915_context *i915, { GLuint program_size = p->csr - p->program; GLuint decl_size = p->decl - p->declarations; + GLuint nr; if (p->error) return; @@ -554,32 +555,32 @@ i915_upload_program(struct i915_context *i915, i915->state.ProgramSize = decl_size + program_size; } - /* Always seemed to get a failure if I used memcmp() to - * shortcircuit this state upload. Needs further investigation? - */ - if (p->nr_constants) { - GLuint nr = p->nr_constants; - - I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1); - I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS); - - i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4); - i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1); - - memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr)); - i915->state.ConstantSize = 2 + (nr) * 4; - - if (0) { - GLuint i; - for (i = 0; i < nr; i++) { - fprintf(stderr, "const[%d]: %f %f %f %f\n", i, - p->constant[i][0], - p->constant[i][1], p->constant[i][2], p->constant[i][3]); - } + nr = p->nr_constants; + if (i915->state.ConstantSize != 2 + nr*4 || + memcmp(i915->state.Constant + 2, + p->constant, 4*sizeof(int)*nr)) { + if (nr) { + I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1); + I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS); + + i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4); + i915->state.Constant[1] = (1 << nr) -1; + + memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * nr); + i915->state.ConstantSize = 2 + nr * 4; + + if (0) { + GLuint i; + for (i = 0; i < nr; i++) { + fprintf(stderr, "const[%d]: %f %f %f %f\n", i, + p->constant[i][0], + p->constant[i][1], p->constant[i][2], p->constant[i][3]); + } + } + } + else { + I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0); } - } - else { - I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0); } p->on_hardware = 1; diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h index 7f31ff674f2..766547a4c6a 100644 --- a/src/mesa/drivers/dri/i915/i915_reg.h +++ b/src/mesa/drivers/dri/i915/i915_reg.h @@ -361,13 +361,6 @@ /* p222 */ -#define I915_MAX_TEX_INDIRECT 4 -#define I915_MAX_TEX_INSN 32 -#define I915_MAX_ALU_INSN 64 -#define I915_MAX_DECL_INSN 27 -#define I915_MAX_TEMPORARY 16 - - /* Each instruction is 3 dwords long, though most don't require all * this space. Maximum of 123 instructions. Smaller maxes per insn * type. diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c index 63c6e78ebe9..58d4f5daffd 100644 --- a/src/mesa/drivers/dri/i915/i915_state.c +++ b/src/mesa/drivers/dri/i915/i915_state.c @@ -56,8 +56,7 @@ i915_update_stencil(struct gl_context * ctx) GLenum front_func, front_fail, front_pass_z_fail, front_pass_z_pass; GLuint back_ref, back_writemask, back_mask; GLenum back_func, back_fail, back_pass_z_fail, back_pass_z_pass; - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + GLuint dirty = 0; /* The 915 considers CW to be "front" for two-sided stencil, so choose * appropriately. @@ -94,56 +93,68 @@ i915_update_stencil(struct gl_context * ctx) back_pass_z_fail = ctx->Stencil.ZFailFunc[0]; back_pass_z_pass = ctx->Stencil.ZPassFunc[0]; } +#define set_ctx_bits(reg, mask, set) do{ \ + GLuint dw = i915->state.Ctx[reg]; \ + dw &= ~(mask); \ + dw |= (set); \ + dirty |= dw != i915->state.Ctx[reg]; \ + i915->state.Ctx[reg] = dw; \ +} while(0) /* Set front state. */ - i915->state.Ctx[I915_CTXREG_STATE4] &= ~(MODE4_ENABLE_STENCIL_TEST_MASK | - MODE4_ENABLE_STENCIL_WRITE_MASK); - i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | - ENABLE_STENCIL_WRITE_MASK | - STENCIL_TEST_MASK(front_mask) | - STENCIL_WRITE_MASK(front_writemask)); - - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK | - S5_STENCIL_TEST_FUNC_MASK | - S5_STENCIL_FAIL_MASK | - S5_STENCIL_PASS_Z_FAIL_MASK | - S5_STENCIL_PASS_Z_PASS_MASK); - - i915->state.Ctx[I915_CTXREG_LIS5] |= - (front_ref << S5_STENCIL_REF_SHIFT) | - (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) | - (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) | - (intel_translate_stencil_op(front_pass_z_fail) << - S5_STENCIL_PASS_Z_FAIL_SHIFT) | - (intel_translate_stencil_op(front_pass_z_pass) << - S5_STENCIL_PASS_Z_PASS_SHIFT); + set_ctx_bits(I915_CTXREG_STATE4, + MODE4_ENABLE_STENCIL_TEST_MASK | + MODE4_ENABLE_STENCIL_WRITE_MASK, + ENABLE_STENCIL_TEST_MASK | + ENABLE_STENCIL_WRITE_MASK | + STENCIL_TEST_MASK(front_mask) | + STENCIL_WRITE_MASK(front_writemask)); + + set_ctx_bits(I915_CTXREG_LIS5, + S5_STENCIL_REF_MASK | + S5_STENCIL_TEST_FUNC_MASK | + S5_STENCIL_FAIL_MASK | + S5_STENCIL_PASS_Z_FAIL_MASK | + S5_STENCIL_PASS_Z_PASS_MASK, + (front_ref << S5_STENCIL_REF_SHIFT) | + (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) | + (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) | + (intel_translate_stencil_op(front_pass_z_fail) << + S5_STENCIL_PASS_Z_FAIL_SHIFT) | + (intel_translate_stencil_op(front_pass_z_pass) << + S5_STENCIL_PASS_Z_PASS_SHIFT)); /* Set back state if different from front. */ if (ctx->Stencil._TestTwoSide) { - i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= - ~(BFO_STENCIL_REF_MASK | - BFO_STENCIL_TEST_MASK | - BFO_STENCIL_FAIL_MASK | - BFO_STENCIL_PASS_Z_FAIL_MASK | - BFO_STENCIL_PASS_Z_PASS_MASK); - i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] |= BFO_STENCIL_TWO_SIDE | - (back_ref << BFO_STENCIL_REF_SHIFT) | - (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) | - (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) | - (intel_translate_stencil_op(back_pass_z_fail) << - BFO_STENCIL_PASS_Z_FAIL_SHIFT) | - (intel_translate_stencil_op(back_pass_z_pass) << - BFO_STENCIL_PASS_Z_PASS_SHIFT); - - i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] &= - ~(BFM_STENCIL_TEST_MASK_MASK | - BFM_STENCIL_WRITE_MASK_MASK); - i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] |= - BFM_STENCIL_TEST_MASK(back_mask) | - BFM_STENCIL_WRITE_MASK(back_writemask); + set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS, + BFO_STENCIL_REF_MASK | + BFO_STENCIL_TEST_MASK | + BFO_STENCIL_FAIL_MASK | + BFO_STENCIL_PASS_Z_FAIL_MASK | + BFO_STENCIL_PASS_Z_PASS_MASK, + BFO_STENCIL_TWO_SIDE | + (back_ref << BFO_STENCIL_REF_SHIFT) | + (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) | + (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) | + (intel_translate_stencil_op(back_pass_z_fail) << + BFO_STENCIL_PASS_Z_FAIL_SHIFT) | + (intel_translate_stencil_op(back_pass_z_pass) << + BFO_STENCIL_PASS_Z_PASS_SHIFT)); + + set_ctx_bits(I915_CTXREG_BF_STENCIL_MASKS, + BFM_STENCIL_TEST_MASK_MASK | + BFM_STENCIL_WRITE_MASK_MASK, + BFM_STENCIL_TEST_MASK(back_mask) | + BFM_STENCIL_WRITE_MASK(back_writemask)); } else { - i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= ~BFO_STENCIL_TWO_SIDE; + set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS, + BFO_STENCIL_TWO_SIDE, 0); } + +#undef set_ctx_bits + + if (dirty) + I915_STATECHANGE(i915, I915_UPLOAD_CTX); } static void @@ -169,15 +180,18 @@ i915AlphaFunc(struct gl_context * ctx, GLenum func, GLfloat ref) struct i915_context *i915 = I915_CONTEXT(ctx); int test = intel_translate_compare_func(func); GLubyte refByte; + GLuint dw; UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref); - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK | - S6_ALPHA_REF_MASK); - i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | - (((GLuint) refByte) << - S6_ALPHA_REF_SHIFT)); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; + dw &= ~(S6_ALPHA_TEST_FUNC_MASK | S6_ALPHA_REF_MASK); + dw |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | + (((GLuint) refByte) << S6_ALPHA_REF_SHIFT)); + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } /* This function makes sure that the proper enables are @@ -190,23 +204,32 @@ static void i915EvalLogicOpBlendState(struct gl_context * ctx) { struct i915_context *i915 = I915_CONTEXT(ctx); + GLuint dw0, dw1; - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw0 = i915->state.Ctx[I915_CTXREG_LIS5]; + dw1 = i915->state.Ctx[I915_CTXREG_LIS6]; if (RGBA_LOGICOP_ENABLED(ctx)) { - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE; - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; + dw0 |= S5_LOGICOP_ENABLE; + dw1 &= ~S6_CBUF_BLEND_ENABLE; } else { - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE; + dw0 &= ~S5_LOGICOP_ENABLE; if (ctx->Color.BlendEnabled) { - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE; + dw1 |= S6_CBUF_BLEND_ENABLE; } else { - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; + dw1 &= ~S6_CBUF_BLEND_ENABLE; } } + if (dw0 != i915->state.Ctx[I915_CTXREG_LIS5] || + dw1 != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw0; + i915->state.Ctx[I915_CTXREG_LIS6] = dw1; + + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } static void @@ -214,6 +237,7 @@ i915BlendColor(struct gl_context * ctx, const GLfloat color[4]) { struct i915_context *i915 = I915_CONTEXT(ctx); GLubyte r, g, b, a; + GLuint dw; DBG("%s\n", __FUNCTION__); @@ -222,9 +246,11 @@ i915BlendColor(struct gl_context * ctx, const GLfloat color[4]) UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = - (a << 24) | (r << 16) | (g << 8) | b; + dw = (a << 24) | (r << 16) | (g << 8) | b; + if (dw != i915->state.Blend[I915_BLENDREG_BLENDCOLOR1]) { + i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_BLEND); + } } @@ -258,7 +284,7 @@ static void i915UpdateBlendState(struct gl_context * ctx) { struct i915_context *i915 = I915_CONTEXT(ctx); - GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] & + GLuint iab = (i915->state.Blend[I915_BLENDREG_IAB] & ~(IAB_SRC_FACTOR_MASK | IAB_DST_FACTOR_MASK | (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE)); @@ -293,11 +319,13 @@ i915UpdateBlendState(struct gl_context * ctx) if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) iab |= IAB_ENABLE; - if (iab != i915->state.Ctx[I915_CTXREG_IAB] || - lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_IAB] = iab; + if (iab != i915->state.Blend[I915_BLENDREG_IAB]) { + i915->state.Blend[I915_BLENDREG_IAB] = iab; + I915_STATECHANGE(i915, I915_UPLOAD_BLEND); + } + if (lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) { i915->state.Ctx[I915_CTXREG_LIS6] = lis6; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); } /* This will catch a logicop blend equation */ @@ -325,27 +353,36 @@ i915DepthFunc(struct gl_context * ctx, GLenum func) { struct i915_context *i915 = I915_CONTEXT(ctx); int test = intel_translate_compare_func(func); + GLuint dw; DBG("%s\n", __FUNCTION__); - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK; - i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT; + dw = i915->state.Ctx[I915_CTXREG_LIS6]; + dw &= ~S6_DEPTH_TEST_FUNC_MASK; + dw |= test << S6_DEPTH_TEST_FUNC_SHIFT; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + } } static void i915DepthMask(struct gl_context * ctx, GLboolean flag) { struct i915_context *i915 = I915_CONTEXT(ctx); + GLuint dw; DBG("%s flag (%d)\n", __FUNCTION__, flag); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; if (flag && ctx->Depth.Test) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE; + dw |= S6_DEPTH_WRITE_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE; + dw &= ~S6_DEPTH_WRITE_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + } } @@ -532,7 +569,7 @@ static void i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused) { struct i915_context *i915 = I915_CONTEXT(ctx); - GLuint mode; + GLuint mode, dw; DBG("%s %d\n", __FUNCTION__, ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0); @@ -554,9 +591,13 @@ i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused) mode = S4_CULLMODE_BOTH; } - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_CULLMODE_MASK; - i915->state.Ctx[I915_CTXREG_LIS4] |= mode; + dw = i915->state.Ctx[I915_CTXREG_LIS4]; + dw &= ~S4_CULLMODE_MASK; + dw |= mode; + if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { + i915->state.Ctx[I915_CTXREG_LIS4] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } static void @@ -690,6 +731,7 @@ i915_update_fog(struct gl_context * ctx) GLenum mode; GLboolean enabled; GLboolean try_pixel_fog; + GLuint dw; if (ctx->FragmentProgram._Current) { /* Pull in static fog state from program */ @@ -765,12 +807,16 @@ i915_update_fog(struct gl_context * ctx) i915->vertex_fog = I915_FOG_VERTEX; } - I915_STATECHANGE(i915, I915_UPLOAD_CTX); I915_ACTIVESTATE(i915, I915_UPLOAD_FOG, enabled); + dw = i915->state.Ctx[I915_CTXREG_LIS5]; if (enabled) - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_FOG_ENABLE; + dw |= S5_FOG_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_FOG_ENABLE; + dw &= ~S5_FOG_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } /* Always enable pixel fog. Vertex fog using fog coord will conflict * with fog code appended onto fragment program. @@ -837,6 +883,7 @@ static void i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) { struct i915_context *i915 = I915_CONTEXT(ctx); + GLuint dw; switch (cap) { case GL_TEXTURE_2D: @@ -848,11 +895,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) break; case GL_ALPHA_TEST: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; if (state) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_ALPHA_TEST_ENABLE; + dw |= S6_ALPHA_TEST_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_ALPHA_TEST_ENABLE; + dw &= ~S6_ALPHA_TEST_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_BLEND: @@ -872,19 +923,27 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) break; case GL_DITHER: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS5]; if (state) - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; + dw |= S5_COLOR_DITHER_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_COLOR_DITHER_ENABLE; + dw &= ~S5_COLOR_DITHER_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_DEPTH_TEST: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS6]; if (state) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_TEST_ENABLE; + dw |= S6_DEPTH_TEST_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_ENABLE; + dw &= ~S6_DEPTH_TEST_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { + i915->state.Ctx[I915_CTXREG_LIS6] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } i915DepthMask(ctx, ctx->Depth.Mask); break; @@ -900,11 +959,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) break; case GL_LINE_SMOOTH: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS4]; if (state) - i915->state.Ctx[I915_CTXREG_LIS4] |= S4_LINE_ANTIALIAS_ENABLE; + dw |= S4_LINE_ANTIALIAS_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_LINE_ANTIALIAS_ENABLE; + dw &= ~S4_LINE_ANTIALIAS_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { + i915->state.Ctx[I915_CTXREG_LIS4] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_FOG: @@ -923,13 +986,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) hw_stencil = (irbStencil && irbStencil->region); } if (hw_stencil) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS5]; if (state) - i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | - S5_STENCIL_WRITE_ENABLE); + dw |= (S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE); else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE | - S5_STENCIL_WRITE_ENABLE); + dw &= ~(S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE); + if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { + i915->state.Ctx[I915_CTXREG_LIS5] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } } else { FALLBACK(&i915->intel, I915_FALLBACK_STENCIL, state); @@ -959,11 +1024,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) /* This state change is handled in i915_reduced_primitive_state because * the hardware bit should only be set when rendering points. */ - I915_STATECHANGE(i915, I915_UPLOAD_CTX); + dw = i915->state.Ctx[I915_CTXREG_LIS4]; if (state) - i915->state.Ctx[I915_CTXREG_LIS4] |= S4_SPRITE_POINT_ENABLE; + dw |= S4_SPRITE_POINT_ENABLE; else - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_SPRITE_POINT_ENABLE; + dw &= ~S4_SPRITE_POINT_ENABLE; + if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { + i915->state.Ctx[I915_CTXREG_LIS4] = dw; + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + } break; case GL_POINT_SMOOTH: @@ -984,6 +1053,7 @@ i915_init_packets(struct i915_context *i915) { I915_STATECHANGE(i915, I915_UPLOAD_CTX); + I915_STATECHANGE(i915, I915_UPLOAD_BLEND); /* Probably don't want to upload all this stuff every time one * piece changes. */ @@ -1010,13 +1080,13 @@ i915_init_packets(struct i915_context *i915) ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff)); - i915->state.Ctx[I915_CTXREG_IAB] = + i915->state.Blend[I915_BLENDREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE | IAB_MODIFY_FUNC | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR); - i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] = + i915->state.Blend[I915_BLENDREG_BLENDCOLOR0] = _3DSTATE_CONST_BLEND_COLOR_CMD; - i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0; + i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = 0; i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] = _3DSTATE_BACKFACE_STENCIL_MASKS | @@ -1087,6 +1157,7 @@ i915_init_packets(struct i915_context *i915) i915->state.active = (I915_UPLOAD_PROGRAM | I915_UPLOAD_STIPPLE | I915_UPLOAD_CTX | + I915_UPLOAD_BLEND | I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT | I915_UPLOAD_RASTER_RULES); diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index a94b9571275..921183b81df 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -217,7 +217,7 @@ i915_emit_invarient_state(struct intel_context *intel) #define emit(intel, state, size ) \ - intel_batchbuffer_data(intel->batch, state, size, false) + intel_batchbuffer_data(intel, state, size, false) static GLuint get_dirty(struct i915_hw_state *state) @@ -251,6 +251,9 @@ get_state_size(struct i915_hw_state *state) if (dirty & I915_UPLOAD_CTX) sz += sizeof(state->Ctx); + if (dirty & I915_UPLOAD_BLEND) + sz += sizeof(state->Blend); + if (dirty & I915_UPLOAD_BUFFERS) sz += sizeof(state->Buffer); @@ -299,7 +302,7 @@ i915_emit_state(struct intel_context *intel) * scheduling is allowed, rather than assume that it is whenever a * batchbuffer fills up. */ - intel_batchbuffer_require_space(intel->batch, + intel_batchbuffer_require_space(intel, get_state_size(state) + INTEL_PRIM_EMIT_SIZE, false); count = 0; @@ -307,7 +310,7 @@ i915_emit_state(struct intel_context *intel) aper_count = 0; dirty = get_dirty(state); - aper_array[aper_count++] = intel->batch->buf; + aper_array[aper_count++] = intel->batch.bo; if (dirty & I915_UPLOAD_BUFFERS) { aper_array[aper_count++] = state->draw_region->buffer; if (state->depth_region) @@ -327,7 +330,7 @@ i915_emit_state(struct intel_context *intel) if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) { if (count == 0) { count++; - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); goto again; } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); @@ -366,6 +369,13 @@ i915_emit_state(struct intel_context *intel) emit(intel, state->Ctx, sizeof(state->Ctx)); } + if (dirty & I915_UPLOAD_BLEND) { + if (INTEL_DEBUG & DEBUG_STATE) + fprintf(stderr, "I915_UPLOAD_BLEND:\n"); + + emit(intel, state->Blend, sizeof(state->Blend)); + } + if (dirty & I915_UPLOAD_BUFFERS) { GLuint count; @@ -426,6 +436,7 @@ i915_emit_state(struct intel_context *intel) */ if (dirty & I915_UPLOAD_TEX_ALL) { int nr = 0; + GLuint unwind; for (i = 0; i < I915_TEX_UNITS; i++) if (dirty & I915_UPLOAD_TEX(i)) @@ -445,6 +456,7 @@ i915_emit_state(struct intel_context *intel) } ADVANCE_BATCH(); + unwind = intel->batch.used; BEGIN_BATCH(2 + nr * 3); OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); @@ -455,6 +467,13 @@ i915_emit_state(struct intel_context *intel) OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); } ADVANCE_BATCH(); + if (i915->last_sampler && + memcmp(intel->batch.map + i915->last_sampler, + intel->batch.map + unwind, + (2 + nr*3)*sizeof(int)) == 0) + intel->batch.used = unwind; + else + i915->last_sampler = unwind; } if (dirty & I915_UPLOAD_CONSTANTS) { @@ -476,9 +495,7 @@ i915_emit_state(struct intel_context *intel) } } - intel->batch->dirty_state &= ~dirty; assert(get_dirty(state) == 0); - assert((intel->batch->dirty_state & (1<<1)) == 0); } static void @@ -660,6 +677,10 @@ i915_new_batch(struct intel_context *intel) */ i915->state.emitted = 0; i915->last_draw_offset = 0; + i915->last_sampler = 0; + + i915->current_vb_bo = NULL; + i915->current_vertex_size = 0; } static void diff --git a/src/mesa/drivers/dri/i915/intel_render.c b/src/mesa/drivers/dri/i915/intel_render.c index 0d8ab4b507e..2d361ca0a9a 100644 --- a/src/mesa/drivers/dri/i915/intel_render.c +++ b/src/mesa/drivers/dri/i915/intel_render.c @@ -124,7 +124,7 @@ static INLINE GLuint intel_get_vb_max(struct intel_context *intel) GLuint ret; if (intel->intelScreen->no_vbo) - ret = intel->batch->size - 1500; + ret = sizeof(intel->batch.map) - 1500; else ret = INTEL_VB_SIZE; ret /= (intel->vertex_size * 4); diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c index b9a8aeb12f2..cf9291cdfca 100644 --- a/src/mesa/drivers/dri/i915/intel_tris.c +++ b/src/mesa/drivers/dri/i915/intel_tris.c @@ -54,6 +54,7 @@ #include "intel_span.h" #include "i830_context.h" #include "i830_reg.h" +#include "i915_context.h" static void intelRenderPrimitive(struct gl_context * ctx, GLenum prim); static void intelRasterPrimitive(struct gl_context * ctx, GLenum rprim, @@ -62,22 +63,22 @@ static void intelRasterPrimitive(struct gl_context * ctx, GLenum rprim, static void intel_flush_inline_primitive(struct intel_context *intel) { - GLuint used = intel->batch->ptr - intel->prim.start_ptr; + GLuint used = intel->batch.used - intel->prim.start_ptr; assert(intel->prim.primitive != ~0); /* printf("/\n"); */ - if (used < 8) + if (used < 2) goto do_discard; - *(int *) intel->prim.start_ptr = (_3DPRIMITIVE | - intel->prim.primitive | (used / 4 - 2)); + intel->batch.map[intel->prim.start_ptr] = + _3DPRIMITIVE | intel->prim.primitive | (used - 2); goto finished; do_discard: - intel->batch->ptr -= used; + intel->batch.used = intel->prim.start_ptr; finished: intel->prim.primitive = ~0; @@ -100,9 +101,7 @@ static void intel_start_inline(struct intel_context *intel, uint32_t prim) */ BEGIN_BATCH(1); - assert((intel->batch->dirty_state & (1<<1)) == 0); - - intel->prim.start_ptr = intel->batch->ptr; + intel->prim.start_ptr = intel->batch.used; intel->prim.primitive = prim; intel->prim.flush = intel_flush_inline_primitive; @@ -118,26 +117,25 @@ static void intel_wrap_inline(struct intel_context *intel) GLuint prim = intel->prim.primitive; intel_flush_inline_primitive(intel); - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); intel_start_inline(intel, prim); /* ??? */ } static GLuint *intel_extend_inline(struct intel_context *intel, GLuint dwords) { - GLuint sz = dwords * sizeof(GLuint); GLuint *ptr; assert(intel->prim.flush == intel_flush_inline_primitive); - if (intel_batchbuffer_space(intel->batch) < sz) + if (intel_batchbuffer_space(intel) < dwords * sizeof(GLuint)) intel_wrap_inline(intel); /* printf("."); */ intel->vtbl.assert_not_dirty(intel); - ptr = (GLuint *) intel->batch->ptr; - intel->batch->ptr += sz; + ptr = intel->batch.map + intel->batch.used; + intel->batch.used += dwords; return ptr; } @@ -218,15 +216,15 @@ void intel_flush_prim(struct intel_context *intel) offset = intel->prim.start_offset; intel->prim.start_offset = intel->prim.current_offset; if (intel->gen < 3) - intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128); + intel->prim.current_offset = intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128); intel->prim.flush = NULL; intel->vtbl.emit_state(intel); - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = vb_bo; if (dri_bufmgr_check_aperture_space(aper_array, 2)) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); intel->vtbl.emit_state(intel); } @@ -236,11 +234,6 @@ void intel_flush_prim(struct intel_context *intel) */ intel->no_batch_wrap = GL_TRUE; - /* Check that we actually emitted the state into this batch, using the - * UPLOAD_CTX bit as the signal. - */ - assert((intel->batch->dirty_state & (1<<1)) == 0); - #if 0 printf("emitting %d..%d=%d vertices size %d\n", offset, intel->prim.current_offset, count, @@ -248,20 +241,39 @@ void intel_flush_prim(struct intel_context *intel) #endif if (intel->gen >= 3) { - BEGIN_BATCH(5); - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(0) | I1_LOAD_S(1) | 1); - assert((offset & ~S0_VB_OFFSET_MASK) == 0); - OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, offset); - OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | - (intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); + struct i915_context *i915 = i915_context(&intel->ctx); + unsigned int cmd = 0, len = 0; + if (vb_bo != i915->current_vb_bo) { + cmd |= I1_LOAD_S(0); + len++; + } + + if (intel->vertex_size != i915->current_vertex_size) { + cmd |= I1_LOAD_S(1); + len++; + } + if (len) + len++; + + BEGIN_BATCH(2+len); + if (cmd) + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | cmd | (len - 2)); + if (vb_bo != i915->current_vb_bo) { + OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, 0); + i915->current_vb_bo = vb_bo; + } + if (intel->vertex_size != i915->current_vertex_size) { + OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | + (intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); + i915->current_vertex_size = intel->vertex_size; + } OUT_BATCH(_3DPRIMITIVE | PRIM_INDIRECT | PRIM_INDIRECT_SEQUENTIAL | intel->prim.primitive | count); - OUT_BATCH(0); /* Beginning vertex index */ + OUT_BATCH(offset / (intel->vertex_size * 4)); ADVANCE_BATCH(); } else { struct i830_context *i830 = i830_context(&intel->ctx); diff --git a/src/mesa/drivers/dri/i965/brw_cc.c b/src/mesa/drivers/dri/i965/brw_cc.c index c986970a757..412d82ab3ca 100644 --- a/src/mesa/drivers/dri/i965/brw_cc.c +++ b/src/mesa/drivers/dri/i965/brw_cc.c @@ -35,6 +35,7 @@ #include "brw_defines.h" #include "brw_util.h" #include "main/macros.h" +#include "intel_batchbuffer.h" void brw_update_cc_vp(struct brw_context *brw) @@ -92,54 +93,54 @@ static void upload_cc_unit(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_cc_unit_state cc; - void *map; + struct brw_cc_unit_state *cc; - memset(&cc, 0, sizeof(cc)); + cc = brw_state_batch(brw, sizeof(*cc), 64, &brw->cc.state_offset); + memset(cc, 0, sizeof(*cc)); /* _NEW_STENCIL */ if (ctx->Stencil._Enabled) { const unsigned back = ctx->Stencil._BackFace; - cc.cc0.stencil_enable = 1; - cc.cc0.stencil_func = + cc->cc0.stencil_enable = 1; + cc->cc0.stencil_func = intel_translate_compare_func(ctx->Stencil.Function[0]); - cc.cc0.stencil_fail_op = + cc->cc0.stencil_fail_op = intel_translate_stencil_op(ctx->Stencil.FailFunc[0]); - cc.cc0.stencil_pass_depth_fail_op = + cc->cc0.stencil_pass_depth_fail_op = intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]); - cc.cc0.stencil_pass_depth_pass_op = + cc->cc0.stencil_pass_depth_pass_op = intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]); - cc.cc1.stencil_ref = ctx->Stencil.Ref[0]; - cc.cc1.stencil_write_mask = ctx->Stencil.WriteMask[0]; - cc.cc1.stencil_test_mask = ctx->Stencil.ValueMask[0]; + cc->cc1.stencil_ref = ctx->Stencil.Ref[0]; + cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0]; + cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0]; if (ctx->Stencil._TestTwoSide) { - cc.cc0.bf_stencil_enable = 1; - cc.cc0.bf_stencil_func = + cc->cc0.bf_stencil_enable = 1; + cc->cc0.bf_stencil_func = intel_translate_compare_func(ctx->Stencil.Function[back]); - cc.cc0.bf_stencil_fail_op = + cc->cc0.bf_stencil_fail_op = intel_translate_stencil_op(ctx->Stencil.FailFunc[back]); - cc.cc0.bf_stencil_pass_depth_fail_op = + cc->cc0.bf_stencil_pass_depth_fail_op = intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]); - cc.cc0.bf_stencil_pass_depth_pass_op = + cc->cc0.bf_stencil_pass_depth_pass_op = intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]); - cc.cc1.bf_stencil_ref = ctx->Stencil.Ref[back]; - cc.cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back]; - cc.cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back]; + cc->cc1.bf_stencil_ref = ctx->Stencil.Ref[back]; + cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back]; + cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back]; } /* Not really sure about this: */ if (ctx->Stencil.WriteMask[0] || (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back])) - cc.cc0.stencil_write_enable = 1; + cc->cc0.stencil_write_enable = 1; } /* _NEW_COLOR */ if (ctx->Color._LogicOpEnabled && ctx->Color.LogicOp != GL_COPY) { - cc.cc2.logicop_enable = 1; - cc.cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp); + cc->cc2.logicop_enable = 1; + cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp); } else if (ctx->Color.BlendEnabled) { GLenum eqRGB = ctx->Color.Blend[0].EquationRGB; GLenum eqA = ctx->Color.Blend[0].EquationA; @@ -167,58 +168,55 @@ static void upload_cc_unit(struct brw_context *brw) srcA = dstA = GL_ONE; } - cc.cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB); - cc.cc6.src_blend_factor = brw_translate_blend_factor(srcRGB); - cc.cc6.blend_function = brw_translate_blend_equation(eqRGB); + cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB); + cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB); + cc->cc6.blend_function = brw_translate_blend_equation(eqRGB); - cc.cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA); - cc.cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA); - cc.cc5.ia_blend_function = brw_translate_blend_equation(eqA); + cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA); + cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA); + cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA); - cc.cc3.blend_enable = 1; - cc.cc3.ia_blend_enable = (srcA != srcRGB || + cc->cc3.blend_enable = 1; + cc->cc3.ia_blend_enable = (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB); } if (ctx->Color.AlphaEnabled) { - cc.cc3.alpha_test = 1; - cc.cc3.alpha_test_func = + cc->cc3.alpha_test = 1; + cc->cc3.alpha_test_func = intel_translate_compare_func(ctx->Color.AlphaFunc); - cc.cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; + cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; - UNCLAMPED_FLOAT_TO_UBYTE(cc.cc7.alpha_ref.ub[0], ctx->Color.AlphaRef); + UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef); } if (ctx->Color.DitherFlag) { - cc.cc5.dither_enable = 1; - cc.cc6.y_dither_offset = 0; - cc.cc6.x_dither_offset = 0; + cc->cc5.dither_enable = 1; + cc->cc6.y_dither_offset = 0; + cc->cc6.x_dither_offset = 0; } /* _NEW_DEPTH */ if (ctx->Depth.Test) { - cc.cc2.depth_test = 1; - cc.cc2.depth_test_function = + cc->cc2.depth_test = 1; + cc->cc2.depth_test_function = intel_translate_compare_func(ctx->Depth.Func); - cc.cc2.depth_write_enable = ctx->Depth.Mask; + cc->cc2.depth_write_enable = ctx->Depth.Mask; } if (intel->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS)) - cc.cc5.statistics_enable = 1; + cc->cc5.statistics_enable = 1; /* CACHE_NEW_CC_VP */ - cc.cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */ + cc->cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */ - map = brw_state_batch(brw, sizeof(cc), 64, - &brw->cc.state_bo, &brw->cc.state_offset); - memcpy(map, &cc, sizeof(cc)); brw->state.dirty.cache |= CACHE_NEW_CC_UNIT; /* Emit CC viewport relocation */ - drm_intel_bo_emit_reloc(brw->cc.state_bo, (brw->cc.state_offset + - offsetof(struct brw_cc_unit_state, - cc4)), + drm_intel_bo_emit_reloc(brw->intel.batch.bo, + (brw->cc.state_offset + + offsetof(struct brw_cc_unit_state, cc4)), brw->cc.vp_bo, 0, I915_GEM_DOMAIN_INSTRUCTION, 0); } @@ -235,18 +233,16 @@ const struct brw_tracked_state brw_cc_unit = { static void upload_blend_constant_color(struct brw_context *brw) { - struct gl_context *ctx = &brw->intel.ctx; - struct brw_blend_constant_color bcc; - - memset(&bcc, 0, sizeof(bcc)); - bcc.header.opcode = _3DSTATE_BLEND_CONSTANT_COLOR; - bcc.header.length = sizeof(bcc)/4-2; - bcc.blend_constant_color[0] = ctx->Color.BlendColor[0]; - bcc.blend_constant_color[1] = ctx->Color.BlendColor[1]; - bcc.blend_constant_color[2] = ctx->Color.BlendColor[2]; - bcc.blend_constant_color[3] = ctx->Color.BlendColor[3]; - - BRW_CACHED_BATCH_STRUCT(brw, &bcc); + struct intel_context *intel = &brw->intel; + struct gl_context *ctx = &intel->ctx; + + BEGIN_BATCH(5); + OUT_BATCH(_3DSTATE_BLEND_CONSTANT_COLOR << 16 | (5-2)); + OUT_BATCH_F(ctx->Color.BlendColor[0]); + OUT_BATCH_F(ctx->Color.BlendColor[1]); + OUT_BATCH_F(ctx->Color.BlendColor[2]); + OUT_BATCH_F(ctx->Color.BlendColor[3]); + CACHED_BATCH(); } const struct brw_tracked_state brw_blend_constant_color = { diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 7069724466a..3e52304f6ab 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -145,7 +145,7 @@ struct brw_context; #define BRW_NEW_NR_VS_SURFACES 0x80000 #define BRW_NEW_INDEX_BUFFER 0x100000 #define BRW_NEW_VS_CONSTBUF 0x200000 -#define BRW_NEW_WM_CONSTBUF 0x200000 +#define BRW_NEW_WM_CONSTBUF 0x400000 struct brw_state_flags { /** State update flags signalled by mesa internals */ @@ -408,21 +408,26 @@ struct brw_cached_batch_item { */ #define ATTRIB_BIT_DWORDS ((VERT_ATTRIB_MAX+31)/32) +struct brw_vertex_buffer { + /** Buffer object containing the uploaded vertex data */ + drm_intel_bo *bo; + uint32_t offset; + /** Byte stride between elements in the uploaded array */ + GLuint stride; +}; struct brw_vertex_element { const struct gl_client_array *glarray; + int buffer; + /** The corresponding Mesa vertex attribute */ gl_vert_attrib attrib; /** Size of a complete element */ GLuint element_size; /** Number of uploaded elements for this input. */ GLuint count; - /** Byte stride between elements in the uploaded array */ - GLuint stride; /** Offset of the first element within the buffer object */ unsigned int offset; - /** Buffer object containing the uploaded vertex data */ - drm_intel_bo *bo; }; @@ -461,8 +466,6 @@ struct brw_context struct { struct brw_state_flags dirty; - GLuint nr_color_regions; - struct intel_region *color_regions[MAX_DRAW_BUFFERS]; struct intel_region *depth_region; /** @@ -485,23 +488,27 @@ struct brw_context struct { struct brw_vertex_element inputs[VERT_ATTRIB_MAX]; + struct brw_vertex_buffer buffers[VERT_ATTRIB_MAX]; + struct { + uint32_t handle; + uint32_t offset; + uint32_t stride; + } current_buffers[VERT_ATTRIB_MAX]; struct brw_vertex_element *enabled[VERT_ATTRIB_MAX]; GLuint nr_enabled; - -#define BRW_NR_UPLOAD_BUFS 17 -#define BRW_UPLOAD_INIT_SIZE (128*1024) - - struct { - drm_intel_bo *bo; - GLuint offset; - } upload; + GLuint nr_buffers, nr_current_buffers; /* Summary of size and varying of active arrays, so we can check * for changes to this state: */ struct brw_vertex_info info; unsigned int min_index, max_index; + + /* Offset from start of vertex buffer so we can avoid redefining + * the same VB packed over and over again. + */ + unsigned int start_vertex_bias; } vb; struct { @@ -515,7 +522,7 @@ struct brw_context /* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */ drm_intel_bo *bo; unsigned int offset; - unsigned int size; + /* Offset to index buffer index to use in CMD_3D_PRIM so that we can * avoid re-uploading the IB packet over and over if we're actually * referencing the same index buffer. @@ -528,11 +535,6 @@ struct brw_context const struct gl_vertex_program *vertex_program; const struct gl_fragment_program *fragment_program; - - /* For populating the gtt: - */ - GLuint next_free_page; - /* hw-dependent 3DSTATE_VF_STATISTICS opcode */ uint32_t CMD_VF_STATISTICS; /* hw-dependent 3DSTATE_PIPELINE_SELECT opcode */ @@ -612,9 +614,7 @@ struct brw_context drm_intel_bo *const_bo; /** Binding table of pointers to surf_bo entries */ - drm_intel_bo *bind_bo; uint32_t bind_bo_offset; - drm_intel_bo *surf_bo[BRW_VS_MAX_SURF]; uint32_t surf_offset[BRW_VS_MAX_SURF]; GLuint nr_surfaces; } vs; @@ -666,9 +666,7 @@ struct brw_context drm_intel_bo *sampler_bo; /** Binding table of pointers to surf_bo entries */ - drm_intel_bo *bind_bo; uint32_t bind_bo_offset; - drm_intel_bo *surf_bo[BRW_WM_MAX_SURF]; uint32_t surf_offset[BRW_WM_MAX_SURF]; drm_intel_bo *prog_bo; @@ -693,7 +691,6 @@ struct brw_context drm_intel_bo *depth_stencil_state_bo; drm_intel_bo *color_calc_state_bo; - drm_intel_bo *state_bo; uint32_t state_offset; } cc; @@ -841,4 +838,3 @@ float convert_param(enum param_conversion conversion, float param) GLboolean brw_do_cubemap_normalize(struct exec_list *instructions); #endif - diff --git a/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp b/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp index 35bea681214..8574169e472 100644 --- a/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp +++ b/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp @@ -51,7 +51,7 @@ brw_cubemap_normalize_visitor::visit_leave(ir_texture *ir) if (ir->sampler->type->sampler_dimensionality != GLSL_SAMPLER_DIM_CUBE) return visit_continue; - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); ir_variable *var = new(mem_ctx) ir_variable(ir->coordinate->type, "coordinate", ir_var_auto); diff --git a/src/mesa/drivers/dri/i965/brw_curbe.c b/src/mesa/drivers/dri/i965/brw_curbe.c index 877b22fec19..ae11c487a2c 100644 --- a/src/mesa/drivers/dri/i965/brw_curbe.c +++ b/src/mesa/drivers/dri/i965/brw_curbe.c @@ -146,22 +146,24 @@ const struct brw_tracked_state brw_curbe_offsets = { */ void brw_upload_cs_urb_state(struct brw_context *brw) { - struct brw_cs_urb_state cs_urb; - memset(&cs_urb, 0, sizeof(cs_urb)); + struct intel_context *intel = &brw->intel; + BEGIN_BATCH(2); /* It appears that this is the state packet for the CS unit, ie. the * urb entries detailed here are housed in the CS range from the * URB_FENCE command. */ - cs_urb.header.opcode = CMD_CS_URB_STATE; - cs_urb.header.length = sizeof(cs_urb)/4 - 2; + OUT_BATCH(CMD_CS_URB_STATE << 16 | (2-2)); /* BRW_NEW_URB_FENCE */ - cs_urb.bits0.nr_urb_entries = brw->urb.nr_cs_entries; - cs_urb.bits0.urb_entry_size = brw->urb.csize - 1; - - assert(brw->urb.nr_cs_entries); - BRW_CACHED_BATCH_STRUCT(brw, &cs_urb); + if (brw->urb.csize == 0) { + OUT_BATCH(0); + } else { + /* BRW_NEW_URB_FENCE */ + assert(brw->urb.nr_cs_entries); + OUT_BATCH((brw->urb.csize - 1) << 4 | brw->urb.nr_cs_entries); + } + CACHED_BATCH(); } static GLfloat fixed_plane[6][4] = { diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index 2f7dcc2dda7..a413c02b573 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -817,8 +817,8 @@ #define CMD_PIPELINE_SELECT_965 0x6104 #define CMD_PIPELINE_SELECT_GM45 0x6904 -#define CMD_PIPELINED_STATE_POINTERS 0x7800 -#define CMD_BINDING_TABLE_PTRS 0x7801 +#define _3DSTATE_PIPELINED_POINTERS 0x7800 +#define _3DSTATE_BINDING_TABLE_POINTERS 0x7801 # define GEN6_BINDING_TABLE_MODIFY_VS (1 << 8) # define GEN6_BINDING_TABLE_MODIFY_GS (1 << 9) # define GEN6_BINDING_TABLE_MODIFY_PS (1 << 12) diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 7eb16b71f4a..f5abe021c43 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -145,9 +145,14 @@ static void brw_emit_prim(struct brw_context *brw, prim_packet.start_vert_location = prim->start; if (prim->indexed) prim_packet.start_vert_location += brw->ib.start_vertex_offset; + else + prim_packet.start_vert_location += brw->vb.start_vertex_bias; prim_packet.instance_count = 1; prim_packet.start_instance_location = 0; prim_packet.base_vert_location = prim->basevertex; + if (prim->indexed) + prim_packet.base_vert_location += brw->vb.start_vertex_bias; + /* If we're set to always flush, do it before and after the primitive emit. * We want to catch both missed flushes that hurt instruction/state cache @@ -155,14 +160,14 @@ static void brw_emit_prim(struct brw_context *brw, * the besides the draw code. */ if (intel->always_flush_cache) { - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } if (prim_packet.verts_per_instance) { - intel_batchbuffer_data( brw->intel.batch, &prim_packet, + intel_batchbuffer_data(&brw->intel, &prim_packet, sizeof(prim_packet), false); } if (intel->always_flush_cache) { - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } } @@ -172,13 +177,16 @@ static void brw_merge_inputs( struct brw_context *brw, struct brw_vertex_info old = brw->vb.info; GLuint i; - for (i = 0; i < VERT_ATTRIB_MAX; i++) - drm_intel_bo_unreference(brw->vb.inputs[i].bo); + for (i = 0; i < brw->vb.nr_buffers; i++) { + drm_intel_bo_unreference(brw->vb.buffers[i].bo); + brw->vb.buffers[i].bo = NULL; + } + brw->vb.nr_buffers = 0; - memset(&brw->vb.inputs, 0, sizeof(brw->vb.inputs)); memset(&brw->vb.info, 0, sizeof(brw->vb.info)); for (i = 0; i < VERT_ATTRIB_MAX; i++) { + brw->vb.inputs[i].buffer = -1; brw->vb.inputs[i].glarray = arrays[i]; brw->vb.inputs[i].attrib = (gl_vert_attrib) i; @@ -303,7 +311,6 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, struct brw_context *brw = brw_context(ctx); GLboolean retval = GL_FALSE; GLboolean warn = GL_FALSE; - GLboolean first_time = GL_TRUE; GLuint i; if (ctx->NewState) @@ -351,14 +358,10 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, * an upper bound of how much we might emit in a single * brw_try_draw_prims(). */ - intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4, - false); + intel_batchbuffer_require_space(intel, 1024, false); hw_prim = brw_set_prim(brw, &prim[i]); - - if (first_time || (brw->state.dirty.brw & BRW_NEW_PRIMITIVE)) { - first_time = GL_FALSE; - + if (brw->state.dirty.brw) { brw_validate_state(brw); /* Various fallback checks: */ @@ -371,7 +374,7 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, if (dri_bufmgr_check_aperture_space(brw->state.validated_bos, brw->state.validated_bo_count)) { static GLboolean warned; - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); /* Validate the state after we flushed the batch (which would have * changed the set of dirty state). If we still fail to @@ -400,7 +403,7 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, } if (intel->always_flush_batch) - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); out: brw_state_cache_check_size(brw); @@ -461,25 +464,32 @@ void brw_draw_init( struct brw_context *brw ) { struct gl_context *ctx = &brw->intel.ctx; struct vbo_context *vbo = vbo_context(ctx); + int i; /* Register our drawing function: */ vbo->draw_prims = brw_draw_prims; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + brw->vb.inputs[i].buffer = -1; + brw->vb.nr_buffers = 0; + brw->vb.nr_enabled = 0; } void brw_draw_destroy( struct brw_context *brw ) { int i; - if (brw->vb.upload.bo != NULL) { - drm_intel_bo_unreference(brw->vb.upload.bo); - brw->vb.upload.bo = NULL; + for (i = 0; i < brw->vb.nr_buffers; i++) { + drm_intel_bo_unreference(brw->vb.buffers[i].bo); + brw->vb.buffers[i].bo = NULL; } + brw->vb.nr_buffers = 0; - for (i = 0; i < VERT_ATTRIB_MAX; i++) { - drm_intel_bo_unreference(brw->vb.inputs[i].bo); - brw->vb.inputs[i].bo = NULL; + for (i = 0; i < brw->vb.nr_enabled; i++) { + brw->vb.enabled[i]->buffer = -1; } + brw->vb.nr_enabled = 0; drm_intel_bo_unreference(brw->ib.bo); brw->ib.bo = NULL; diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index 2cefe614dd2..7234ce210b5 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -25,6 +25,7 @@ * **************************************************************************/ +#undef NDEBUG #include "main/glheader.h" #include "main/bufferobj.h" @@ -238,76 +239,31 @@ static GLuint get_index_type(GLenum type) } } -static void wrap_buffers( struct brw_context *brw, - GLuint size ) -{ - if (size < BRW_UPLOAD_INIT_SIZE) - size = BRW_UPLOAD_INIT_SIZE; - - brw->vb.upload.offset = 0; - - if (brw->vb.upload.bo != NULL) - drm_intel_bo_unreference(brw->vb.upload.bo); - brw->vb.upload.bo = drm_intel_bo_alloc(brw->intel.bufmgr, "temporary VBO", - size, 1); -} - -static void get_space( struct brw_context *brw, - GLuint size, - drm_intel_bo **bo_return, - GLuint *offset_return ) -{ - size = ALIGN(size, 64); - - if (brw->vb.upload.bo == NULL || - brw->vb.upload.offset + size > brw->vb.upload.bo->size) { - wrap_buffers(brw, size); - } - - assert(*bo_return == NULL); - drm_intel_bo_reference(brw->vb.upload.bo); - *bo_return = brw->vb.upload.bo; - *offset_return = brw->vb.upload.offset; - brw->vb.upload.offset += size; -} - static void copy_array_to_vbo_array( struct brw_context *brw, struct brw_vertex_element *element, + struct brw_vertex_buffer *buffer, GLuint dst_stride) { GLuint size = element->count * dst_stride; - get_space(brw, size, &element->bo, &element->offset); - - if (element->glarray->StrideB == 0) { - assert(element->count == 1); - element->stride = 0; - } else { - element->stride = dst_stride; - } - + buffer->stride = dst_stride; if (dst_stride == element->glarray->StrideB) { - drm_intel_gem_bo_map_gtt(element->bo); - memcpy((char *)element->bo->virtual + element->offset, - element->glarray->Ptr, size); - drm_intel_gem_bo_unmap_gtt(element->bo); + intel_upload_data(&brw->intel, element->glarray->Ptr, size, dst_stride, + &buffer->bo, &buffer->offset); } else { - char *dest; const unsigned char *src = element->glarray->Ptr; + char *map = intel_upload_map(&brw->intel, size, dst_stride); + char *dst = map; int i; - drm_intel_gem_bo_map_gtt(element->bo); - dest = element->bo->virtual; - dest += element->offset; - for (i = 0; i < element->count; i++) { - memcpy(dest, src, dst_stride); + memcpy(dst, src, dst_stride); src += element->glarray->StrideB; - dest += dst_stride; + dst += dst_stride; } - - drm_intel_gem_bo_unmap_gtt(element->bo); + intel_upload_unmap(&brw->intel, map, size, dst_stride, + &buffer->bo, &buffer->offset); } } @@ -316,11 +272,11 @@ static void brw_prepare_vertices(struct brw_context *brw) struct gl_context *ctx = &brw->intel.ctx; struct intel_context *intel = intel_context(ctx); GLbitfield vs_inputs = brw->vs.prog_data->inputs_read; - GLuint i; const unsigned char *ptr = NULL; - GLuint interleave = 0; + GLuint interleaved = 0, total_size = 0, count = -1; unsigned int min_index = brw->vb.min_index; unsigned int max_index = brw->vb.max_index; + int i, j; struct brw_vertex_element *upload[VERT_ATTRIB_MAX]; GLuint nr_uploads = 0; @@ -340,6 +296,12 @@ static void brw_prepare_vertices(struct brw_context *brw) brw->vb.enabled[brw->vb.nr_enabled++] = input; } + if (brw->vb.nr_enabled == 0) + return; + + if (brw->vb.nr_buffers) + goto validate; + /* XXX: In the rare cases where this happens we fallback all * the way to software rasterization, although a tnl fallback * would be sufficient. I don't know of *any* real world @@ -351,23 +313,43 @@ static void brw_prepare_vertices(struct brw_context *brw) return; } - for (i = 0; i < brw->vb.nr_enabled; i++) { + for (i = j = 0; i < brw->vb.nr_enabled; i++) { struct brw_vertex_element *input = brw->vb.enabled[i]; + const struct gl_client_array *glarray = input->glarray; + int type_size = get_size(glarray->Type); - input->element_size = get_size(input->glarray->Type) * input->glarray->Size; + input->element_size = type_size * glarray->Size; - if (_mesa_is_bufferobj(input->glarray->BufferObj)) { + if (_mesa_is_bufferobj(glarray->BufferObj)) { struct intel_buffer_object *intel_buffer = - intel_buffer_object(input->glarray->BufferObj); - - /* Named buffer object: Just reference its contents directly. */ - drm_intel_bo_unreference(input->bo); - input->bo = intel_bufferobj_buffer(intel, intel_buffer, - INTEL_READ); - drm_intel_bo_reference(input->bo); - input->offset = (unsigned long)input->glarray->Ptr; - input->stride = input->glarray->StrideB; - input->count = input->glarray->_MaxElement; + intel_buffer_object(glarray->BufferObj); + int k; + + for (k = 0; k < i; k++) { + const struct gl_client_array *other = brw->vb.enabled[k]->glarray; + if (glarray->BufferObj == other->BufferObj && + glarray->StrideB == other->StrideB && + (uintptr_t)(glarray->Ptr - other->Ptr) < glarray->StrideB) + { + input->buffer = brw->vb.enabled[k]->buffer; + input->offset = glarray->Ptr - other->Ptr; + break; + } + } + if (k == i) { + struct brw_vertex_buffer *buffer = &brw->vb.buffers[j]; + + /* Named buffer object: Just reference its contents directly. */ + buffer->bo = intel_bufferobj_source(intel, intel_buffer, + &buffer->offset); + drm_intel_bo_reference(buffer->bo); + buffer->offset += (uintptr_t)glarray->Ptr; + buffer->stride = glarray->StrideB; + + input->buffer = j++; + input->offset = 0; + } + input->count = glarray->_MaxElement; /* This is a common place to reach if the user mistakenly supplies * a pointer in place of a VBO offset. If we just let it go through, @@ -381,71 +363,138 @@ static void brw_prepare_vertices(struct brw_context *brw) * probably a service to the poor programmer to do so rather than * trying to just not render. */ - assert(input->offset < input->bo->size); + assert(input->offset < brw->vb.buffers[input->buffer].bo->size); } else { - input->count = input->glarray->StrideB ? max_index + 1 : 1; - if (input->bo != NULL) { - /* Already-uploaded vertex data is present from a previous - * prepare_vertices, but we had to re-validate state due to - * check_aperture failing and a new batch being produced. - */ - continue; - } + input->count = glarray->StrideB ? max_index + 1 : 1; /* Queue the buffer object up to be uploaded in the next pass, * when we've decided if we're doing interleaved or not. */ - if (input->attrib == VERT_ATTRIB_POS) { + if (nr_uploads == 0) { /* Position array not properly enabled: */ - if (input->glarray->StrideB == 0) { + if (input->attrib == VERT_ATTRIB_POS && glarray->StrideB == 0) { intel->Fallback = GL_TRUE; /* boolean, not bitfield */ return; } - interleave = input->glarray->StrideB; - ptr = input->glarray->Ptr; + interleaved = glarray->StrideB; + ptr = glarray->Ptr; } - else if (interleave != input->glarray->StrideB || - (const unsigned char *)input->glarray->Ptr - ptr < 0 || - (const unsigned char *)input->glarray->Ptr - ptr > interleave) + else if (interleaved != glarray->StrideB || + (uintptr_t)(glarray->Ptr - ptr) > interleaved) { - interleave = 0; + interleaved = 0; } + else if (total_size & (type_size -1)) + { + /* enforce natural alignment (for doubles) */ + interleaved = 0; + } + + if (count > input->count) + count = input->count; upload[nr_uploads++] = input; + total_size += input->element_size; } } /* Handle any arrays to be uploaded. */ - if (nr_uploads > 1 && interleave && interleave <= 256) { - /* All uploads are interleaved, so upload the arrays together as - * interleaved. First, upload the contents and set up upload[0]. - */ - copy_array_to_vbo_array(brw, upload[0], interleave); - - for (i = 1; i < nr_uploads; i++) { - /* Then, just point upload[i] at upload[0]'s buffer. */ - upload[i]->stride = interleave; - upload[i]->offset = upload[0]->offset + - ((const unsigned char *)upload[i]->glarray->Ptr - ptr); - upload[i]->bo = upload[0]->bo; - drm_intel_bo_reference(upload[i]->bo); + if (nr_uploads > 1) { + if (interleaved && interleaved <= 2*total_size) { + /* All uploads are interleaved, so upload the arrays together as + * interleaved. First, upload the contents and set up upload[0]. + */ + upload[0]->count = count; /* trim the upload over all arrays */ + copy_array_to_vbo_array(brw, + upload[0], &brw->vb.buffers[j], + interleaved); + + for (i = 0; i < nr_uploads; i++) { + /* Then, just point upload[i] at upload[0]'s buffer. */ + upload[i]->offset = + ((const unsigned char *)upload[i]->glarray->Ptr - ptr); + upload[i]->buffer = j; + } + j++; + + nr_uploads = 0; } - } - else { - /* Upload non-interleaved arrays */ - for (i = 0; i < nr_uploads; i++) { - copy_array_to_vbo_array(brw, upload[i], upload[i]->element_size); + else if (total_size < 2048) { + /* Upload non-interleaved arrays into a single interleaved array */ + struct brw_vertex_buffer *buffer = &brw->vb.buffers[j]; + int count = upload[0]->count, offset; + char *map; + + map = intel_upload_map(&brw->intel, total_size * count, total_size); + for (i = offset = 0; i < nr_uploads; i++) { + const unsigned char *src = upload[i]->glarray->Ptr; + int size = upload[i]->element_size; + int stride = upload[i]->glarray->StrideB; + char *dst = map + offset; + int n; + + for (n = 0; n < count; n++) { + memcpy(dst, src, size); + src += stride; + dst += total_size; + } + + upload[i]->offset = offset; + upload[i]->buffer = j; + + offset += size; + } + intel_upload_unmap(&brw->intel, map, total_size * count, total_size, + &buffer->bo, &buffer->offset); + buffer->stride = offset; + j++; + + nr_uploads = 0; } } + /* Upload non-interleaved arrays */ + for (i = 0; i < nr_uploads; i++) { + copy_array_to_vbo_array(brw, + upload[i], &brw->vb.buffers[j], + upload[i]->element_size); + upload[i]->buffer = j++; + upload[i]->offset = 0; + } - brw_prepare_query_begin(brw); + /* can we simply extend the current vb? */ + brw->vb.start_vertex_bias = 0; + if (j == brw->vb.nr_current_buffers) { + int delta = 0; + for (i = 0; i < j; i++) { + int d; + + if (brw->vb.current_buffers[i].handle != brw->vb.buffers[i].bo->handle || + brw->vb.current_buffers[i].stride != brw->vb.buffers[i].stride) + break; + + d = brw->vb.buffers[i].offset - brw->vb.current_buffers[i].offset; + if (delta == 0) + delta = d / brw->vb.current_buffers[i].stride; + if (delta * brw->vb.current_buffers[i].stride != d) + break; + } - for (i = 0; i < brw->vb.nr_enabled; i++) { - struct brw_vertex_element *input = brw->vb.enabled[i]; + if (i == j) { + brw->vb.start_vertex_bias = delta; + while (--j >= 0) + drm_intel_bo_unreference(brw->vb.buffers[j].bo); + j = 0; + } + } - brw_add_validated_bo(brw, input->bo); + brw->vb.nr_buffers = j; + +validate: + brw_prepare_query_begin(brw); + for (i = 0; i < brw->vb.nr_buffers; i++) { + brw_add_validated_bo(brw, brw->vb.buffers[i].bo); } } @@ -482,49 +531,44 @@ static void brw_emit_vertices(struct brw_context *brw) (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | (BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT)); - ADVANCE_BATCH(); + CACHED_BATCH(); return; } /* Now emit VB and VEP state packets. - * - * This still defines a hardware VB for each input, even if they - * are interleaved or from the same VBO. TBD if this makes a - * performance difference. */ - BEGIN_BATCH(1 + brw->vb.nr_enabled * 4); - OUT_BATCH((CMD_VERTEX_BUFFER << 16) | - ((1 + brw->vb.nr_enabled * 4) - 2)); - for (i = 0; i < brw->vb.nr_enabled; i++) { - struct brw_vertex_element *input = brw->vb.enabled[i]; - uint32_t dw0; + if (brw->vb.nr_buffers) { + BEGIN_BATCH(1 + 4*brw->vb.nr_buffers); + OUT_BATCH((CMD_VERTEX_BUFFER << 16) | (4*brw->vb.nr_buffers - 1)); + for (i = 0; i < brw->vb.nr_buffers; i++) { + struct brw_vertex_buffer *buffer = &brw->vb.buffers[i]; + uint32_t dw0; + + if (intel->gen >= 6) { + dw0 = GEN6_VB0_ACCESS_VERTEXDATA | (i << GEN6_VB0_INDEX_SHIFT); + } else { + dw0 = BRW_VB0_ACCESS_VERTEXDATA | (i << BRW_VB0_INDEX_SHIFT); + } - if (intel->gen >= 6) { - dw0 = GEN6_VB0_ACCESS_VERTEXDATA | - (i << GEN6_VB0_INDEX_SHIFT); - } else { - dw0 = BRW_VB0_ACCESS_VERTEXDATA | - (i << BRW_VB0_INDEX_SHIFT); + OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT)); + OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset); + if (intel->gen >= 5) { + OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1); + } else + OUT_BATCH(buffer->bo->size / buffer->stride); + OUT_BATCH(0); /* Instance data step rate */ + + brw->vb.current_buffers[i].handle = buffer->bo->handle; + brw->vb.current_buffers[i].offset = buffer->offset; + brw->vb.current_buffers[i].stride = buffer->stride; } - - OUT_BATCH(dw0 | - (input->stride << BRW_VB0_PITCH_SHIFT)); - OUT_RELOC(input->bo, - I915_GEM_DOMAIN_VERTEX, 0, - input->offset); - if (intel->gen >= 5) { - OUT_RELOC(input->bo, - I915_GEM_DOMAIN_VERTEX, 0, - input->bo->size - 1); - } else - OUT_BATCH(input->stride ? input->count : 0); - OUT_BATCH(0); /* Instance data step rate */ + brw->vb.nr_current_buffers = i; + ADVANCE_BATCH(); } - ADVANCE_BATCH(); BEGIN_BATCH(1 + brw->vb.nr_enabled * 2); - OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + brw->vb.nr_enabled * 2) - 2)); + OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | (2*brw->vb.nr_enabled - 1)); for (i = 0; i < brw->vb.nr_enabled; i++) { struct brw_vertex_element *input = brw->vb.enabled[i]; uint32_t format = get_surface_type(input->glarray->Type, @@ -545,15 +589,15 @@ static void brw_emit_vertices(struct brw_context *brw) } if (intel->gen >= 6) { - OUT_BATCH((i << GEN6_VE0_INDEX_SHIFT) | + OUT_BATCH((input->buffer << GEN6_VE0_INDEX_SHIFT) | GEN6_VE0_VALID | (format << BRW_VE0_FORMAT_SHIFT) | - (0 << BRW_VE0_SRC_OFFSET_SHIFT)); + (input->offset << BRW_VE0_SRC_OFFSET_SHIFT)); } else { - OUT_BATCH((i << BRW_VE0_INDEX_SHIFT) | + OUT_BATCH((input->buffer << BRW_VE0_INDEX_SHIFT) | BRW_VE0_VALID | (format << BRW_VE0_FORMAT_SHIFT) | - (0 << BRW_VE0_SRC_OFFSET_SHIFT)); + (input->offset << BRW_VE0_SRC_OFFSET_SHIFT)); } if (intel->gen >= 5) @@ -568,7 +612,7 @@ static void brw_emit_vertices(struct brw_context *brw) (comp3 << BRW_VE1_COMPONENT_3_SHIFT) | ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT)); } - ADVANCE_BATCH(); + CACHED_BATCH(); } const struct brw_tracked_state brw_vertices = { @@ -597,25 +641,20 @@ static void brw_prepare_indices(struct brw_context *brw) ib_type_size = get_size(index_buffer->type); ib_size = ib_type_size * index_buffer->count; - bufferobj = index_buffer->obj;; + bufferobj = index_buffer->obj; /* Turn into a proper VBO: */ if (!_mesa_is_bufferobj(bufferobj)) { - brw->ib.start_vertex_offset = 0; /* Get new bufferobj, offset: */ - get_space(brw, ib_size, &bo, &offset); - - /* Straight upload - */ - drm_intel_gem_bo_map_gtt(bo); - memcpy((char *)bo->virtual + offset, index_buffer->ptr, ib_size); - drm_intel_gem_bo_unmap_gtt(bo); + intel_upload_data(&brw->intel, index_buffer->ptr, ib_size, ib_type_size, + &bo, &offset); + brw->ib.start_vertex_offset = offset / ib_type_size; + offset = 0; } else { offset = (GLuint) (unsigned long) index_buffer->ptr; - brw->ib.start_vertex_offset = 0; /* If the index buffer isn't aligned to its element size, we have to * rebase it into a temporary. @@ -627,41 +666,35 @@ static void brw_prepare_indices(struct brw_context *brw) bufferobj); map += offset; - get_space(brw, ib_size, &bo, &offset); - - drm_intel_bo_subdata(bo, offset, ib_size, map); + intel_upload_data(&brw->intel, map, ib_size, ib_type_size, + &bo, &offset); + brw->ib.start_vertex_offset = offset / ib_type_size; + offset = 0; ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobj); } else { - bo = intel_bufferobj_buffer(intel, intel_buffer_object(bufferobj), - INTEL_READ); - drm_intel_bo_reference(bo); - /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading * the index buffer state when we're just moving the start index * of our drawing. */ brw->ib.start_vertex_offset = offset / ib_type_size; - offset = 0; - ib_size = bo->size; + + bo = intel_bufferobj_source(intel, intel_buffer_object(bufferobj), + &offset); + drm_intel_bo_reference(bo); } } - if (brw->ib.bo != bo || - brw->ib.offset != offset || - brw->ib.size != ib_size) - { + if (brw->ib.bo != bo || brw->ib.offset != offset) { drm_intel_bo_unreference(brw->ib.bo); brw->ib.bo = bo; brw->ib.offset = offset; - brw->ib.size = ib_size; + brw_add_validated_bo(brw, brw->ib.bo); brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER; } else { drm_intel_bo_unreference(bo); } - - brw_add_validated_bo(brw, brw->ib.bo); } const struct brw_tracked_state brw_indices = { @@ -681,29 +714,18 @@ static void brw_emit_index_buffer(struct brw_context *brw) if (index_buffer == NULL) return; - /* Emit the indexbuffer packet: - */ - { - struct brw_indexbuffer ib; - - memset(&ib, 0, sizeof(ib)); - - ib.header.bits.opcode = CMD_INDEX_BUFFER; - ib.header.bits.length = sizeof(ib)/4 - 2; - ib.header.bits.index_format = get_index_type(index_buffer->type); - ib.header.bits.cut_index_enable = 0; - - BEGIN_BATCH(4); - OUT_BATCH( ib.header.dword ); - OUT_RELOC(brw->ib.bo, - I915_GEM_DOMAIN_VERTEX, 0, - brw->ib.offset); - OUT_RELOC(brw->ib.bo, - I915_GEM_DOMAIN_VERTEX, 0, - brw->ib.offset + brw->ib.size - 1); - OUT_BATCH( 0 ); - ADVANCE_BATCH(); - } + BEGIN_BATCH(3); + OUT_BATCH(CMD_INDEX_BUFFER << 16 | + /* cut index enable << 10 */ + get_index_type(index_buffer->type) << 8 | + 1); + OUT_RELOC(brw->ib.bo, + I915_GEM_DOMAIN_VERTEX, 0, + brw->ib.offset); + OUT_RELOC(brw->ib.bo, + I915_GEM_DOMAIN_VERTEX, 0, + brw->ib.bo->size - 1); + ADVANCE_BATCH(); } const struct brw_tracked_state brw_index_buffer = { diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 9a71e5377df..30e3bd54469 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -41,7 +41,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "brw_fs.h" #include "../glsl/glsl_types.h" @@ -56,7 +55,7 @@ brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type) { struct brw_shader *shader; - shader = talloc_zero(NULL, struct brw_shader); + shader = rzalloc(NULL, struct brw_shader); if (shader) { shader->base.Type = type; shader->base.Name = name; @@ -70,7 +69,7 @@ struct gl_shader_program * brw_new_shader_program(struct gl_context *ctx, GLuint name) { struct brw_shader_program *prog; - prog = talloc_zero(NULL, struct brw_shader_program); + prog = rzalloc(NULL, struct brw_shader_program); if (prog) { prog->base.Name = name; _mesa_init_shader_program(ctx, &prog->base); @@ -96,11 +95,11 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) struct brw_shader *shader = (struct brw_shader *)prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; if (shader != NULL) { - void *mem_ctx = talloc_new(NULL); + void *mem_ctx = ralloc_context(NULL); bool progress; if (shader->ir) - talloc_free(shader->ir); + ralloc_free(shader->ir); shader->ir = new(shader) exec_list; clone_ir_list(mem_ctx, shader->ir, shader->base.ir); @@ -150,7 +149,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) validate_ir_tree(shader->ir); reparent_ir(shader->ir, shader->ir); - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } if (!_mesa_ir_link_shader(ctx, prog)) @@ -237,8 +236,8 @@ fs_visitor::virtual_grf_alloc(int size) virtual_grf_array_size = 16; else virtual_grf_array_size *= 2; - virtual_grf_sizes = talloc_realloc(mem_ctx, virtual_grf_sizes, - int, virtual_grf_array_size); + virtual_grf_sizes = reralloc(mem_ctx, virtual_grf_sizes, int, + virtual_grf_array_size); /* This slot is always unused. */ virtual_grf_sizes[0] = 0; @@ -495,7 +494,7 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir) wpos.reg_offset++; /* gl_FragCoord.w: Already set up in emit_interpolation */ - emit(fs_inst(BRW_OPCODE_MOV, wpos, this->wpos_w)); + emit(fs_inst(BRW_OPCODE_MOV, wpos, this->pixel_w)); return reg; } @@ -662,14 +661,18 @@ fs_visitor::emit_math(fs_opcodes opcode, fs_reg dst, fs_reg src0, fs_reg src1) assert(opcode == FS_OPCODE_POW); if (intel->gen >= 6) { - /* Can't do hstride == 0 args to gen6 math, so expand it out. */ - if (src0.file == UNIFORM) { + /* Can't do hstride == 0 args to gen6 math, so expand it out. + * + * The hardware ignores source modifiers (negate and abs) on math + * instructions, so we also move to a temp to set those up. + */ + if (src0.file == UNIFORM || src0.abs || src0.negate) { fs_reg expanded = fs_reg(this, glsl_type::float_type); emit(fs_inst(BRW_OPCODE_MOV, expanded, src0)); src0 = expanded; } - if (src1.file == UNIFORM) { + if (src1.file == UNIFORM || src1.abs || src1.negate) { fs_reg expanded = fs_reg(this, glsl_type::float_type); emit(fs_inst(BRW_OPCODE_MOV, expanded, src1)); src1 = expanded; @@ -1338,6 +1341,37 @@ fs_visitor::visit(ir_texture *ir) ir->coordinate->accept(this); fs_reg coordinate = this->result; + if (ir->offset != NULL) { + ir_constant *offset = ir->offset->as_constant(); + assert(offset != NULL); + + signed char offsets[3]; + for (unsigned i = 0; i < ir->offset->type->vector_elements; i++) + offsets[i] = (signed char) offset->value.i[i]; + + /* Combine all three offsets into a single unsigned dword: + * + * bits 11:8 - U Offset (X component) + * bits 7:4 - V Offset (Y component) + * bits 3:0 - R Offset (Z component) + */ + unsigned offset_bits = 0; + for (unsigned i = 0; i < ir->offset->type->vector_elements; i++) { + const unsigned shift = 4 * (2 - i); + offset_bits |= (offsets[i] << shift) & (0xF << shift); + } + + /* Explicitly set up the message header by copying g0 to msg reg m1. */ + emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, 1, BRW_REGISTER_TYPE_UD), + fs_reg(GRF, 0, BRW_REGISTER_TYPE_UD))); + + /* Then set the offset bits in DWord 2 of the message header. */ + emit(fs_inst(BRW_OPCODE_MOV, + fs_reg(retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, 1, 2), + BRW_REGISTER_TYPE_UD)), + fs_reg(brw_imm_uw(offset_bits)))); + } + /* Should be lowered by do_lower_texture_projection */ assert(!ir->projector); @@ -1398,6 +1432,14 @@ fs_visitor::visit(ir_texture *ir) inst = emit_texture_gen5(ir, dst, coordinate); } + /* If there's an offset, we already set up m1. To avoid the implied move, + * use the null register. Otherwise, we want an implied move from g0. + */ + if (ir->offset != NULL) + inst->src[0] = fs_reg(brw_null_reg()); + else + inst->src[0] = fs_reg(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW)); + inst->sampler = sampler; this->result = dst; @@ -2066,7 +2108,7 @@ fs_visitor::emit_fb_writes() } for (int target = 0; target < c->key.nr_color_regions; target++) { - this->current_annotation = talloc_asprintf(this->mem_ctx, + this->current_annotation = ralloc_asprintf(this->mem_ctx, "FB write target %d", target); if (this->frag_color || this->frag_data) { @@ -2244,7 +2286,7 @@ fs_visitor::generate_math(fs_inst *inst, } void -fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst) +fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src) { int msg_type = -1; int rlen = 4; @@ -2302,7 +2344,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst) brw_SAMPLE(p, retype(dst, BRW_REGISTER_TYPE_UW), inst->base_mrf, - retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW), + src, SURF_INDEX_TEXTURE(inst->sampler), inst->sampler, WRITEMASK_XYZW, @@ -2756,8 +2798,8 @@ void fs_visitor::calculate_live_intervals() { int num_vars = this->virtual_grf_next; - int *def = talloc_array(mem_ctx, int, num_vars); - int *use = talloc_array(mem_ctx, int, num_vars); + int *def = ralloc_array(mem_ctx, int, num_vars); + int *use = ralloc_array(mem_ctx, int, num_vars); int loop_depth = 0; int loop_start = 0; int bb_header_ip = 0; @@ -2840,8 +2882,8 @@ fs_visitor::calculate_live_intervals() } } - talloc_free(this->virtual_grf_def); - talloc_free(this->virtual_grf_use); + ralloc_free(this->virtual_grf_def); + ralloc_free(this->virtual_grf_use); this->virtual_grf_def = def; this->virtual_grf_use = use; @@ -3017,6 +3059,8 @@ fs_visitor::register_coalesce() inst->dst.type != inst->src[0].type) continue; + bool has_source_modifiers = inst->src[0].abs || inst->src[0].negate; + /* Found a move of a GRF to a GRF. Let's see if we can coalesce * them: check for no writes to either one until the exit of the * program. @@ -3041,6 +3085,14 @@ fs_visitor::register_coalesce() break; } } + + /* The gen6 MATH instruction can't handle source modifiers, so avoid + * coalescing those for now. We should do something more specific. + */ + if (intel->gen == 6 && scan_inst->is_math() && has_source_modifiers) { + interfered = true; + break; + } } if (interfered) { continue; @@ -3358,20 +3410,25 @@ void fs_visitor::generate_code() { int last_native_inst = 0; - struct brw_instruction *if_stack[16], *loop_stack[16]; - int if_stack_depth = 0, loop_stack_depth = 0; - int if_depth_in_loop[16]; const char *last_annotation_string = NULL; ir_instruction *last_annotation_ir = NULL; + int if_stack_array_size = 16; + int loop_stack_array_size = 16; + int if_stack_depth = 0, loop_stack_depth = 0; + brw_instruction **if_stack = + rzalloc_array(this->mem_ctx, brw_instruction *, if_stack_array_size); + brw_instruction **loop_stack = + rzalloc_array(this->mem_ctx, brw_instruction *, loop_stack_array_size); + int *if_depth_in_loop = + rzalloc_array(this->mem_ctx, int, loop_stack_array_size); + + if (unlikely(INTEL_DEBUG & DEBUG_WM)) { printf("Native code for fragment shader %d:\n", ctx->Shader.CurrentFragmentProgram->Name); } - if_depth_in_loop[loop_stack_depth] = 0; - - memset(&if_stack, 0, sizeof(if_stack)); foreach_iter(exec_list_iterator, iter, this->instructions) { fs_inst *inst = (fs_inst *)iter.get(); struct brw_reg src[3], dst; @@ -3455,7 +3512,6 @@ fs_visitor::generate_code() break; case BRW_OPCODE_IF: - assert(if_stack_depth < 16); if (inst->src[0].file != BAD_FILE) { assert(intel->gen >= 6); if_stack[if_stack_depth] = brw_IF_gen6(p, inst->conditional_mod, src[0], src[1]); @@ -3464,6 +3520,11 @@ fs_visitor::generate_code() } if_depth_in_loop[loop_stack_depth]++; if_stack_depth++; + if (if_stack_array_size <= if_stack_depth) { + if_stack_array_size *= 2; + if_stack = reralloc(this->mem_ctx, if_stack, brw_instruction *, + if_stack_array_size); + } break; case BRW_OPCODE_ELSE: @@ -3478,6 +3539,13 @@ fs_visitor::generate_code() case BRW_OPCODE_DO: loop_stack[loop_stack_depth++] = brw_DO(p, BRW_EXECUTE_8); + if (loop_stack_array_size <= loop_stack_depth) { + loop_stack_array_size *= 2; + loop_stack = reralloc(this->mem_ctx, loop_stack, brw_instruction *, + loop_stack_array_size); + if_depth_in_loop = reralloc(this->mem_ctx, if_depth_in_loop, int, + loop_stack_array_size); + } if_depth_in_loop[loop_stack_depth] = 0; break; @@ -3540,7 +3608,7 @@ fs_visitor::generate_code() case FS_OPCODE_TEX: case FS_OPCODE_TXB: case FS_OPCODE_TXL: - generate_tex(inst, dst); + generate_tex(inst, dst, src[0]); break; case FS_OPCODE_DISCARD_NOT: generate_discard_not(inst, dst); @@ -3596,6 +3664,10 @@ fs_visitor::generate_code() last_native_inst = p->nr_insn; } + ralloc_free(if_stack); + ralloc_free(loop_stack); + ralloc_free(if_depth_in_loop); + brw_set_uip_jip(p); /* OK, while the INTEL_DEBUG=wm above is very nice for debugging FS diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index f0497957bc4..8352760acf7 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -41,7 +41,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "../glsl/glsl_types.h" #include "../glsl/ir.h" @@ -83,13 +82,13 @@ enum fs_opcodes { class fs_reg { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_size(ctx, size); + node = ralloc_size(ctx, size); assert(node != NULL); return node; @@ -193,13 +192,13 @@ static const fs_reg reg_null_d(ARF, BRW_ARF_NULL, BRW_REGISTER_TYPE_D); class fs_inst : public exec_node { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_zero_size(ctx, size); + node = rzalloc_size(ctx, size); assert(node != NULL); return node; @@ -361,7 +360,7 @@ public: this->fp = brw->fragment_program; this->intel = &brw->intel; this->ctx = &intel->ctx; - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->shader = shader; this->fail = false; this->variable_ht = hash_table_ctor(0, @@ -405,7 +404,7 @@ public: ~fs_visitor() { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); hash_table_dtor(this->variable_ht); } @@ -454,7 +453,7 @@ public: void generate_fb_write(fs_inst *inst); void generate_linterp(fs_inst *inst, struct brw_reg dst, struct brw_reg *src); - void generate_tex(fs_inst *inst, struct brw_reg dst); + void generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src); void generate_math(fs_inst *inst, struct brw_reg dst, struct brw_reg *src); void generate_discard_not(fs_inst *inst, struct brw_reg temp); void generate_discard_and(fs_inst *inst, struct brw_reg temp); diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp index 20bfa4c3ea3..7f3f52854d2 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp @@ -141,7 +141,7 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir) return visit_continue; if (!this->mem_ctx) - this->mem_ctx = talloc_parent(ir); + this->mem_ctx = ralloc_parent(ir); for (i = 0; i < expr->get_num_operands(); i++) { if (expr->operands[i]->type->is_vector()) { diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp index 078a349abdf..f0277423170 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp @@ -41,7 +41,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "brw_fs.h" #include "../glsl/glsl_types.h" @@ -234,8 +233,8 @@ fs_visitor::assign_regs() } - talloc_free(g); - talloc_free(regs); + ralloc_free(g); + ralloc_free(regs); return false; } @@ -273,8 +272,8 @@ fs_visitor::assign_regs() this->grf_used = last_grf + 1; - talloc_free(g); - talloc_free(regs); + ralloc_free(g); + ralloc_free(regs); return true; } diff --git a/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp b/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp index c8f0b27b76f..bff8f82f3f7 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp @@ -39,7 +39,6 @@ extern "C" { #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" -#include "talloc.h" } #include "brw_fs.h" #include "../glsl/glsl_types.h" @@ -129,7 +128,7 @@ public: instruction_scheduler(fs_visitor *v, void *mem_ctx, int virtual_grf_count) { this->v = v; - this->mem_ctx = talloc_new(mem_ctx); + this->mem_ctx = ralloc_context(mem_ctx); this->virtual_grf_count = virtual_grf_count; this->instructions.make_empty(); this->instructions_to_schedule = 0; @@ -137,7 +136,7 @@ public: ~instruction_scheduler() { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); } void add_barrier_deps(schedule_node *n); void add_dep(schedule_node *before, schedule_node *after, int latency); @@ -196,11 +195,11 @@ instruction_scheduler::add_dep(schedule_node *before, schedule_node *after, else before->child_array_size *= 2; - before->children = talloc_realloc(mem_ctx, before->children, - schedule_node *, - before->child_array_size); - before->child_latency = talloc_realloc(mem_ctx, before->child_latency, - int, before->child_array_size); + before->children = reralloc(mem_ctx, before->children, + schedule_node *, + before->child_array_size); + before->child_latency = reralloc(mem_ctx, before->child_latency, + int, before->child_array_size); } before->children[before->child_count] = after; diff --git a/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp index 2be6b08b5c7..530ffa26580 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp @@ -69,7 +69,7 @@ public: ir_variable *components[4]; - /** talloc_parent(this->var) -- the shader's talloc context. */ + /** ralloc_parent(this->var) -- the shader's ralloc context. */ void *mem_ctx; }; @@ -77,13 +77,13 @@ class ir_vector_reference_visitor : public ir_hierarchical_visitor { public: ir_vector_reference_visitor(void) { - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->variable_list.make_empty(); } ~ir_vector_reference_visitor(void) { - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } virtual ir_visitor_status visit(ir_variable *); @@ -358,7 +358,7 @@ brw_do_vector_splitting(exec_list *instructions) if (refs.variable_list.is_empty()) return false; - void *mem_ctx = talloc_new(NULL); + void *mem_ctx = ralloc_context(NULL); /* Replace the decls of the vectors to be split with their split * components. @@ -368,10 +368,10 @@ brw_do_vector_splitting(exec_list *instructions) const struct glsl_type *type; type = glsl_type::get_instance(entry->var->type->base_type, 1, 1); - entry->mem_ctx = talloc_parent(entry->var); + entry->mem_ctx = ralloc_parent(entry->var); for (unsigned int i = 0; i < entry->var->type->vector_elements; i++) { - const char *name = talloc_asprintf(mem_ctx, "%s_%c", + const char *name = ralloc_asprintf(mem_ctx, "%s_%c", entry->var->name, "xyzw"[i]); @@ -386,7 +386,7 @@ brw_do_vector_splitting(exec_list *instructions) ir_vector_splitting_visitor split(&refs.variable_list); visit_list_elements(&split, instructions); - talloc_free(mem_ctx); + ralloc_free(mem_ctx); return true; } diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index 79afe19deba..c768be23fa7 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -74,7 +74,7 @@ static void upload_binding_table_pointers(struct brw_context *brw) struct intel_context *intel = &brw->intel; BEGIN_BATCH(6); - OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2)); + OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | (6 - 2)); OUT_BATCH(brw->vs.bind_bo_offset); OUT_BATCH(0); /* gs */ OUT_BATCH(0); /* clip */ @@ -104,7 +104,7 @@ static void upload_gen6_binding_table_pointers(struct brw_context *brw) struct intel_context *intel = &brw->intel; BEGIN_BATCH(4); - OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | + OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | GEN6_BINDING_TABLE_MODIFY_VS | GEN6_BINDING_TABLE_MODIFY_GS | GEN6_BINDING_TABLE_MODIFY_PS | @@ -142,7 +142,7 @@ static void upload_pipelined_state_pointers(struct brw_context *brw ) } BEGIN_BATCH(7); - OUT_BATCH(CMD_PIPELINED_STATE_POINTERS << 16 | (7 - 2)); + OUT_BATCH(_3DSTATE_PIPELINED_POINTERS << 16 | (7 - 2)); OUT_RELOC(brw->vs.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); if (brw->gs.prog_active) OUT_RELOC(brw->gs.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); @@ -151,7 +151,7 @@ static void upload_pipelined_state_pointers(struct brw_context *brw ) OUT_RELOC(brw->clip.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); OUT_RELOC(brw->sf.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_RELOC(brw->wm.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); - OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, + OUT_RELOC(brw->intel.batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, brw->cc.state_offset); ADVANCE_BATCH(); @@ -301,16 +301,15 @@ const struct brw_tracked_state brw_depthbuffer = { static void upload_polygon_stipple(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_polygon_stipple bps; GLuint i; if (!ctx->Polygon.StippleFlag) return; - memset(&bps, 0, sizeof(bps)); - bps.header.opcode = _3DSTATE_POLY_STIPPLE_PATTERN; - bps.header.length = sizeof(bps)/4-2; + BEGIN_BATCH(33); + OUT_BATCH(_3DSTATE_POLY_STIPPLE_PATTERN << 16 | (33 - 2)); /* Polygon stipple is provided in OpenGL order, i.e. bottom * row first. If we're rendering to a window (i.e. the @@ -321,14 +320,13 @@ static void upload_polygon_stipple(struct brw_context *brw) */ if (ctx->DrawBuffer->Name == 0) { for (i = 0; i < 32; i++) - bps.stipple[i] = ctx->PolygonStipple[31 - i]; /* invert */ + OUT_BATCH(ctx->PolygonStipple[31 - i]); /* invert */ } else { for (i = 0; i < 32; i++) - bps.stipple[i] = ctx->PolygonStipple[i]; /* don't invert */ + OUT_BATCH(ctx->PolygonStipple[i]); } - - BRW_CACHED_BATCH_STRUCT(brw, &bps); + CACHED_BATCH(); } const struct brw_tracked_state brw_polygon_stipple = { @@ -347,15 +345,14 @@ const struct brw_tracked_state brw_polygon_stipple = { static void upload_polygon_stipple_offset(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_polygon_stipple_offset bpso; if (!ctx->Polygon.StippleFlag) return; - memset(&bpso, 0, sizeof(bpso)); - bpso.header.opcode = _3DSTATE_POLY_STIPPLE_OFFSET; - bpso.header.length = sizeof(bpso)/4-2; + BEGIN_BATCH(2); + OUT_BATCH(_3DSTATE_POLY_STIPPLE_OFFSET << 16 | (2-2)); /* If we're drawing to a system window (ctx->DrawBuffer->Name == 0), * we have to invert the Y axis in order to match the OpenGL @@ -365,16 +362,11 @@ static void upload_polygon_stipple_offset(struct brw_context *brw) * system works just fine, and there's no window system to * worry about. */ - if (brw->intel.ctx.DrawBuffer->Name == 0) { - bpso.bits0.x_offset = 0; - bpso.bits0.y_offset = (32 - (ctx->DrawBuffer->Height & 31)) & 31; - } - else { - bpso.bits0.y_offset = 0; - bpso.bits0.x_offset = 0; - } - - BRW_CACHED_BATCH_STRUCT(brw, &bpso); + if (brw->intel.ctx.DrawBuffer->Name == 0) + OUT_BATCH((32 - (ctx->DrawBuffer->Height & 31)) & 31); + else + OUT_BATCH(0); + CACHED_BATCH(); } #define _NEW_WINDOW_POS 0x40000000 @@ -393,18 +385,17 @@ const struct brw_tracked_state brw_polygon_stipple_offset = { */ static void upload_aa_line_parameters(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_aa_line_parameters balp; if (!ctx->Line.SmoothFlag || !brw->has_aa_line_parameters) return; + OUT_BATCH(_3DSTATE_AA_LINE_PARAMETERS << 16 | (3 - 2)); /* use legacy aa line coverage computation */ - memset(&balp, 0, sizeof(balp)); - balp.header.opcode = _3DSTATE_AA_LINE_PARAMETERS; - balp.header.length = sizeof(balp) / 4 - 2; - - BRW_CACHED_BATCH_STRUCT(brw, &balp); + OUT_BATCH(0); + OUT_BATCH(0); + CACHED_BATCH(); } const struct brw_tracked_state brw_aa_line_parameters = { @@ -422,28 +413,21 @@ const struct brw_tracked_state brw_aa_line_parameters = { static void upload_line_stipple(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; struct gl_context *ctx = &brw->intel.ctx; - struct brw_line_stipple bls; GLfloat tmp; GLint tmpi; if (!ctx->Line.StippleFlag) return; - memset(&bls, 0, sizeof(bls)); - bls.header.opcode = _3DSTATE_LINE_STIPPLE_PATTERN; - bls.header.length = sizeof(bls)/4 - 2; - - bls.bits0.pattern = ctx->Line.StipplePattern; - bls.bits1.repeat_count = ctx->Line.StippleFactor; - + BEGIN_BATCH(3); + OUT_BATCH(_3DSTATE_LINE_STIPPLE_PATTERN << 16 | (3 - 2)); + OUT_BATCH(ctx->Line.StipplePattern); tmp = 1.0 / (GLfloat) ctx->Line.StippleFactor; tmpi = tmp * (1<<13); - - - bls.bits1.inverse_repeat_count = tmpi; - - BRW_CACHED_BATCH_STRUCT(brw, &bls); + OUT_BATCH(tmpi << 16 | ctx->Line.StippleFactor); + CACHED_BATCH(); } const struct brw_tracked_state brw_line_stipple = { @@ -565,7 +549,7 @@ static void upload_state_base_address( struct brw_context *brw ) BEGIN_BATCH(10); OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (10 - 2)); OUT_BATCH(1); /* General state base address */ - OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0, + OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); /* Surface state base address */ OUT_BATCH(1); /* Dynamic state base address */ OUT_BATCH(1); /* Indirect object base address */ @@ -579,7 +563,7 @@ static void upload_state_base_address( struct brw_context *brw ) BEGIN_BATCH(8); OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2)); OUT_BATCH(1); /* General state base address */ - OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0, + OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); /* Surface state base address */ OUT_BATCH(1); /* Indirect object base address */ OUT_BATCH(1); /* Instruction base address */ @@ -591,7 +575,7 @@ static void upload_state_base_address( struct brw_context *brw ) BEGIN_BATCH(6); OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2)); OUT_BATCH(1); /* General state base address */ - OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0, + OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); /* Surface state base address */ OUT_BATCH(1); /* Indirect object base address */ OUT_BATCH(1); /* General state upper bound */ diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c index 94efa791091..7d653327e30 100644 --- a/src/mesa/drivers/dri/i965/brw_program.c +++ b/src/mesa/drivers/dri/i965/brw_program.c @@ -36,7 +36,7 @@ #include "program/program.h" #include "program/programopt.h" #include "tnl/tnl.h" -#include "talloc.h" +#include "../glsl/ralloc.h" #include "brw_context.h" #include "brw_wm.h" @@ -115,7 +115,7 @@ shader_error(struct gl_context *ctx, struct gl_program *prog, const char *msg) shader = _mesa_lookup_shader_program(ctx, prog->Id); if (shader) { - shader->InfoLog = talloc_strdup_append(shader->InfoLog, msg); + ralloc_strcat(&shader->InfoLog, msg); shader->LinkStatus = GL_FALSE; } } diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c index 656aad630a1..b41d05dd438 100644 --- a/src/mesa/drivers/dri/i965/brw_queryobj.c +++ b/src/mesa/drivers/dri/i965/brw_queryobj.c @@ -177,7 +177,7 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q) ADVANCE_BATCH(); } - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); } else { /* Flush the batchbuffer in case it has writes to our query BO. * Have later queries write to a new query BO so that further rendering @@ -185,7 +185,7 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q) */ if (query->bo) { brw_emit_query_end(brw); - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); drm_intel_bo_unreference(brw->query.bo); brw->query.bo = NULL; diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index 4bb93e73369..86b0caa4a4e 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -164,26 +164,18 @@ void brw_destroy_caches( struct brw_context *brw ); /*********************************************************************** * brw_state_batch.c */ -#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(brw->intel.batch, (s), \ +#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(&brw->intel, (s), \ sizeof(*(s)), false) -#define BRW_CACHED_BATCH_STRUCT(brw, s) brw_cached_batch_struct( brw, (s), sizeof(*(s)) ) -GLboolean brw_cached_batch_struct( struct brw_context *brw, - const void *data, - GLuint sz ); -void brw_destroy_batch_cache( struct brw_context *brw ); -void brw_clear_batch_cache( struct brw_context *brw ); void *brw_state_batch(struct brw_context *brw, int size, int alignment, - drm_intel_bo **out_bo, uint32_t *out_offset); /* brw_wm_surface_state.c */ void brw_create_constant_surface(struct brw_context *brw, drm_intel_bo *bo, int width, - drm_intel_bo **out_bo, uint32_t *out_offset); #endif diff --git a/src/mesa/drivers/dri/i965/brw_state_batch.c b/src/mesa/drivers/dri/i965/brw_state_batch.c index a21af13caa3..213c7a38d8c 100644 --- a/src/mesa/drivers/dri/i965/brw_state_batch.c +++ b/src/mesa/drivers/dri/i965/brw_state_batch.c @@ -29,75 +29,10 @@ * Keith Whitwell <[email protected]> */ - - #include "brw_state.h" #include "intel_batchbuffer.h" #include "main/imports.h" - - -/* A facility similar to the data caching code above, which aims to - * prevent identical commands being issued repeatedly. - */ -GLboolean brw_cached_batch_struct( struct brw_context *brw, - const void *data, - GLuint sz ) -{ - struct brw_cached_batch_item *item = brw->cached_batch_items; - struct header *newheader = (struct header *)data; - - if (brw->emit_state_always) { - intel_batchbuffer_data(brw->intel.batch, data, sz, false); - return GL_TRUE; - } - - while (item) { - if (item->header->opcode == newheader->opcode) { - if (item->sz == sz && memcmp(item->header, newheader, sz) == 0) - return GL_FALSE; - if (item->sz != sz) { - free(item->header); - item->header = malloc(sz); - item->sz = sz; - } - goto emit; - } - item = item->next; - } - - assert(!item); - item = CALLOC_STRUCT(brw_cached_batch_item); - item->header = malloc(sz); - item->sz = sz; - item->next = brw->cached_batch_items; - brw->cached_batch_items = item; - - emit: - memcpy(item->header, newheader, sz); - intel_batchbuffer_data(brw->intel.batch, data, sz, false); - return GL_TRUE; -} - -void brw_clear_batch_cache( struct brw_context *brw ) -{ - struct brw_cached_batch_item *item = brw->cached_batch_items; - - while (item) { - struct brw_cached_batch_item *next = item->next; - free((void *)item->header); - free(item); - item = next; - } - - brw->cached_batch_items = NULL; -} - -void brw_destroy_batch_cache( struct brw_context *brw ) -{ - brw_clear_batch_cache(brw); -} - /** * Allocates a block of space in the batchbuffer for indirect state. * @@ -116,13 +51,12 @@ void * brw_state_batch(struct brw_context *brw, int size, int alignment, - drm_intel_bo **out_bo, uint32_t *out_offset) { - struct intel_batchbuffer *batch = brw->intel.batch; + struct intel_batchbuffer *batch = &brw->intel.batch; uint32_t offset; - assert(size < batch->buf->size); + assert(size < batch->bo->size); offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment); /* If allocating from the top would wrap below the batchbuffer, or @@ -130,19 +64,13 @@ brw_state_batch(struct brw_context *brw, * space, then flush and try again. */ if (batch->state_batch_offset < size || - offset < batch->ptr - batch->map + batch->reserved_space) { - intel_batchbuffer_flush(batch); + offset < 4*batch->used + batch->reserved_space) { + intel_batchbuffer_flush(&brw->intel); offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment); } batch->state_batch_offset = offset; - if (*out_bo != batch->buf) { - drm_intel_bo_unreference(*out_bo); - drm_intel_bo_reference(batch->buf); - *out_bo = batch->buf; - } - *out_offset = offset; - return batch->map + offset; + return batch->map + (offset>>2); } diff --git a/src/mesa/drivers/dri/i965/brw_state_cache.c b/src/mesa/drivers/dri/i965/brw_state_cache.c index 7045888ad4a..01eeb19a684 100644 --- a/src/mesa/drivers/dri/i965/brw_state_cache.c +++ b/src/mesa/drivers/dri/i965/brw_state_cache.c @@ -431,8 +431,6 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache) void brw_state_cache_check_size(struct brw_context *brw) { - DBG("%s (n_items=%d)\n", __FUNCTION__, brw->cache.n_items); - /* un-tuned guess. Each object is generally a page, so 1000 of them is 4 MB of * state cache. */ diff --git a/src/mesa/drivers/dri/i965/brw_state_dump.c b/src/mesa/drivers/dri/i965/brw_state_dump.c index e2628874712..fdce79da2f4 100644 --- a/src/mesa/drivers/dri/i965/brw_state_dump.c +++ b/src/mesa/drivers/dri/i965/brw_state_dump.c @@ -26,6 +26,7 @@ */ #include "main/mtypes.h" +#include "intel_batchbuffer.h" #include "brw_context.h" #include "brw_defines.h" @@ -54,7 +55,8 @@ state_out(const char *name, void *data, uint32_t hw_offset, int index, /** Generic, undecoded state buffer debug printout */ static void -state_struct_out(const char *name, drm_intel_bo *buffer, unsigned int state_size) +state_struct_out(const char *name, drm_intel_bo *buffer, + unsigned int offset, unsigned int size) { int i; @@ -62,8 +64,8 @@ state_struct_out(const char *name, drm_intel_bo *buffer, unsigned int state_size return; drm_intel_bo_map(buffer, GL_FALSE); - for (i = 0; i < state_size / 4; i++) { - state_out(name, buffer->virtual, buffer->offset, i, + for (i = 0; i < size / 4; i++) { + state_out(name, buffer->virtual + offset, buffer->offset + offset, i, "dword %d\n", i); } drm_intel_bo_unmap(buffer); @@ -98,21 +100,25 @@ get_965_surface_format(unsigned int surface_format) static void dump_wm_surface_state(struct brw_context *brw) { + dri_bo *bo; + GLubyte *base; int i; + bo = brw->intel.batch.bo; + drm_intel_bo_map(bo, GL_FALSE); + base = bo->virtual; + for (i = 0; i < brw->wm.nr_surfaces; i++) { - drm_intel_bo *surf_bo = brw->wm.surf_bo[i]; unsigned int surfoff; struct brw_surface_state *surf; char name[20]; - if (surf_bo == NULL) { + if (brw->wm.surf_offset[i] == 0) { fprintf(stderr, "WM SURF%d: NULL\n", i); continue; } - drm_intel_bo_map(surf_bo, GL_FALSE); - surfoff = surf_bo->offset + brw->wm.surf_offset[i]; - surf = (struct brw_surface_state *)(surf_bo->virtual + brw->wm.surf_offset[i]); + surfoff = bo->offset + brw->wm.surf_offset[i]; + surf = (struct brw_surface_state *)(base + brw->wm.surf_offset[i]); sprintf(name, "WM SURF%d", i); state_out(name, surf, surfoff, 0, "%s %s\n", @@ -127,9 +133,8 @@ static void dump_wm_surface_state(struct brw_context *brw) surf->ss4.min_lod); state_out(name, surf, surfoff, 5, "x,y offset: %d,%d\n", surf->ss5.x_offset, surf->ss5.y_offset); - - drm_intel_bo_unmap(surf_bo); } + drm_intel_bo_unmap(bo); } @@ -280,13 +285,14 @@ static void dump_cc_state(struct brw_context *brw) const char *name = "CC"; struct gen6_color_calc_state *cc; uint32_t cc_off; + dri_bo *bo = brw->intel.batch.bo; - if (brw->cc.state_bo == NULL) + if (brw->cc.state_offset == 0) return; - drm_intel_bo_map(brw->cc.state_bo, GL_FALSE); - cc = brw->cc.state_bo->virtual; - cc_off = brw->cc.state_bo->offset; + drm_intel_bo_map(bo, GL_FALSE); + cc = bo->virtual; + cc_off = bo->offset; state_out(name, cc, cc_off, 0, "alpha test format %s, round disable %d, stencil ref %d," "bf stencil ref %d\n", @@ -300,7 +306,7 @@ static void dump_cc_state(struct brw_context *brw) state_out(name, cc, cc_off, 4, "constant blue %f\n", cc->constant_b); state_out(name, cc, cc_off, 5, "constant alpha %f\n", cc->constant_a); - drm_intel_bo_unmap(brw->cc.state_bo); + drm_intel_bo_unmap(bo); } @@ -369,26 +375,29 @@ void brw_debug_batch(struct intel_context *intel) { struct brw_context *brw = brw_context(&intel->ctx); - state_struct_out("WM bind", brw->wm.bind_bo, 4 * brw->wm.nr_surfaces); + state_struct_out("WM bind", + brw->intel.batch.bo, + brw->wm.bind_bo_offset, + 4 * brw->wm.nr_surfaces); dump_wm_surface_state(brw); dump_wm_sampler_state(brw); if (intel->gen < 6) - state_struct_out("VS", brw->vs.state_bo, sizeof(struct brw_vs_unit_state)); + state_struct_out("VS", brw->vs.state_bo, 0, sizeof(struct brw_vs_unit_state)); brw_debug_prog("VS prog", brw->vs.prog_bo); if (intel->gen < 6) - state_struct_out("GS", brw->gs.state_bo, sizeof(struct brw_gs_unit_state)); + state_struct_out("GS", brw->gs.state_bo, 0, sizeof(struct brw_gs_unit_state)); brw_debug_prog("GS prog", brw->gs.prog_bo); if (intel->gen < 6) { - state_struct_out("SF", brw->sf.state_bo, sizeof(struct brw_sf_unit_state)); + state_struct_out("SF", brw->sf.state_bo, 0, sizeof(struct brw_sf_unit_state)); brw_debug_prog("SF prog", brw->sf.prog_bo); } dump_sf_viewport_state(brw); if (intel->gen < 6) - state_struct_out("WM", brw->wm.state_bo, sizeof(struct brw_wm_unit_state)); + state_struct_out("WM", brw->wm.state_bo, 0, sizeof(struct brw_wm_unit_state)); brw_debug_prog("WM prog", brw->wm.prog_bo); if (intel->gen >= 6) { diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c index eba4411ca70..2d6fb37355d 100644 --- a/src/mesa/drivers/dri/i965/brw_state_upload.c +++ b/src/mesa/drivers/dri/i965/brw_state_upload.c @@ -176,17 +176,16 @@ void brw_init_state( struct brw_context *brw ) void brw_destroy_state( struct brw_context *brw ) { brw_destroy_caches(brw); - brw_destroy_batch_cache(brw); } /*********************************************************************** */ -static GLboolean check_state( const struct brw_state_flags *a, - const struct brw_state_flags *b ) +static GLuint check_state( const struct brw_state_flags *a, + const struct brw_state_flags *b ) { - return ((a->mesa & b->mesa) || - (a->brw & b->brw) || + return ((a->mesa & b->mesa) | + (a->brw & b->brw) | (a->cache & b->cache)); } @@ -233,7 +232,6 @@ static struct dirty_bit_map mesa_bits[] = { DEFINE_BIT(_NEW_MODELVIEW), DEFINE_BIT(_NEW_PROJECTION), DEFINE_BIT(_NEW_TEXTURE_MATRIX), - DEFINE_BIT(_NEW_ACCUM), DEFINE_BIT(_NEW_COLOR), DEFINE_BIT(_NEW_DEPTH), DEFINE_BIT(_NEW_EVAL), @@ -279,6 +277,10 @@ static struct dirty_bit_map brw_bits[] = { DEFINE_BIT(BRW_NEW_VERTICES), DEFINE_BIT(BRW_NEW_BATCH), DEFINE_BIT(BRW_NEW_DEPTH_BUFFER), + DEFINE_BIT(BRW_NEW_NR_WM_SURFACES), + DEFINE_BIT(BRW_NEW_NR_VS_SURFACES), + DEFINE_BIT(BRW_NEW_VS_CONSTBUF), + DEFINE_BIT(BRW_NEW_WM_CONSTBUF), {0, 0, 0} }; @@ -349,7 +351,7 @@ void brw_validate_state( struct brw_context *brw ) state->mesa |= brw->intel.NewGLState; brw->intel.NewGLState = 0; - brw_add_validated_bo(brw, intel->batch->buf); + brw_add_validated_bo(brw, intel->batch.bo); if (intel->gen >= 6) { atoms = gen6_atoms; @@ -375,14 +377,9 @@ void brw_validate_state( struct brw_context *brw ) brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; } - if (state->mesa == 0 && - state->cache == 0 && - state->brw == 0) + if ((state->mesa | state->cache | state->brw) == 0) return; - if (brw->state.dirty.brw & BRW_NEW_CONTEXT) - brw_clear_batch_cache(brw); - brw->intel.Fallback = GL_FALSE; /* boolean, not bitfield */ /* do prepare stage for all atoms */ diff --git a/src/mesa/drivers/dri/i965/brw_util.c b/src/mesa/drivers/dri/i965/brw_util.c index e878da3850d..d28d9abcb33 100644 --- a/src/mesa/drivers/dri/i965/brw_util.c +++ b/src/mesa/drivers/dri/i965/brw_util.c @@ -37,16 +37,6 @@ #include "brw_util.h" #include "brw_defines.h" -GLuint brw_count_bits(uint64_t val) -{ - GLuint i; - for (i = 0; val ; val >>= 1) - if (val & 1) - i++; - return i; -} - - GLuint brw_translate_blend_equation( GLenum mode ) { switch (mode) { diff --git a/src/mesa/drivers/dri/i965/brw_util.h b/src/mesa/drivers/dri/i965/brw_util.h index 04f3175d3e1..940a8715502 100644 --- a/src/mesa/drivers/dri/i965/brw_util.h +++ b/src/mesa/drivers/dri/i965/brw_util.h @@ -35,7 +35,14 @@ #include "main/mtypes.h" -extern GLuint brw_count_bits(uint64_t val); +#ifdef __GNUC__ +#define brw_count_bits(v) __builtin_popcount(v) +#else +static inline GLuint brw_count_bits(uint64_t v) +{ + return _mesa_popcount(v>>32) + _mesa_popcount(v&0xffffffff); +} +#endif extern GLuint brw_parameter_list_state_flags(struct gl_program_parameter_list *paramList); extern GLuint brw_translate_blend_factor( GLenum factor ); extern GLuint brw_translate_blend_equation( GLenum mode ); diff --git a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c index b0b05445eb9..48cf265e51b 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c @@ -124,13 +124,11 @@ brw_update_vs_constant_surface( struct gl_context *ctx, * it. */ if (brw->vs.const_bo == NULL) { - drm_intel_bo_unreference(brw->vs.surf_bo[surf]); - brw->vs.surf_bo[surf] = NULL; + brw->vs.surf_offset[surf] = 0; return; } brw_create_constant_surface(brw, brw->vs.const_bo, params->NumParameters, - &brw->vs.surf_bo[surf], &brw->vs.surf_offset[surf]); } @@ -166,11 +164,10 @@ static void upload_vs_surfaces(struct brw_context *brw) /* BRW_NEW_NR_VS_SURFACES */ if (brw->vs.nr_surfaces == 0) { - if (brw->vs.bind_bo) { - drm_intel_bo_unreference(brw->vs.bind_bo); - brw->vs.bind_bo = NULL; + if (brw->vs.bind_bo_offset) { brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE; } + brw->vs.bind_bo_offset = 0; return; } @@ -180,15 +177,11 @@ static void upload_vs_surfaces(struct brw_context *brw) * space for the binding table. (once we have vs samplers) */ bind = brw_state_batch(brw, sizeof(uint32_t) * BRW_VS_MAX_SURF, - 32, &brw->vs.bind_bo, &brw->vs.bind_bo_offset); + 32, &brw->vs.bind_bo_offset); for (i = 0; i < BRW_VS_MAX_SURF; i++) { /* BRW_NEW_VS_CONSTBUF */ - if (brw->vs.surf_bo[i]) { - bind[i] = brw->vs.surf_offset[i]; - } else { - bind[i] = 0; - } + bind[i] = brw->vs.surf_offset[i]; } brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE; diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c index 100a21b59d7..152ee141568 100644 --- a/src/mesa/drivers/dri/i965/brw_vtbl.c +++ b/src/mesa/drivers/dri/i965/brw_vtbl.c @@ -73,15 +73,11 @@ static void brw_destroy_context( struct intel_context *intel ) free(brw->wm.compile_data); } - for (i = 0; i < brw->state.nr_color_regions; i++) - intel_region_release(&brw->state.color_regions[i]); - brw->state.nr_color_regions = 0; intel_region_release(&brw->state.depth_region); dri_bo_release(&brw->curbe.curbe_bo); dri_bo_release(&brw->vs.prog_bo); dri_bo_release(&brw->vs.state_bo); - dri_bo_release(&brw->vs.bind_bo); dri_bo_release(&brw->vs.const_bo); dri_bo_release(&brw->gs.prog_bo); dri_bo_release(&brw->gs.state_bo); @@ -93,16 +89,12 @@ static void brw_destroy_context( struct intel_context *intel ) dri_bo_release(&brw->sf.vp_bo); for (i = 0; i < BRW_MAX_TEX_UNIT; i++) dri_bo_release(&brw->wm.sdc_bo[i]); - dri_bo_release(&brw->wm.bind_bo); - for (i = 0; i < BRW_WM_MAX_SURF; i++) - dri_bo_release(&brw->wm.surf_bo[i]); dri_bo_release(&brw->wm.sampler_bo); dri_bo_release(&brw->wm.prog_bo); dri_bo_release(&brw->wm.state_bo); dri_bo_release(&brw->wm.const_bo); dri_bo_release(&brw->wm.push_const_bo); dri_bo_release(&brw->cc.prog_bo); - dri_bo_release(&brw->cc.state_bo); dri_bo_release(&brw->cc.vp_bo); dri_bo_release(&brw->cc.blend_state_bo); dri_bo_release(&brw->cc.depth_stencil_state_bo); @@ -122,20 +114,14 @@ static void brw_set_draw_region( struct intel_context *intel, GLuint num_color_regions) { struct brw_context *brw = brw_context(&intel->ctx); - GLuint i; /* release old color/depth regions */ if (brw->state.depth_region != depth_region) brw->state.dirty.brw |= BRW_NEW_DEPTH_BUFFER; - for (i = 0; i < brw->state.nr_color_regions; i++) - intel_region_release(&brw->state.color_regions[i]); intel_region_release(&brw->state.depth_region); /* reference new color/depth regions */ - for (i = 0; i < num_color_regions; i++) - intel_region_reference(&brw->state.color_regions[i], color_regions[i]); intel_region_reference(&brw->state.depth_region, depth_region); - brw->state.nr_color_regions = num_color_regions; } @@ -173,14 +159,7 @@ static void brw_new_batch( struct intel_context *intel ) brw->state.dirty.brw |= ~0; brw->state.dirty.cache |= ~0; - /* Move to the end of the current upload buffer so that we'll force choosing - * a new buffer next time. - */ - if (brw->vb.upload.bo != NULL) { - drm_intel_bo_unreference(brw->vb.upload.bo); - brw->vb.upload.bo = NULL; - brw->vb.upload.offset = 0; - } + brw->vb.nr_current_buffers = 0; } static void brw_invalidate_state( struct intel_context *intel, GLuint new_state ) diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 656501b4f79..ee8212f6f16 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -431,7 +431,8 @@ static void brw_wm_populate_key( struct brw_context *brw, key->render_to_fbo = ctx->DrawBuffer->Name != 0; } - key->nr_color_regions = brw->state.nr_color_regions; + /* _NEW_BUFFERS */ + key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; /* CACHE_NEW_VS_PROG */ key->vp_outputs_written = brw->vs.prog_data->outputs_written; diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c index e9ef635bca2..5b5afc4626b 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_state.c @@ -47,7 +47,6 @@ struct brw_wm_unit_key { unsigned int dispatch_grf_start_reg; unsigned int curbe_offset; - unsigned int urb_size; unsigned int nr_surfaces, sampler_count; GLboolean uses_depth, computes_depth, uses_kill, is_glsl; @@ -98,9 +97,6 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key) key->dispatch_grf_start_reg = brw->wm.prog_data->first_curbe_grf; key->total_scratch = brw->wm.prog_data->total_scratch; - /* BRW_NEW_URB_FENCE */ - key->urb_size = brw->urb.vsize; - /* BRW_NEW_CURBE_OFFSETS */ key->curbe_offset = brw->curbe.wm_start; 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 a372554555c..1010d9f6f9c 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -188,47 +188,43 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit ) struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel]; const GLuint surf_index = SURF_INDEX_TEXTURE(unit); - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); + surf = brw_state_batch(brw, sizeof(*surf), 32, + &brw->wm.surf_offset[surf_index]); + memset(surf, 0, sizeof(*surf)); - surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - surf.ss0.surface_type = translate_tex_target(tObj->Target); - surf.ss0.surface_format = translate_tex_format(firstImage->TexFormat, + surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + surf->ss0.surface_type = translate_tex_target(tObj->Target); + surf->ss0.surface_format = translate_tex_format(firstImage->TexFormat, firstImage->InternalFormat, tObj->DepthMode, tObj->sRGBDecode); /* This is ok for all textures with channel width 8bit or less: */ -/* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ - surf.ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */ +/* surf->ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ + surf->ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */ - surf.ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel; - surf.ss2.width = firstImage->Width - 1; - surf.ss2.height = firstImage->Height - 1; - brw_set_surface_tiling(&surf, intelObj->mt->region->tiling); - surf.ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1; - surf.ss3.depth = firstImage->Depth - 1; + surf->ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel; + surf->ss2.width = firstImage->Width - 1; + surf->ss2.height = firstImage->Height - 1; + brw_set_surface_tiling(surf, intelObj->mt->region->tiling); + surf->ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1; + surf->ss3.depth = firstImage->Depth - 1; - surf.ss4.min_lod = 0; + surf->ss4.min_lod = 0; if (tObj->Target == GL_TEXTURE_CUBE_MAP) { - surf.ss0.cube_pos_x = 1; - surf.ss0.cube_pos_y = 1; - surf.ss0.cube_pos_z = 1; - surf.ss0.cube_neg_x = 1; - surf.ss0.cube_neg_y = 1; - surf.ss0.cube_neg_z = 1; + surf->ss0.cube_pos_x = 1; + surf->ss0.cube_pos_y = 1; + surf->ss0.cube_pos_z = 1; + surf->ss0.cube_neg_x = 1; + surf->ss0.cube_neg_y = 1; + surf->ss0.cube_neg_z = 1; } - map = brw_state_batch(brw, sizeof(surf), 32, - &brw->wm.surf_bo[surf_index], - &brw->wm.surf_offset[surf_index]); - memcpy(map, &surf, sizeof(surf)); - /* Emit relocation to surface contents */ - drm_intel_bo_emit_reloc(brw->wm.surf_bo[surf_index], + drm_intel_bo_emit_reloc(brw->intel.batch.bo, brw->wm.surf_offset[surf_index] + offsetof(struct brw_surface_state, ss1), intelObj->mt->region->buffer, 0, @@ -243,41 +239,38 @@ void brw_create_constant_surface(struct brw_context *brw, drm_intel_bo *bo, int width, - drm_intel_bo **out_bo, uint32_t *out_offset) { struct intel_context *intel = &brw->intel; const GLint w = width - 1; - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); + surf = brw_state_batch(brw, sizeof(*surf), 32, out_offset); + memset(surf, 0, sizeof(*surf)); - surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - surf.ss0.surface_type = BRW_SURFACE_BUFFER; - surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + surf->ss0.surface_type = BRW_SURFACE_BUFFER; + surf->ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; if (intel->gen >= 6) - surf.ss0.render_cache_read_write = 1; + surf->ss0.render_cache_read_write = 1; assert(bo); - surf.ss1.base_addr = bo->offset; /* reloc */ - - surf.ss2.width = w & 0x7f; /* bits 6:0 of size or width */ - surf.ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */ - surf.ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */ - surf.ss3.pitch = (width * 16) - 1; /* ignored?? */ - brw_set_surface_tiling(&surf, I915_TILING_NONE); /* tiling now allowed */ + surf->ss1.base_addr = bo->offset; /* reloc */ - map = brw_state_batch(brw, sizeof(surf), 32, out_bo, out_offset); - memcpy(map, &surf, sizeof(surf)); + surf->ss2.width = w & 0x7f; /* bits 6:0 of size or width */ + surf->ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */ + surf->ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */ + surf->ss3.pitch = (width * 16) - 1; /* ignored?? */ + brw_set_surface_tiling(surf, I915_TILING_NONE); /* tiling now allowed */ /* Emit relocation to surface contents. Section 5.1.1 of the gen4 * bspec ("Data Cache") says that the data cache does not exist as * a separate cache and is just the sampler cache. */ - drm_intel_bo_emit_reloc(*out_bo, (*out_offset + - offsetof(struct brw_surface_state, ss1)), + drm_intel_bo_emit_reloc(brw->intel.batch.bo, + (*out_offset + + offsetof(struct brw_surface_state, ss1)), bo, 0, I915_GEM_DOMAIN_SAMPLER, 0); } @@ -356,16 +349,14 @@ static void upload_wm_constant_surface(struct brw_context *brw ) * it. */ if (brw->wm.const_bo == 0) { - if (brw->wm.surf_bo[surf] != NULL) { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; + if (brw->wm.surf_offset[surf]) { brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; + brw->wm.surf_offset[surf] = 0; } return; } brw_create_constant_surface(brw, brw->wm.const_bo, params->NumParameters, - &brw->wm.surf_bo[surf], &brw->wm.surf_offset[surf]); brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; } @@ -384,33 +375,23 @@ static void brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) { struct intel_context *intel = &brw->intel; - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); - - surf.ss0.surface_type = BRW_SURFACE_NULL; - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - surf.ss1.base_addr = 0; + surf = brw_state_batch(brw, sizeof(*surf), 32, + &brw->wm.surf_offset[unit]); + memset(surf, 0, sizeof(*surf)); - surf.ss2.width = 0; - surf.ss2.height = 0; - brw_set_surface_tiling(&surf, I915_TILING_NONE); - surf.ss3.pitch = 0; + surf->ss0.surface_type = BRW_SURFACE_NULL; + surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; if (intel->gen < 6) { /* _NEW_COLOR */ - surf.ss0.color_blend = 0; - surf.ss0.writedisable_red = 1; - surf.ss0.writedisable_green = 1; - surf.ss0.writedisable_blue = 1; - surf.ss0.writedisable_alpha = 1; + surf->ss0.color_blend = 0; + surf->ss0.writedisable_red = 1; + surf->ss0.writedisable_green = 1; + surf->ss0.writedisable_blue = 1; + surf->ss0.writedisable_alpha = 1; } - - map = brw_state_batch(brw, sizeof(surf), 32, - &brw->wm.surf_bo[unit], - &brw->wm.surf_offset[unit]); - memcpy(map, &surf, sizeof(surf)); } /** @@ -427,10 +408,11 @@ brw_update_renderbuffer_surface(struct brw_context *brw, struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct intel_region *region = irb->region; - struct brw_surface_state surf; - void *map; + struct brw_surface_state *surf; - memset(&surf, 0, sizeof(surf)); + surf = brw_state_batch(brw, sizeof(*surf), 32, + &brw->wm.surf_offset[unit]); + memset(surf, 0, sizeof(*surf)); switch (irb->Base.Format) { case MESA_FORMAT_XRGB8888: @@ -441,21 +423,24 @@ brw_update_renderbuffer_surface(struct brw_context *brw, * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is * used. */ - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; break; case MESA_FORMAT_SARGB8: /* without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB surfaces to the blend/update as sRGB */ - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + if (ctx->Color.sRGBEnabled) + surf->ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format]; + else + surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; break; default: - surf.ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format]; - assert(surf.ss0.surface_format != 0); + surf->ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format]; + assert(surf->ss0.surface_format != 0); } - surf.ss0.surface_type = BRW_SURFACE_2D; + surf->ss0.surface_type = BRW_SURFACE_2D; if (region->tiling == I915_TILING_NONE) { - surf.ss1.base_addr = (region->draw_x + + surf->ss1.base_addr = (region->draw_x + region->draw_y * region->pitch) * region->cpp; } else { uint32_t tile_base, tile_x, tile_y; @@ -479,43 +464,38 @@ brw_update_renderbuffer_surface(struct brw_context *brw, /* Note that the low bits of these fields are missing, so * there's the possibility of getting in trouble. */ - surf.ss1.base_addr = tile_base; - surf.ss5.x_offset = tile_x / 4; - surf.ss5.y_offset = tile_y / 2; + surf->ss1.base_addr = tile_base; + surf->ss5.x_offset = tile_x / 4; + surf->ss5.y_offset = tile_y / 2; } - surf.ss1.base_addr += region->buffer->offset; /* reloc */ + surf->ss1.base_addr += region->buffer->offset; /* reloc */ - surf.ss2.width = rb->Width - 1; - surf.ss2.height = rb->Height - 1; - brw_set_surface_tiling(&surf, region->tiling); - surf.ss3.pitch = (region->pitch * region->cpp) - 1; + surf->ss2.width = rb->Width - 1; + surf->ss2.height = rb->Height - 1; + brw_set_surface_tiling(surf, region->tiling); + surf->ss3.pitch = (region->pitch * region->cpp) - 1; if (intel->gen < 6) { /* _NEW_COLOR */ - surf.ss0.color_blend = (!ctx->Color._LogicOpEnabled && + surf->ss0.color_blend = (!ctx->Color._LogicOpEnabled && (ctx->Color.BlendEnabled & (1 << unit))); - surf.ss0.writedisable_red = !ctx->Color.ColorMask[unit][0]; - surf.ss0.writedisable_green = !ctx->Color.ColorMask[unit][1]; - surf.ss0.writedisable_blue = !ctx->Color.ColorMask[unit][2]; + surf->ss0.writedisable_red = !ctx->Color.ColorMask[unit][0]; + surf->ss0.writedisable_green = !ctx->Color.ColorMask[unit][1]; + surf->ss0.writedisable_blue = !ctx->Color.ColorMask[unit][2]; /* As mentioned above, disable writes to the alpha component when the * renderbuffer is XRGB. */ if (ctx->DrawBuffer->Visual.alphaBits == 0) - surf.ss0.writedisable_alpha = 1; + surf->ss0.writedisable_alpha = 1; else - surf.ss0.writedisable_alpha = !ctx->Color.ColorMask[unit][3]; + surf->ss0.writedisable_alpha = !ctx->Color.ColorMask[unit][3]; } - map = brw_state_batch(brw, sizeof(surf), 32, - &brw->wm.surf_bo[unit], - &brw->wm.surf_offset[unit]); - memcpy(map, &surf, sizeof(surf)); - - drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit], + drm_intel_bo_emit_reloc(brw->intel.batch.bo, brw->wm.surf_offset[unit] + offsetof(struct brw_surface_state, ss1), region->buffer, - surf.ss1.base_addr - region->buffer->offset, + surf->ss1.base_addr - region->buffer->offset, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); } @@ -533,6 +513,11 @@ prepare_wm_surfaces(struct brw_context *brw) struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct intel_region *region = irb ? irb->region : NULL; + if (region == NULL || region->buffer == NULL) { + brw->intel.Fallback = GL_TRUE; /* boolean, not bitfield */ + return; + } + brw_add_validated_bo(brw, region->buffer); nr_surfaces = SURF_INDEX_DRAW(i) + 1; } @@ -598,8 +583,7 @@ upload_wm_surfaces(struct brw_context *brw) if (texUnit->_ReallyEnabled) { brw_update_texture_surface(ctx, i); } else { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; + brw->wm.surf_offset[surf] = 0; } } @@ -632,16 +616,11 @@ brw_wm_upload_binding_table(struct brw_context *brw) * space for the binding table. */ bind = brw_state_batch(brw, sizeof(uint32_t) * BRW_WM_MAX_SURF, - 32, &brw->wm.bind_bo, &brw->wm.bind_bo_offset); + 32, &brw->wm.bind_bo_offset); for (i = 0; i < BRW_WM_MAX_SURF; i++) { /* BRW_NEW_WM_SURFACES */ bind[i] = brw->wm.surf_offset[i]; - if (brw->wm.surf_bo[i]) { - bind[i] = brw->wm.surf_offset[i]; - } else { - bind[i] = 0; - } } brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE; diff --git a/src/mesa/drivers/dri/i965/gen6_cc.c b/src/mesa/drivers/dri/i965/gen6_cc.c index f51afa40716..d1648a102d4 100644 --- a/src/mesa/drivers/dri/i965/gen6_cc.c +++ b/src/mesa/drivers/dri/i965/gen6_cc.c @@ -254,14 +254,14 @@ prepare_color_calc_state(struct brw_context *brw) color_calc_state_populate_key(brw, &key); - drm_intel_bo_unreference(brw->cc.state_bo); - brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_COLOR_CALC_STATE, + drm_intel_bo_unreference(brw->cc.color_calc_state_bo); + brw->cc.color_calc_state_bo = brw_search_cache(&brw->cache, BRW_COLOR_CALC_STATE, &key, sizeof(key), NULL, 0, NULL); - if (brw->cc.state_bo == NULL) - brw->cc.state_bo = color_calc_state_create_from_key(brw, &key); + if (brw->cc.color_calc_state_bo == NULL) + brw->cc.color_calc_state_bo = color_calc_state_create_from_key(brw, &key); } const struct brw_tracked_state gen6_color_calc_state = { @@ -281,14 +281,14 @@ static void upload_cc_state_pointers(struct brw_context *brw) OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); OUT_RELOC(brw->cc.blend_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); OUT_RELOC(brw->cc.depth_stencil_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); - OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); + OUT_RELOC(brw->cc.color_calc_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1); ADVANCE_BATCH(); } static void prepare_cc_state_pointers(struct brw_context *brw) { - brw_add_validated_bo(brw, brw->cc.state_bo); + brw_add_validated_bo(brw, brw->cc.color_calc_state_bo); brw_add_validated_bo(brw, brw->cc.blend_state_bo); brw_add_validated_bo(brw, brw->cc.depth_stencil_state_bo); } diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c index f27782935d4..50a5ad38c6f 100644 --- a/src/mesa/drivers/dri/i965/gen6_sf_state.c +++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c @@ -54,6 +54,8 @@ get_attr_override(struct brw_context *brw, int fs_attr, int two_side_color) * be FRAG_ATTRIB_*. */ for (i = 1; i < vs_attr; i++) { + if (i == VERT_RESULT_PSIZ) + continue; if (brw->vs.prog_data->outputs_written & BITFIELD64_BIT(i)) attr_index++; } @@ -207,7 +209,7 @@ upload_sf_state(struct brw_context *brw) ctx->Point._Attenuated)) dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; - dw4 |= U_FIXED(CLAMP(ctx->Point.Size, 0.125, 225.875), 3) << + dw4 |= U_FIXED(CLAMP(ctx->Point.Size, 0.125, 255.875), 3) << GEN6_SF_POINT_WIDTH_SHIFT; if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) dw1 |= GEN6_SF_POINT_SPRITE_LOWERLEFT; diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c index 67ce8a4da02..42b4f923e0c 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c @@ -27,89 +27,89 @@ #include "intel_context.h" #include "intel_batchbuffer.h" +#include "intel_buffer_objects.h" #include "intel_decode.h" #include "intel_reg.h" #include "intel_bufmgr.h" #include "intel_buffers.h" -void -intel_batchbuffer_reset(struct intel_batchbuffer *batch) +struct cached_batch_item { + struct cached_batch_item *next; + uint16_t header; + uint16_t size; +}; + +static void clear_cache( struct intel_context *intel ) { - struct intel_context *intel = batch->intel; + struct cached_batch_item *item = intel->batch.cached_items; - if (batch->buf != NULL) { - drm_intel_bo_unreference(batch->buf); - batch->buf = NULL; + while (item) { + struct cached_batch_item *next = item->next; + free(item); + item = next; } - batch->buf = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer", - intel->maxBatchSize, 4096); - drm_intel_gem_bo_map_gtt(batch->buf); - batch->map = batch->buf->virtual; - - batch->size = intel->maxBatchSize; - batch->ptr = batch->map; - batch->reserved_space = BATCH_RESERVED; - batch->dirty_state = ~0; - batch->state_batch_offset = batch->size; + intel->batch.cached_items = NULL; } -struct intel_batchbuffer * -intel_batchbuffer_alloc(struct intel_context *intel) +void +intel_batchbuffer_reset(struct intel_context *intel) { - struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1); + if (intel->batch.bo != NULL) { + drm_intel_bo_unreference(intel->batch.bo); + intel->batch.bo = NULL; + } + clear_cache(intel); - batch->intel = intel; - intel_batchbuffer_reset(batch); + intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer", + intel->maxBatchSize, 4096); - return batch; + intel->batch.reserved_space = BATCH_RESERVED; + intel->batch.state_batch_offset = intel->batch.bo->size; + intel->batch.used = 0; } void -intel_batchbuffer_free(struct intel_batchbuffer *batch) +intel_batchbuffer_free(struct intel_context *intel) { - if (batch->map) { - drm_intel_gem_bo_unmap_gtt(batch->buf); - batch->map = NULL; - } - dri_bo_unreference(batch->buf); - batch->buf = NULL; - free(batch); + drm_intel_bo_unreference(intel->batch.bo); + clear_cache(intel); } - /* TODO: Push this whole function into bufmgr. */ static void -do_flush_locked(struct intel_batchbuffer *batch, GLuint used) +do_flush_locked(struct intel_context *intel) { - struct intel_context *intel = batch->intel; + struct intel_batchbuffer *batch = &intel->batch; int ret = 0; - int x_off = 0, y_off = 0; - - drm_intel_gem_bo_unmap_gtt(batch->buf); - - batch->ptr = NULL; if (!intel->intelScreen->no_hw) { int ring; - if (intel->gen < 6 || !intel->batch->is_blit) { + if (intel->gen < 6 || !batch->is_blit) { ring = I915_EXEC_RENDER; } else { ring = I915_EXEC_BLT; } - drm_intel_bo_mrb_exec(batch->buf, used, NULL, 0, - (x_off & 0xffff) | (y_off << 16), ring); + ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map); + if (ret == 0 && batch->state_batch_offset != batch->bo->size) { + ret = drm_intel_bo_subdata(batch->bo, + batch->state_batch_offset, + batch->bo->size - batch->state_batch_offset, + (char *)batch->map + batch->state_batch_offset); + } + + if (ret == 0) + ret = drm_intel_bo_mrb_exec(batch->bo, 4*batch->used, NULL, 0, 0, ring); } if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) { - drm_intel_bo_map(batch->buf, GL_FALSE); - intel_decode(batch->buf->virtual, used / 4, batch->buf->offset, + intel_decode(batch->map, batch->used, + batch->bo->offset, intel->intelScreen->deviceID, GL_TRUE); - drm_intel_bo_unmap(batch->buf); if (intel->vtbl.debug_batch != NULL) intel->vtbl.debug_batch(intel); @@ -122,80 +122,54 @@ do_flush_locked(struct intel_batchbuffer *batch, GLuint used) } void -_intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file, - int line) +_intel_batchbuffer_flush(struct intel_context *intel, + const char *file, int line) { - struct intel_context *intel = batch->intel; - GLuint used = batch->ptr - batch->map; - - if (intel->first_post_swapbuffers_batch == NULL) { - intel->first_post_swapbuffers_batch = intel->batch->buf; - drm_intel_bo_reference(intel->first_post_swapbuffers_batch); - } - - if (used == 0) + if (intel->batch.used == 0) return; if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line, - used); + 4*intel->batch.used); - batch->reserved_space = 0; + intel->batch.reserved_space = 0; if (intel->always_flush_cache) { - intel_batchbuffer_emit_mi_flush(batch); - used = batch->ptr - batch->map; - } - - /* Round batchbuffer usage to 2 DWORDs. */ - - if ((used & 4) == 0) { - *(GLuint *) (batch->ptr) = 0; /* noop */ - batch->ptr += 4; - used = batch->ptr - batch->map; + intel_batchbuffer_emit_mi_flush(intel); } /* Mark the end of the buffer. */ - *(GLuint *) (batch->ptr) = MI_BATCH_BUFFER_END; - batch->ptr += 4; - used = batch->ptr - batch->map; - assert (used <= batch->buf->size); - - /* Workaround for recursive batchbuffer flushing: If the window is - * moved, we can get into a case where we try to flush during a - * flush. What happens is that when we try to grab the lock for - * the first flush, we detect that the window moved which then - * causes another flush (from the intel_draw_buffer() call in - * intelUpdatePageFlipping()). To work around this we reset the - * batchbuffer tail pointer before trying to get the lock. This - * prevent the nested buffer flush, but a better fix would be to - * avoid that in the first place. */ - batch->ptr = batch->map; + intel_batchbuffer_emit_dword(intel, MI_BATCH_BUFFER_END); + if (intel->batch.used & 1) { + /* Round batchbuffer usage to 2 DWORDs. */ + intel_batchbuffer_emit_dword(intel, MI_NOOP); + } if (intel->vtbl.finish_batch) intel->vtbl.finish_batch(intel); + intel_upload_finish(intel); + /* Check that we didn't just wrap our batchbuffer at a bad time. */ assert(!intel->no_batch_wrap); - do_flush_locked(batch, used); + do_flush_locked(intel); if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) { fprintf(stderr, "waiting for idle\n"); - drm_intel_bo_map(batch->buf, GL_TRUE); - drm_intel_bo_unmap(batch->buf); + drm_intel_bo_wait_rendering(intel->batch.bo); } /* Reset the buffer: */ - intel_batchbuffer_reset(batch); + intel_batchbuffer_reset(intel); } /* This is the only way buffers get added to the validate list. */ GLboolean -intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, +intel_batchbuffer_emit_reloc(struct intel_context *intel, drm_intel_bo *buffer, uint32_t read_domains, uint32_t write_domain, uint32_t delta) @@ -204,58 +178,98 @@ intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, assert(delta < buffer->size); - if (batch->ptr - batch->map > batch->buf->size) - printf ("bad relocation ptr %p map %p offset %d size %lu\n", - batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size); - ret = drm_intel_bo_emit_reloc(batch->buf, batch->ptr - batch->map, + ret = drm_intel_bo_emit_reloc(intel->batch.bo, 4*intel->batch.used, buffer, delta, read_domains, write_domain); + assert(ret == 0); + (void)ret; /* * Using the old buffer offset, write in what the right data would be, in case * the buffer doesn't move and we can short-circuit the relocation processing * in the kernel */ - intel_batchbuffer_emit_dword (batch, buffer->offset + delta); + intel_batchbuffer_emit_dword(intel, buffer->offset + delta); return GL_TRUE; } GLboolean -intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch, +intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel, drm_intel_bo *buffer, - uint32_t read_domains, uint32_t write_domain, + uint32_t read_domains, + uint32_t write_domain, uint32_t delta) { int ret; assert(delta < buffer->size); - if (batch->ptr - batch->map > batch->buf->size) - printf ("bad relocation ptr %p map %p offset %d size %lu\n", - batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size); - ret = drm_intel_bo_emit_reloc_fence(batch->buf, batch->ptr - batch->map, + ret = drm_intel_bo_emit_reloc_fence(intel->batch.bo, 4*intel->batch.used, buffer, delta, read_domains, write_domain); + assert(ret == 0); + (void)ret; /* * Using the old buffer offset, write in what the right data would * be, in case the buffer doesn't move and we can short-circuit the * relocation processing in the kernel */ - intel_batchbuffer_emit_dword (batch, buffer->offset + delta); + intel_batchbuffer_emit_dword(intel, buffer->offset + delta); return GL_TRUE; } void -intel_batchbuffer_data(struct intel_batchbuffer *batch, +intel_batchbuffer_data(struct intel_context *intel, const void *data, GLuint bytes, bool is_blit) { assert((bytes & 3) == 0); - intel_batchbuffer_require_space(batch, bytes, is_blit); - __memcpy(batch->ptr, data, bytes); - batch->ptr += bytes; + intel_batchbuffer_require_space(intel, bytes, is_blit); + __memcpy(intel->batch.map + intel->batch.used, data, bytes); + intel->batch.used += bytes >> 2; +} + +void +intel_batchbuffer_cached_advance(struct intel_context *intel) +{ + struct cached_batch_item **prev = &intel->batch.cached_items, *item; + uint32_t sz = (intel->batch.used - intel->batch.emit) * sizeof(uint32_t); + uint32_t *start = intel->batch.map + intel->batch.emit; + uint16_t op = *start >> 16; + + while (*prev) { + uint32_t *old; + + item = *prev; + old = intel->batch.map + item->header; + if (op == *old >> 16) { + if (item->size == sz && memcmp(old, start, sz) == 0) { + if (prev != &intel->batch.cached_items) { + *prev = item->next; + item->next = intel->batch.cached_items; + intel->batch.cached_items = item; + } + intel->batch.used = intel->batch.emit; + return; + } + + goto emit; + } + prev = &item->next; + } + + item = malloc(sizeof(struct cached_batch_item)); + if (item == NULL) + return; + + item->next = intel->batch.cached_items; + intel->batch.cached_items = item; + +emit: + item->size = sz; + item->header = intel->batch.emit; } /* Emit a pipelined flush to either flush render and texture cache for @@ -265,12 +279,10 @@ intel_batchbuffer_data(struct intel_batchbuffer *batch, * This is also used for the always_flush_cache driconf debug option. */ void -intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch) +intel_batchbuffer_emit_mi_flush(struct intel_context *intel) { - struct intel_context *intel = batch->intel; - if (intel->gen >= 6) { - if (intel->batch->is_blit) { + if (intel->batch.is_blit) { BEGIN_BATCH_BLT(4); OUT_BATCH(MI_FLUSH_DW); OUT_BATCH(0); diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.h b/src/mesa/drivers/dri/intel/intel_batchbuffer.h index 635708587a6..a0a5c9841c6 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.h @@ -7,71 +7,37 @@ #include "intel_bufmgr.h" #include "intel_reg.h" -#define BATCH_SZ 16384 #define BATCH_RESERVED 16 +void intel_batchbuffer_reset(struct intel_context *intel); +void intel_batchbuffer_free(struct intel_context *intel); -struct intel_batchbuffer -{ - struct intel_context *intel; - - drm_intel_bo *buf; - - GLubyte *map; - GLubyte *ptr; - - GLuint size; - uint32_t state_batch_offset; - -#ifdef DEBUG - /** Tracking of BEGIN_BATCH()/OUT_BATCH()/ADVANCE_BATCH() debugging */ - struct { - GLuint total; - GLubyte *start_ptr; - } emit; -#endif - - bool is_blit; - GLuint dirty_state; - GLuint reserved_space; -}; - -struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context - *intel); - -void intel_batchbuffer_free(struct intel_batchbuffer *batch); - - -void _intel_batchbuffer_flush(struct intel_batchbuffer *batch, +void _intel_batchbuffer_flush(struct intel_context *intel, const char *file, int line); -#define intel_batchbuffer_flush(batch) \ - _intel_batchbuffer_flush(batch, __FILE__, __LINE__) +#define intel_batchbuffer_flush(intel) \ + _intel_batchbuffer_flush(intel, __FILE__, __LINE__) -void intel_batchbuffer_reset(struct intel_batchbuffer *batch); /* Unlike bmBufferData, this currently requires the buffer be mapped. * Consider it a convenience function wrapping multple * intel_buffer_dword() calls. */ -void intel_batchbuffer_data(struct intel_batchbuffer *batch, +void intel_batchbuffer_data(struct intel_context *intel, const void *data, GLuint bytes, bool is_blit); -void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, - GLuint bytes); - -GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, +GLboolean intel_batchbuffer_emit_reloc(struct intel_context *intel, drm_intel_bo *buffer, uint32_t read_domains, uint32_t write_domain, uint32_t offset); -GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch, +GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel, drm_intel_bo *buffer, uint32_t read_domains, uint32_t write_domain, uint32_t offset); -void intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch); +void intel_batchbuffer_emit_mi_flush(struct intel_context *intel); static INLINE uint32_t float_as_int(float f) { @@ -90,93 +56,93 @@ static INLINE uint32_t float_as_int(float f) * work... */ static INLINE GLint -intel_batchbuffer_space(struct intel_batchbuffer *batch) +intel_batchbuffer_space(struct intel_context *intel) { - return (batch->state_batch_offset - batch->reserved_space) - - (batch->ptr - batch->map); + return (intel->batch.state_batch_offset - intel->batch.reserved_space) - intel->batch.used*4; } static INLINE void -intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword) +intel_batchbuffer_emit_dword(struct intel_context *intel, GLuint dword) { #ifdef DEBUG - assert(intel_batchbuffer_space(batch) >= 4); + assert(intel_batchbuffer_space(intel) >= 4); #endif - *(GLuint *) (batch->ptr) = dword; - batch->ptr += 4; + intel->batch.map[intel->batch.used++] = dword; } static INLINE void -intel_batchbuffer_emit_float(struct intel_batchbuffer *batch, float f) +intel_batchbuffer_emit_float(struct intel_context *intel, float f) { - intel_batchbuffer_emit_dword(batch, float_as_int(f)); + intel_batchbuffer_emit_dword(intel, float_as_int(f)); } static INLINE void -intel_batchbuffer_require_space(struct intel_batchbuffer *batch, +intel_batchbuffer_require_space(struct intel_context *intel, GLuint sz, int is_blit) { - if (batch->intel->gen >= 6 && batch->is_blit != is_blit && - batch->ptr != batch->map) { - intel_batchbuffer_flush(batch); + if (intel->gen >= 6 && + intel->batch.is_blit != is_blit && intel->batch.used) { + intel_batchbuffer_flush(intel); } - batch->is_blit = is_blit; + intel->batch.is_blit = is_blit; #ifdef DEBUG - assert(sz < batch->size - 8); + assert(sz < sizeof(intel->batch.map) - BATCH_RESERVED); #endif - if (intel_batchbuffer_space(batch) < sz) - intel_batchbuffer_flush(batch); + if (intel_batchbuffer_space(intel) < sz) + intel_batchbuffer_flush(intel); } static INLINE void -intel_batchbuffer_begin(struct intel_batchbuffer *batch, int n, bool is_blit) +intel_batchbuffer_begin(struct intel_context *intel, int n, bool is_blit) { - intel_batchbuffer_require_space(batch, n * 4, is_blit); + intel_batchbuffer_require_space(intel, n * 4, is_blit); + intel->batch.emit = intel->batch.used; #ifdef DEBUG - assert(batch->map); - assert(batch->emit.start_ptr == NULL); - batch->emit.total = n * 4; - batch->emit.start_ptr = batch->ptr; + intel->batch.total = n; #endif } static INLINE void -intel_batchbuffer_advance(struct intel_batchbuffer *batch) +intel_batchbuffer_advance(struct intel_context *intel) { #ifdef DEBUG - unsigned int _n = batch->ptr - batch->emit.start_ptr; - assert(batch->emit.start_ptr != NULL); - if (_n != batch->emit.total) { + struct intel_batchbuffer *batch = &intel->batch; + unsigned int _n = batch->used - batch->emit; + assert(batch->total != 0); + if (_n != batch->total) { fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n", - _n, batch->emit.total); + _n, batch->total); abort(); } - batch->emit.start_ptr = NULL; + batch->total = 0; #endif } +void intel_batchbuffer_cached_advance(struct intel_context *intel); + /* Here are the crusty old macros, to be removed: */ #define BATCH_LOCALS -#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel->batch, n, false) -#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel->batch, n, true) -#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d) -#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel->batch,f) +#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel, n, false) +#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel, n, true) +#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel, d) +#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel,f) #define OUT_RELOC(buf, read_domains, write_domain, delta) do { \ - intel_batchbuffer_emit_reloc(intel->batch, buf, \ + intel_batchbuffer_emit_reloc(intel, buf, \ read_domains, write_domain, delta); \ } while (0) #define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do { \ - intel_batchbuffer_emit_reloc_fenced(intel->batch, buf, \ + intel_batchbuffer_emit_reloc_fenced(intel, buf, \ read_domains, write_domain, delta); \ } while (0) -#define ADVANCE_BATCH() intel_batchbuffer_advance(intel->batch); +#define ADVANCE_BATCH() intel_batchbuffer_advance(intel); +#define CACHED_BATCH() intel_batchbuffer_cached_advance(intel); #endif diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 6232e479cb6..e1ab7f16371 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -123,12 +123,12 @@ intelEmitCopyBlit(struct intel_context *intel, /* do space check before going any further */ do { - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = dst_buffer; aper_array[2] = src_buffer; if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); pass++; } else break; @@ -137,7 +137,7 @@ intelEmitCopyBlit(struct intel_context *intel, if (pass >= 2) return GL_FALSE; - intel_batchbuffer_require_space(intel->batch, 8 * 4, true); + intel_batchbuffer_require_space(intel, 8 * 4, true); DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", __FUNCTION__, src_buffer, src_pitch, src_offset, src_x, src_y, @@ -193,7 +193,7 @@ intelEmitCopyBlit(struct intel_context *intel, src_offset); ADVANCE_BATCH(); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); return GL_TRUE; } @@ -343,12 +343,12 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) assert(y1 < y2); /* do space check before going any further */ - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = write_buffer; if (drm_intel_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array)) != 0) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); } BEGIN_BATCH_BLT(6); @@ -363,7 +363,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) ADVANCE_BATCH(); if (intel->always_flush_cache) - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); @@ -410,10 +410,10 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords); - intel_batchbuffer_require_space( intel->batch, - (8 * 4) + - (3 * 4) + - dwords * 4, true); + intel_batchbuffer_require_space(intel, + (8 * 4) + + (3 * 4) + + dwords * 4, true); opcode = XY_SETUP_BLT_CMD; if (cpp == 4) @@ -449,11 +449,9 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, OUT_BATCH(((y + h) << 16) | (x + w)); ADVANCE_BATCH(); - intel_batchbuffer_data(intel->batch, - src_bits, - dwords * 4, true); + intel_batchbuffer_data(intel, src_bits, dwords * 4, true); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); return GL_TRUE; } @@ -543,10 +541,10 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx, DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", __FUNCTION__, - intel_image->mt->region->buffer, (pitch * region->cpp), + intel_image->mt->region->buffer, (pitch * cpp), x1, y1, x2 - x1, y2 - y1); - BR13 = br13_for_cpp(region->cpp) | 0xf0 << 16; + BR13 = br13_for_cpp(cpp) | 0xf0 << 16; CMD = XY_COLOR_BLT_CMD; CMD |= XY_BLT_WRITE_ALPHA; @@ -558,15 +556,15 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx, pitch /= 4; } #endif - BR13 |= (pitch * region->cpp); + BR13 |= (pitch * cpp); /* do space check before going any further */ - aper_array[0] = intel->batch->buf; + aper_array[0] = intel->batch.bo; aper_array[1] = region->buffer; if (drm_intel_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array)) != 0) { - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); } BEGIN_BATCH_BLT(6); @@ -580,5 +578,5 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx, OUT_BATCH(0xffffffff); /* white, but only alpha gets written */ ADVANCE_BATCH(); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c index d917161c4be..2f750a768af 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c @@ -53,6 +53,15 @@ intel_bufferobj_alloc_buffer(struct intel_context *intel, intel_obj->Base.Size, 64); } +static void +release_buffer(struct intel_buffer_object *intel_obj) +{ + drm_intel_bo_unreference(intel_obj->buffer); + intel_obj->buffer = NULL; + intel_obj->offset = 0; + intel_obj->source = 0; +} + /** * There is some duplication between mesa's bufferobjects and our * bufmgr buffers. Both have an integer handle and a hashtable to @@ -81,8 +90,7 @@ intel_bufferobj_release_region(struct intel_context *intel, intel_obj->region->pbo = NULL; intel_obj->region = NULL; - drm_intel_bo_unreference(intel_obj->buffer); - intel_obj->buffer = NULL; + release_buffer(intel_obj); } /* Break the COW tie to the region. Both the pbo and the region end @@ -120,10 +128,8 @@ intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj) if (intel_obj->region) { intel_bufferobj_release_region(intel, intel_obj); } - else if (intel_obj->buffer) { - drm_intel_bo_unreference(intel_obj->buffer); - } + drm_intel_bo_unreference(intel_obj->buffer); free(intel_obj); } @@ -154,19 +160,22 @@ intel_bufferobj_data(struct gl_context * ctx, if (intel_obj->region) intel_bufferobj_release_region(intel, intel_obj); - if (intel_obj->buffer != NULL) { - drm_intel_bo_unreference(intel_obj->buffer); - intel_obj->buffer = NULL; - } + if (intel_obj->buffer != NULL) + release_buffer(intel_obj); + free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; if (size != 0) { + if (usage == GL_DYNAMIC_DRAW #ifdef I915 - /* On pre-965, stick VBOs in system memory, as we're always doing swtnl - * with their contents anyway. - */ - if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) { + /* On pre-965, stick VBOs in system memory, as we're always doing + * swtnl with their contents anyway. + */ + || target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER +#endif + ) + { intel_obj->sys_buffer = malloc(size); if (intel_obj->sys_buffer != NULL) { if (data != NULL) @@ -174,7 +183,6 @@ intel_bufferobj_data(struct gl_context * ctx, return GL_TRUE; } } -#endif intel_bufferobj_alloc_buffer(intel, intel_obj); if (!intel_obj->buffer) return GL_FALSE; @@ -202,6 +210,7 @@ intel_bufferobj_subdata(struct gl_context * ctx, { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); + bool busy; if (size == 0) return; @@ -211,34 +220,53 @@ intel_bufferobj_subdata(struct gl_context * ctx, if (intel_obj->region) intel_bufferobj_cow(intel, intel_obj); - if (intel_obj->sys_buffer) - memcpy((char *)intel_obj->sys_buffer + offset, data, size); - else { - /* Flush any existing batchbuffer that might reference this data. */ - if (intel->gen < 6) { - if (drm_intel_bo_busy(intel_obj->buffer) || - drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) { - drm_intel_bo *temp_bo; + /* If we have a single copy in system memory, update that */ + if (intel_obj->sys_buffer) { + if (intel_obj->source) + release_buffer(intel_obj); - temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64); + if (intel_obj->buffer == NULL) { + memcpy((char *)intel_obj->sys_buffer + offset, data, size); + return; + } - drm_intel_bo_subdata(temp_bo, 0, size, data); + free(intel_obj->sys_buffer); + intel_obj->sys_buffer = NULL; + } - intel_emit_linear_blit(intel, - intel_obj->buffer, offset, - temp_bo, 0, - size); + /* Otherwise we need to update the copy in video memory. */ + busy = + drm_intel_bo_busy(intel_obj->buffer) || + drm_intel_bo_references(intel->batch.bo, intel_obj->buffer); - drm_intel_bo_unreference(temp_bo); - } else { - drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); - } + /* replace the current busy bo with fresh data */ + if (busy && size == intel_obj->Base.Size) { + drm_intel_bo_unreference(intel_obj->buffer); + intel_bufferobj_alloc_buffer(intel, intel_obj); + drm_intel_bo_subdata(intel_obj->buffer, 0, size, data); + } else if (intel->gen < 6) { + if (busy) { + drm_intel_bo *temp_bo; + + temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64); + + drm_intel_bo_subdata(temp_bo, 0, size, data); + + intel_emit_linear_blit(intel, + intel_obj->buffer, offset, + temp_bo, 0, + size); + + drm_intel_bo_unreference(temp_bo); } else { - if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) { - intel_batchbuffer_flush(intel->batch); - } drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); } + } else { + /* Can't use the blit to modify the buffer in the middle of batch. */ + if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) { + intel_batchbuffer_flush(intel); + } + drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); } } @@ -280,14 +308,23 @@ intel_bufferobj_map(struct gl_context * ctx, assert(intel_obj); if (intel_obj->sys_buffer) { - obj->Pointer = intel_obj->sys_buffer; - obj->Length = obj->Size; - obj->Offset = 0; - return obj->Pointer; + if (!read_only && intel_obj->source) { + release_buffer(intel_obj); + } + + if (!intel_obj->buffer || intel_obj->source) { + obj->Pointer = intel_obj->sys_buffer; + obj->Length = obj->Size; + obj->Offset = 0; + return obj->Pointer; + } + + free(intel_obj->sys_buffer); + intel_obj->sys_buffer = NULL; } /* Flush any existing batchbuffer that might reference this data. */ - if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) + if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) intel_flush(ctx); if (intel_obj->region) @@ -336,6 +373,7 @@ intel_bufferobj_map_range(struct gl_context * ctx, { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); + GLboolean read_only = (access == GL_READ_ONLY_ARB); assert(intel_obj); @@ -347,8 +385,16 @@ intel_bufferobj_map_range(struct gl_context * ctx, obj->AccessFlags = access; if (intel_obj->sys_buffer) { - obj->Pointer = intel_obj->sys_buffer + offset; - return obj->Pointer; + if (!read_only && intel_obj->source) + release_buffer(intel_obj); + + if (!intel_obj->buffer || intel_obj->source) { + obj->Pointer = intel_obj->sys_buffer + offset; + return obj->Pointer; + } + + free(intel_obj->sys_buffer); + intel_obj->sys_buffer = NULL; } if (intel_obj->region) @@ -359,7 +405,7 @@ intel_bufferobj_map_range(struct gl_context * ctx, * syncing. */ if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) && - drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) + drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) intel_flush(ctx); if (intel_obj->buffer == NULL) { @@ -374,8 +420,7 @@ intel_bufferobj_map_range(struct gl_context * ctx, (access & GL_MAP_INVALIDATE_BUFFER_BIT) && drm_intel_bo_busy(intel_obj->buffer)) { drm_intel_bo_unreference(intel_obj->buffer); - intel_obj->buffer = drm_intel_bo_alloc(intel->bufmgr, "bufferobj", - intel_obj->Base.Size, 64); + intel_bufferobj_alloc_buffer(intel, intel_obj); } /* If the user is mapping a range of an active buffer object but @@ -473,7 +518,7 @@ intel_bufferobj_unmap(struct gl_context * ctx, * flush. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); free(intel_obj->range_map_buffer); intel_obj->range_map_buffer = NULL; } else if (intel_obj->range_map_bo != NULL) { @@ -493,7 +538,7 @@ intel_bufferobj_unmap(struct gl_context * ctx, * flush. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); drm_intel_bo_unreference(intel_obj->range_map_bo); intel_obj->range_map_bo = NULL; @@ -513,7 +558,8 @@ intel_bufferobj_unmap(struct gl_context * ctx, drm_intel_bo * intel_bufferobj_buffer(struct intel_context *intel, - struct intel_buffer_object *intel_obj, GLuint flag) + struct intel_buffer_object *intel_obj, + GLuint flag) { if (intel_obj->region) { if (flag == INTEL_WRITE_PART) @@ -524,23 +570,169 @@ intel_bufferobj_buffer(struct intel_context *intel, } } - if (intel_obj->buffer == NULL) { - void *sys_buffer = intel_obj->sys_buffer; + if (intel_obj->source) + release_buffer(intel_obj); - /* only one of buffer and sys_buffer could be non-NULL */ + if (intel_obj->buffer == NULL) { intel_bufferobj_alloc_buffer(intel, intel_obj); - intel_obj->sys_buffer = NULL; + drm_intel_bo_subdata(intel_obj->buffer, + 0, intel_obj->Base.Size, + intel_obj->sys_buffer); - intel_bufferobj_subdata(&intel->ctx, - GL_ARRAY_BUFFER_ARB, - 0, - intel_obj->Base.Size, - sys_buffer, - &intel_obj->Base); - free(sys_buffer); + free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; + intel_obj->offset = 0; + } + + return intel_obj->buffer; +} + +#define INTEL_UPLOAD_SIZE (64*1024) + +void +intel_upload_finish(struct intel_context *intel) +{ + if (!intel->upload.bo) + return; + + if (intel->upload.buffer_len) { + drm_intel_bo_subdata(intel->upload.bo, + intel->upload.buffer_offset, + intel->upload.buffer_len, + intel->upload.buffer); + intel->upload.buffer_len = 0; + } + + drm_intel_bo_unreference(intel->upload.bo); + intel->upload.bo = NULL; +} + +static void wrap_buffers(struct intel_context *intel, GLuint size) +{ + intel_upload_finish(intel); + + if (size < INTEL_UPLOAD_SIZE) + size = INTEL_UPLOAD_SIZE; + + intel->upload.bo = drm_intel_bo_alloc(intel->bufmgr, "upload", size, 0); + intel->upload.offset = 0; +} + +void intel_upload_data(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset) +{ + GLuint base, delta; + + base = (intel->upload.offset + align - 1) / align * align; + if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) { + wrap_buffers(intel, size); + base = 0; + } + + drm_intel_bo_reference(intel->upload.bo); + *return_bo = intel->upload.bo; + *return_offset = base; + + delta = base - intel->upload.offset; + if (intel->upload.buffer_len && + intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer)) + { + drm_intel_bo_subdata(intel->upload.bo, + intel->upload.buffer_offset, + intel->upload.buffer_len, + intel->upload.buffer); + intel->upload.buffer_len = 0; + } + + if (size < sizeof(intel->upload.buffer)) + { + if (intel->upload.buffer_len == 0) + intel->upload.buffer_offset = base; + else + intel->upload.buffer_len += delta; + + memcpy(intel->upload.buffer + intel->upload.buffer_len, ptr, size); + intel->upload.buffer_len += size; + } + else + { + drm_intel_bo_subdata(intel->upload.bo, base, size, ptr); + } + + intel->upload.offset = base + size; +} + +void *intel_upload_map(struct intel_context *intel, GLuint size, GLuint align) +{ + GLuint base, delta; + char *ptr; + + base = (intel->upload.offset + align - 1) / align * align; + if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) { + wrap_buffers(intel, size); + base = 0; + } + + delta = base - intel->upload.offset; + if (intel->upload.buffer_len && + intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer)) + { + drm_intel_bo_subdata(intel->upload.bo, + intel->upload.buffer_offset, + intel->upload.buffer_len, + intel->upload.buffer); + intel->upload.buffer_len = 0; + } + + if (size <= sizeof(intel->upload.buffer)) { + if (intel->upload.buffer_len == 0) + intel->upload.buffer_offset = base; + else + intel->upload.buffer_len += delta; + + ptr = intel->upload.buffer + intel->upload.buffer_len; + intel->upload.buffer_len += size; + } else + ptr = malloc(size); + + return ptr; +} + +void intel_upload_unmap(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset) +{ + GLuint base; + + base = (intel->upload.offset + align - 1) / align * align; + if (size > sizeof(intel->upload.buffer)) { + drm_intel_bo_subdata(intel->upload.bo, base, size, ptr); + free((void*)ptr); + } + + drm_intel_bo_reference(intel->upload.bo); + *return_bo = intel->upload.bo; + *return_offset = base; + + intel->upload.offset = base + size; +} + +drm_intel_bo * +intel_bufferobj_source(struct intel_context *intel, + struct intel_buffer_object *intel_obj, + GLuint *offset) +{ + if (intel_obj->buffer == NULL) { + intel_upload_data(intel, + intel_obj->sys_buffer, intel_obj->Base.Size, 64, + &intel_obj->buffer, &intel_obj->offset); + intel_obj->source = 1; } + *offset = intel_obj->offset; return intel_obj->buffer; } @@ -555,6 +747,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx, struct intel_buffer_object *intel_src = intel_buffer_object(src); struct intel_buffer_object *intel_dst = intel_buffer_object(dst); drm_intel_bo *src_bo, *dst_bo; + GLuint src_offset; if (size == 0) return; @@ -567,7 +760,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx, if (src == dst) { char *ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER, GL_READ_WRITE, dst); - memcpy(ptr + write_offset, ptr + read_offset, size); + memmove(ptr + write_offset, ptr + read_offset, size); intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst); } else { const char *src_ptr; @@ -589,18 +782,18 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx, /* Otherwise, we have real BOs, so blit them. */ dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART); - src_bo = intel_bufferobj_buffer(intel, intel_src, INTEL_READ); + src_bo = intel_bufferobj_source(intel, intel_src, &src_offset); intel_emit_linear_blit(intel, dst_bo, write_offset, - src_bo, read_offset, size); + src_bo, read_offset + src_offset, size); /* Since we've emitted some blits to buffers that will (likely) be used * in rendering operations in other cache domains in this batch, emit a * flush. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } #if FEATURE_APPLE_object_purgeable diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.h b/src/mesa/drivers/dri/intel/intel_buffer_objects.h index b15c1921061..3ec3a521382 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.h +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.h @@ -42,6 +42,8 @@ struct intel_buffer_object { struct gl_buffer_object Base; drm_intel_bo *buffer; /* the low-level buffer manager's buffer handle */ + GLuint offset; /* any offset into that buffer */ + /** System memory buffer data, if not using a BO to store the data. */ void *sys_buffer; @@ -55,6 +57,7 @@ struct intel_buffer_object GLsizei range_map_size; GLboolean mapped_gtt; + GLboolean source; }; @@ -63,8 +66,25 @@ struct intel_buffer_object drm_intel_bo *intel_bufferobj_buffer(struct intel_context *intel, struct intel_buffer_object *obj, GLuint flag); +drm_intel_bo *intel_bufferobj_source(struct intel_context *intel, + struct intel_buffer_object *obj, + GLuint *offset); + +void intel_upload_data(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset); + +void *intel_upload_map(struct intel_context *intel, + GLuint size, GLuint align); +void intel_upload_unmap(struct intel_context *intel, + const void *ptr, GLuint size, GLuint align, + drm_intel_bo **return_bo, + GLuint *return_offset); + +void intel_upload_finish(struct intel_context *intel); -/* Hook the bufferobject implementation into mesa: +/* Hook the bufferobject implementation into mesa: */ void intelInitBufferObjectFuncs(struct dd_function_table *functions); diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 2a5029964be..c2e2a98af5e 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -470,11 +470,9 @@ intel_prepare_render(struct intel_context *intel) * the swap, and getting our hands on that doesn't seem worth it, * so we just us the first batch we emitted after the last swap. */ - if (intel->need_throttle && intel->first_post_swapbuffers_batch) { - drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); - drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); - intel->first_post_swapbuffers_batch = NULL; - intel->need_throttle = GL_FALSE; + if (intel->need_throttle) { + drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE); + intel->need_throttle = GL_FALSE; } } @@ -487,7 +485,7 @@ intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) if (intel->saved_viewport) intel->saved_viewport(ctx, x, y, w, h); - if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { + if (ctx->DrawBuffer->Name == 0) { dri2InvalidateDrawable(driContext->driDrawablePriv); dri2InvalidateDrawable(driContext->driReadablePriv); } @@ -554,8 +552,8 @@ intel_flush(struct gl_context *ctx) if (intel->gen < 4) INTEL_FIREVERTICES(intel); - if (intel->batch->map != intel->batch->ptr) - intel_batchbuffer_flush(intel->batch); + if (intel->batch.used) + intel_batchbuffer_flush(intel); } static void @@ -583,7 +581,7 @@ intelFinish(struct gl_context * ctx) irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]); - if (irb && irb->region) + if (irb && irb->region && irb->region->buffer) drm_intel_bo_wait_rendering(irb->region->buffer); } if (fb->_DepthBuffer) { @@ -644,8 +642,8 @@ intelInitContext(struct intel_context *intel, mesaVis = &visual; } - if (!_mesa_initialize_context_for_api(&intel->ctx, api, mesaVis, shareCtx, - functions, (void *) intel)) { + if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx, + functions, (void *) intel)) { printf("%s: failed to init mesa context\n", __FUNCTION__); return GL_FALSE; } @@ -748,10 +746,10 @@ intelInitContext(struct intel_context *intel, driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, sPriv->myNum, (intel->gen >= 4) ? "i965" : "i915"); - if (intelScreen->deviceID == PCI_CHIP_I865_G) + if (intel->gen < 4) intel->maxBatchSize = 4096; else - intel->maxBatchSize = BATCH_SZ; + intel->maxBatchSize = sizeof(intel->batch.map); intel->bufmgr = intelScreen->bufmgr; @@ -805,8 +803,8 @@ intelInitContext(struct intel_context *intel, */ _mesa_init_point(ctx); - meta_init_metaops(ctx, &intel->meta); if (intel->gen >= 4) { + ctx->Const.sRGBCapable = GL_TRUE; if (MAX_WIDTH > 8192) ctx->Const.MaxRenderbufferSize = 8192; } else { @@ -863,7 +861,7 @@ intelInitContext(struct intel_context *intel, if (INTEL_DEBUG & DEBUG_BUFMGR) dri_bufmgr_set_debug(intel->bufmgr, GL_TRUE); - intel->batch = intel_batchbuffer_alloc(intel); + intel_batchbuffer_reset(intel); intel_fbo_init(intel); @@ -911,8 +909,6 @@ intelDestroyContext(__DRIcontext * driContextPriv) _mesa_meta_free(&intel->ctx); - meta_destroy_metaops(&intel->meta); - intel->vtbl.destroy(intel); _swsetup_DestroyContext(&intel->ctx); @@ -922,15 +918,12 @@ intelDestroyContext(__DRIcontext * driContextPriv) _swrast_DestroyContext(&intel->ctx); intel->Fallback = 0x0; /* don't call _swrast_Flush later */ - intel_batchbuffer_free(intel->batch); - intel->batch = NULL; + intel_batchbuffer_free(intel); free(intel->prim.vb); intel->prim.vb = NULL; drm_intel_bo_unreference(intel->prim.vb_bo); intel->prim.vb_bo = NULL; - drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); - intel->first_post_swapbuffers_batch = NULL; driDestroyOptionCache(&intel->optionCache); diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index fd3c3ba58fc..772b2fba5a8 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -32,7 +32,6 @@ #include <stdbool.h> #include "main/mtypes.h" #include "main/mm.h" -#include "dri_metaops.h" #ifdef __cplusplus extern "C" { @@ -152,8 +151,6 @@ struct intel_context bool (*render_target_supported)(gl_format format); } vtbl; - struct dri_metaops meta; - GLbitfield Fallback; /**< mask of INTEL_FALLBACK_x bits */ GLuint NewGLState; @@ -172,17 +169,28 @@ struct intel_context int urb_size; - struct intel_batchbuffer *batch; - drm_intel_bo *first_post_swapbuffers_batch; + struct intel_batchbuffer { + drm_intel_bo *bo; + struct cached_batch_item *cached_items; + + uint16_t emit, total; + uint16_t used, reserved_space; + uint32_t map[8192]; +#define BATCH_SZ (8192*sizeof(uint32_t)) + + uint32_t state_batch_offset; + bool is_blit; + } batch; + GLboolean need_throttle; GLboolean no_batch_wrap; struct { GLuint id; + uint32_t start_ptr; /**< for i8xx */ uint32_t primitive; /**< Current hardware primitive type */ void (*flush) (struct intel_context *); - GLubyte *start_ptr; /**< for i8xx */ drm_intel_bo *vb_bo; uint8_t *vb; unsigned int start_offset; /**< Byte offset of primitive sequence */ @@ -190,6 +198,14 @@ struct intel_context unsigned int count; /**< Number of vertices in current primitive */ } prim; + struct { + drm_intel_bo *bo; + GLuint offset; + uint32_t buffer_len; + uint32_t buffer_offset; + char buffer[4096]; + } upload; + GLuint stats_wm; /* Offsets of fields within the current vertex: diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c index 747e9dcb717..febc1d4f859 100644 --- a/src/mesa/drivers/dri/intel/intel_extensions.c +++ b/src/mesa/drivers/dri/intel/intel_extensions.c @@ -175,6 +175,7 @@ static const struct dri_extension brw_extensions[] = { { "GL_ARB_texture_non_power_of_two", NULL }, { "GL_ARB_texture_rg", NULL }, { "GL_EXT_draw_buffers2", GL_EXT_draw_buffers2_functions }, + { "GL_EXT_framebuffer_sRGB", NULL }, { "GL_EXT_shadow_funcs", NULL }, { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions }, { "GL_EXT_texture_sRGB", NULL }, diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 0db5a491c8f..8b57eb19f56 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -34,6 +34,7 @@ #include "main/framebuffer.h" #include "main/renderbuffer.h" #include "main/context.h" +#include "main/teximage.h" #include "main/texrender.h" #include "drivers/common/meta.h" @@ -580,7 +581,7 @@ intel_finish_render_texture(struct gl_context * ctx, * batch. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer like GEM does in the kernel. */ - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); } /** @@ -647,6 +648,84 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) } } +/** + * Try to do a glBlitFramebuffer using glCopyTexSubImage2D + * We can do this when the dst renderbuffer is actually a texture and + * there is no scaling, mirroring or scissoring. + * + * \return new buffer mask indicating the buffers left to blit using the + * normal path. + */ +static GLbitfield +intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx, + GLint srcX0, GLint srcY0, + GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + if (mask & GL_COLOR_BUFFER_BIT) { + const struct gl_framebuffer *drawFb = ctx->DrawBuffer; + const struct gl_framebuffer *readFb = ctx->ReadBuffer; + const struct gl_renderbuffer_attachment *drawAtt = + &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]]; + + /* If the source and destination are the same size with no + mirroring, the rectangles are within the size of the + texture and there is no scissor then we can use + glCopyTexSubimage2D to implement the blit. This will end + up as a fast hardware blit on some drivers */ + if (drawAtt && drawAtt->Texture && + srcX0 - srcX1 == dstX0 - dstX1 && + srcY0 - srcY1 == dstY0 - dstY1 && + srcX1 >= srcX0 && + srcY1 >= srcY0 && + srcX0 >= 0 && srcX1 <= readFb->Width && + srcY0 >= 0 && srcY1 <= readFb->Height && + dstX0 >= 0 && dstX1 <= drawFb->Width && + dstY0 >= 0 && dstY1 <= drawFb->Height && + !ctx->Scissor.Enabled) { + const struct gl_texture_object *texObj = drawAtt->Texture; + const GLuint dstLevel = drawAtt->TextureLevel; + const GLenum target = texObj->Target; + + struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, texObj, target, dstLevel); + GLenum internalFormat = texImage->InternalFormat; + + if (intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, + dstX0, dstY0, + srcX0, srcY0, + srcX1 - srcX0, /* width */ + srcY1 - srcY0)) + mask &= ~GL_COLOR_BUFFER_BIT; + } + } + + return mask; +} + +static void +intel_blit_framebuffer(struct gl_context *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */ + mask = intel_blit_framebuffer_copy_tex_sub_image(ctx, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); + if (mask == 0x0) + return; + + _mesa_meta_BlitFramebuffer(ctx, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); +} /** * Do one-time context initializations related to GL_EXT_framebuffer_object. @@ -663,7 +742,7 @@ intel_fbo_init(struct intel_context *intel) intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; - intel->ctx.Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer; + intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; #if FEATURE_OES_EGL_image intel->ctx.Driver.EGLImageTargetRenderbufferStorage = diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c index e7356a6da0d..d7561ee689d 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c @@ -285,7 +285,7 @@ do_blit_bitmap( struct gl_context *ctx, out: if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) - intel_batchbuffer_flush(intel->batch); + intel_batchbuffer_flush(intel); if (_mesa_is_bufferobj(unpack->BufferObj)) { /* done with PBO so unmap it now */ diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c index 54da29236d2..b2e77c7986a 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_read.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c @@ -80,6 +80,7 @@ do_blit_readpixels(struct gl_context * ctx, drm_intel_bo *dst_buffer; GLboolean all; GLint dst_x, dst_y; + GLuint dirty; DBG("%s\n", __FUNCTION__); @@ -129,7 +130,9 @@ do_blit_readpixels(struct gl_context * ctx, return GL_TRUE; } + dirty = intel->front_buffer_dirty; intel_prepare_render(intel); + intel->front_buffer_dirty = dirty; all = (width * height * src->cpp == dst->Base.Size && x == 0 && dst_offset == 0); @@ -138,8 +141,8 @@ do_blit_readpixels(struct gl_context * ctx, dst_y = 0; dst_buffer = intel_bufferobj_buffer(intel, dst, - all ? INTEL_WRITE_FULL : - INTEL_WRITE_PART); + all ? INTEL_WRITE_FULL : + INTEL_WRITE_PART); if (ctx->ReadBuffer->Name == 0) y = ctx->ReadBuffer->Height - (y + height); @@ -171,6 +174,10 @@ intelReadPixels(struct gl_context * ctx, DBG("%s\n", __FUNCTION__); + if (do_blit_readpixels + (ctx, x, y, width, height, format, type, pack, pixels)) + return; + intel_flush(ctx); /* glReadPixels() wont dirty the front buffer, so reset the dirty @@ -179,10 +186,6 @@ intelReadPixels(struct gl_context * ctx, intel_prepare_render(intel); intel->front_buffer_dirty = dirty; - if (do_blit_readpixels - (ctx, x, y, width, height, format, type, pack, pixels)) - return; - fallback_debug("%s: fallback to swrast\n", __FUNCTION__); /* Update Mesa state before calling down into _swrast_ReadPixels, as diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index e87e29462c3..0857fa8ad70 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -491,7 +491,7 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region) assert(region->cpp * region->pitch * region->height == pbo->Base.Size); - _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, pbo->Base.Size); + _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, (int)pbo->Base.Size); /* Now blit from the texture buffer to the new buffer: */ diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 5d14bcd34c0..356d5f72d89 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -111,8 +111,8 @@ intelDRI2Flush(__DRIdrawable *drawable) intel->need_throttle = GL_TRUE; - if (intel->batch->map != intel->batch->ptr) - intel_batchbuffer_flush(intel->batch); + if (intel->batch.used) + intel_batchbuffer_flush(intel); } static const struct __DRI2flushExtensionRec intelFlushExtension = { @@ -634,6 +634,51 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp) return (const __DRIconfig **)configs; } +struct intel_buffer { + __DRIbuffer base; + struct intel_region *region; +}; + +static __DRIbuffer * +intelAllocateBuffer(__DRIscreen *screen, + unsigned attachment, unsigned format, + int width, int height) +{ + struct intel_buffer *intelBuffer; + struct intel_screen *intelScreen = screen->private; + + intelBuffer = CALLOC(sizeof *intelBuffer); + if (intelBuffer == NULL) + return NULL; + + intelBuffer->region = intel_region_alloc(intelScreen, I915_TILING_NONE, + format / 8, width, height, GL_TRUE); + + if (intelBuffer->region == NULL) { + FREE(intelBuffer); + return NULL; + } + + intel_region_flink(intelBuffer->region, &intelBuffer->base.name); + + intelBuffer->base.attachment = attachment; + intelBuffer->base.cpp = intelBuffer->region->cpp; + intelBuffer->base.pitch = + intelBuffer->region->pitch * intelBuffer->region->cpp; + + return &intelBuffer->base; +} + +static void +intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) +{ + struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer; + + intel_region_release(&intelBuffer->region); + free(intelBuffer); +} + + const struct __DriverAPIRec driDriverAPI = { .DestroyScreen = intelDestroyScreen, .CreateContext = intelCreateContext, @@ -643,6 +688,8 @@ const struct __DriverAPIRec driDriverAPI = { .MakeCurrent = intelMakeCurrent, .UnbindContext = intelUnbindContext, .InitScreen2 = intelInitScreen2, + .AllocateBuffer = intelAllocateBuffer, + .ReleaseBuffer = intelReleaseBuffer }; /* This is the table of extensions that the loader will dlsym() for. */ diff --git a/src/mesa/drivers/dri/intel/intel_syncobj.c b/src/mesa/drivers/dri/intel/intel_syncobj.c index bbfac74b605..b303ea84dd8 100644 --- a/src/mesa/drivers/dri/intel/intel_syncobj.c +++ b/src/mesa/drivers/dri/intel/intel_syncobj.c @@ -72,9 +72,9 @@ intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s, struct intel_sync_object *sync = (struct intel_sync_object *)s; assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE); - intel_batchbuffer_emit_mi_flush(intel->batch); + intel_batchbuffer_emit_mi_flush(intel); - sync->bo = intel->batch->buf; + sync->bo = intel->batch.bo; drm_intel_bo_reference(sync->bo); intel_flush(ctx); diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h index 6552ed0d332..52462f39d54 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.h +++ b/src/mesa/drivers/dri/intel/intel_tex.h @@ -65,4 +65,12 @@ void intel_tex_unmap_images(struct intel_context *intel, int intel_compressed_num_bytes(GLuint mesaFormat); +GLboolean intel_copy_texsubimage(struct intel_context *intel, + GLenum target, + struct intel_texture_image *intelImage, + GLenum internalFormat, + GLint dstx, GLint dsty, + GLint x, GLint y, + GLsizei width, GLsizei height); + #endif diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index a40011ab40c..136d8e1d0a9 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -67,13 +67,13 @@ get_teximage_readbuffer(struct intel_context *intel, GLenum internalFormat) } -static GLboolean -do_copy_texsubimage(struct intel_context *intel, - GLenum target, - struct intel_texture_image *intelImage, - GLenum internalFormat, - GLint dstx, GLint dsty, - GLint x, GLint y, GLsizei width, GLsizei height) +GLboolean +intel_copy_texsubimage(struct intel_context *intel, + GLenum target, + struct intel_texture_image *intelImage, + GLenum internalFormat, + GLint dstx, GLint dsty, + GLint x, GLint y, GLsizei width, GLsizei height) { struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb; @@ -191,9 +191,9 @@ intelCopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level, &width, &height)) return; - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, 0, 0, x, y, width, height)) + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, 0, 0, x, y, width, height)) goto fail; return; @@ -239,9 +239,9 @@ intelCopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level, &width, &height)) return; - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, 0, 0, x, y, width, height)) + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, 0, 0, x, y, width, height)) goto fail; return; @@ -269,9 +269,9 @@ intelCopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level, /* Need to check texture is compatible with source format. */ - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, xoffset, 0, x, y, width, 1)) { + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, xoffset, 0, x, y, width, 1)) { fallback_debug("%s - fallback to swrast\n", __FUNCTION__); _mesa_meta_CopyTexSubImage1D(ctx, target, level, xoffset, x, y, width); } @@ -293,11 +293,10 @@ intelCopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level, /* Need to check texture is compatible with source format. */ - if (!do_copy_texsubimage(intel_context(ctx), target, - intel_texture_image(texImage), - internalFormat, - xoffset, yoffset, x, y, width, height)) { - + if (!intel_copy_texsubimage(intel_context(ctx), target, + intel_texture_image(texImage), + internalFormat, + xoffset, yoffset, x, y, width, height)) { fallback_debug("%s - fallback to swrast\n", __FUNCTION__); _mesa_meta_CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, x, y, width, height); diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index cd8c4c22e5a..9dba529c58d 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -231,15 +231,17 @@ try_pbo_upload(struct intel_context *intel, dst_stride = intelImage->mt->region->pitch; - if (drm_intel_bo_references(intel->batch->buf, dst_buffer)) + if (drm_intel_bo_references(intel->batch.bo, dst_buffer)) intel_flush(&intel->ctx); { - drm_intel_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ); + GLuint offset; + drm_intel_bo *src_buffer = intel_bufferobj_source(intel, pbo, &offset); if (!intelEmitCopyBlit(intel, intelImage->mt->cpp, - src_stride, src_buffer, src_offset, GL_FALSE, + src_stride, src_buffer, + src_offset + offset, GL_FALSE, dst_stride, dst_buffer, 0, intelImage->mt->region->tiling, 0, 0, dst_x, dst_y, width, height, @@ -429,7 +431,7 @@ intelTexImage(struct gl_context * ctx, if (intelImage->mt) { if (pixels != NULL) { /* Flush any queued rendering with the texture before mapping. */ - if (drm_intel_bo_references(intel->batch->buf, + if (drm_intel_bo_references(intel->batch.bo, intelImage->mt->region->buffer)) { intel_flush(ctx); } diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c index 7c989df5ec0..35b01a97402 100644 --- a/src/mesa/drivers/dri/mach64/mach64_context.c +++ b/src/mesa/drivers/dri/mach64/mach64_context.c @@ -120,7 +120,7 @@ GLboolean mach64CreateContext( gl_api api, shareCtx = ((mach64ContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - mmesa->glCtx = _mesa_create_context(glVisual, shareCtx, + mmesa->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx, &functions, (void *)mmesa); if (!mmesa->glCtx) { FREE(mmesa); diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c index d1b281a2c05..eb7df9785c1 100644 --- a/src/mesa/drivers/dri/mga/mga_xmesa.c +++ b/src/mesa/drivers/dri/mga/mga_xmesa.c @@ -457,7 +457,7 @@ mgaCreateContext( gl_api api, shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, + mmesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx, &functions, (void *) mmesa); if (!mmesa->glCtx) { FREE(mmesa); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index 53a121420d3..71dde413873 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -115,7 +115,8 @@ nouveau_context_init(struct gl_context *ctx, struct nouveau_screen *screen, nouveau_fbo_functions_init(&functions); /* Initialize the mesa context. */ - _mesa_initialize_context(ctx, visual, share_ctx, &functions, NULL); + _mesa_initialize_context(ctx, API_OPENGL, visual, + share_ctx, &functions, NULL); nouveau_state_init(ctx); nouveau_bo_state_init(ctx); diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c index 274108005f3..247d86ca008 100644 --- a/src/mesa/drivers/dri/r128/r128_context.c +++ b/src/mesa/drivers/dri/r128/r128_context.c @@ -128,7 +128,7 @@ GLboolean r128CreateContext( gl_api api, shareCtx = ((r128ContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, + rmesa->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx, &functions, (void *) rmesa); if (!rmesa->glCtx) { FREE(rmesa); diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c index 5d69012a81f..63e03b0e0c7 100644 --- a/src/mesa/drivers/dri/r200/r200_vertprog.c +++ b/src/mesa/drivers/dri/r200/r200_vertprog.c @@ -438,7 +438,7 @@ static GLboolean r200_translate_vertex_program(struct gl_context *ctx, struct r2 (1 << VERT_RESULT_TEX5) | (1 << VERT_RESULT_PSIZ))) != 0) { if (R200_DEBUG & RADEON_FALLBACKS) { fprintf(stderr, "can't handle vert prog outputs 0x%llx\n", - mesa_vp->Base.OutputsWritten); + (unsigned long long) mesa_vp->Base.OutputsWritten); } return GL_FALSE; } diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c index 782671bac01..deba9ca834d 100644 --- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c @@ -49,6 +49,11 @@ static void presub_string(char out[10], unsigned int inst) } } +static int get_msb(unsigned int bit, unsigned int r400_ext_addr) +{ + return (r400_ext_addr & bit) ? 1 << 5 : 0; +} + /* just some random things... */ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) { @@ -61,16 +66,21 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) fprintf(stderr, "Hardware program\n"); fprintf(stderr, "----------------\n"); + if (c->is_r400) { + fprintf(stderr, "code_offset_ext: %08x\n", code->r400_code_offset_ext); + } for (n = 0; n <= (code->config & 3); n++) { uint32_t code_addr = code->code_addr[3 - (code->config & 3) + n]; - int alu_offset = (code_addr & R300_ALU_START_MASK) >> R300_ALU_START_SHIFT; - int alu_end = (code_addr & R300_ALU_SIZE_MASK) >> R300_ALU_SIZE_SHIFT; + unsigned int alu_offset = ((code_addr & R300_ALU_START_MASK) >> R300_ALU_START_SHIFT) + + (((code->r400_code_offset_ext >> (24 - (n * 6))) & 0x7) << 6); + unsigned int alu_end = ((code_addr & R300_ALU_SIZE_MASK) >> R300_ALU_SIZE_SHIFT) + + (((code->r400_code_offset_ext >> (27 - (n * 6))) & 0x7) << 6); int tex_offset = (code_addr & R300_TEX_START_MASK) >> R300_TEX_START_SHIFT; int tex_end = (code_addr & R300_TEX_SIZE_MASK) >> R300_TEX_SIZE_SHIFT; - fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, " - "alu_end: %d, tex_end: %d (code_addr: %08x)\n", n, + fprintf(stderr, "NODE %d: alu_offset: %u, tex_offset: %d, " + "alu_end: %u, tex_end: %d (code_addr: %08x)\n", n, alu_offset, tex_offset, alu_end, tex_end, code_addr); if (n > 0 || (code->config & R300_PFS_CNTL_FIRST_NODE_HAS_TEX)) { @@ -125,11 +135,15 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) for (j = 0; j < 3; ++j) { int regc = code->alu.inst[i].rgb_addr >> (j * 6); int rega = code->alu.inst[i].alpha_addr >> (j * 6); + int msbc = get_msb(R400_ADDR_EXT_RGB_MSB_BIT(j), + code->alu.inst[i].r400_ext_addr); + int msba = get_msb(R400_ADDR_EXT_A_MSB_BIT(j), + code->alu.inst[i].r400_ext_addr); sprintf(srcc[j], "%c%i", - (regc & 32) ? 'c' : 't', regc & 31); + (regc & 32) ? 'c' : 't', (regc & 31) | msbc); sprintf(srca[j], "%c%i", - (rega & 32) ? 'c' : 't', rega & 31); + (rega & 32) ? 'c' : 't', (rega & 31) | msba); } dstc[0] = 0; @@ -141,9 +155,14 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) (code->alu.inst[i]. rgb_addr & R300_ALU_DSTC_REG_Z) ? "z" : ""); if (flags[0] != 0) { + unsigned int msb = get_msb( + R400_ADDRD_EXT_RGB_MSB_BIT, + code->alu.inst[i].r400_ext_addr); + sprintf(dstc, "t%i.%s ", - (code->alu.inst[i]. - rgb_addr >> R300_ALU_DSTC_SHIFT) & 31, + ((code->alu.inst[i]. + rgb_addr >> R300_ALU_DSTC_SHIFT) + & 31) | msb, flags); } sprintf(flags, "%s%s%s", @@ -166,9 +185,13 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user) dsta[0] = 0; if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_REG) { + unsigned int msb = get_msb( + R400_ADDRD_EXT_A_MSB_BIT, + code->alu.inst[i].r400_ext_addr); sprintf(dsta, "t%i.w ", - (code->alu.inst[i]. - alpha_addr >> R300_ALU_DSTA_SHIFT) & 31); + ((code->alu.inst[i]. + alpha_addr >> R300_ALU_DSTA_SHIFT) & 31) + | msb); } if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_OUTPUT) { sprintf(tmp, "o%i.w ", diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c index 1db8678e890..28d132a5fe3 100644 --- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c +++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c @@ -64,6 +64,20 @@ struct r300_emit_state { __FILE__, __FUNCTION__, ##args); \ } while(0) +static unsigned int get_msbs_alu(unsigned int bits) +{ + return (bits >> 6) & 0x7; +} + +/** + * @param lsbs The number of least significant bits + */ +static unsigned int get_msbs_tex(unsigned int bits, unsigned int lsbs) +{ + return (bits >> lsbs) & 0x15; +} + +#define R400_EXT_GET_MSBS(x, lsbs, mask) (((x) >> lsbs) & mask) /** * Mark a temporary register as used. @@ -83,7 +97,7 @@ static unsigned int use_source(struct r300_fragment_program_code* code, struct r return src.Index | (1 << 5); } else if (src.File == RC_FILE_TEMPORARY) { use_temporary(code, src.Index); - return src.Index; + return src.Index & 0x1f; } return 0; @@ -151,11 +165,19 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i code->alu.inst[ip].alpha_inst = translate_alpha_opcode(c, inst->Alpha.Opcode); for(j = 0; j < 3; ++j) { + /* Set the RGB address */ unsigned int src = use_source(code, inst->RGB.Src[j]); unsigned int arg; + if (inst->RGB.Src[j].Index >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_RGB_MSB_BIT(j); + code->alu.inst[ip].rgb_addr |= src << (6*j); + /* Set the Alpha address */ src = use_source(code, inst->Alpha.Src[j]); + if (inst->Alpha.Src[j].Index >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_A_MSB_BIT(j); + code->alu.inst[ip].alpha_addr |= src << (6*j); arg = r300FPTranslateRGBSwizzle(inst->RGB.Arg[j].Source, inst->RGB.Arg[j].Swizzle); @@ -223,8 +245,10 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i if (inst->RGB.WriteMask) { use_temporary(code, inst->RGB.DestIndex); + if (inst->RGB.DestIndex >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_RGB_MSB_BIT; code->alu.inst[ip].rgb_addr |= - (inst->RGB.DestIndex << R300_ALU_DSTC_SHIFT) | + ((inst->RGB.DestIndex & 0x1f) << R300_ALU_DSTC_SHIFT) | (inst->RGB.WriteMask << R300_ALU_DSTC_REG_MASK_SHIFT); } if (inst->RGB.OutputWriteMask) { @@ -236,8 +260,10 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i if (inst->Alpha.WriteMask) { use_temporary(code, inst->Alpha.DestIndex); + if (inst->Alpha.DestIndex >= R300_PFS_NUM_TEMP_REGS) + code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_A_MSB_BIT; code->alu.inst[ip].alpha_addr |= - (inst->Alpha.DestIndex << R300_ALU_DSTA_SHIFT) | + ((inst->Alpha.DestIndex & 0x1f) << R300_ALU_DSTA_SHIFT) | R300_ALU_DSTA_REG; } if (inst->Alpha.OutputWriteMask) { @@ -269,6 +295,8 @@ static int finish_node(struct r300_emit_state * emit) unsigned tex_offset; unsigned tex_end; + unsigned int alu_offset_msbs, alu_end_msbs; + if (code->alu.length == emit->node_first_alu) { /* Generate a single NOP for this node */ struct rc_pair_instruction inst; @@ -301,13 +329,48 @@ static int finish_node(struct r300_emit_state * emit) * * Also note that the register specification from AMD is slightly * incorrect in its description of this register. */ - code->code_addr[emit->current_node] = - (alu_offset << R300_ALU_START_SHIFT) | - (alu_end << R300_ALU_SIZE_SHIFT) | - (tex_offset << R300_TEX_START_SHIFT) | - (tex_end << R300_TEX_SIZE_SHIFT) | - emit->node_flags; - + code->code_addr[emit->current_node] = + ((alu_offset << R300_ALU_START_SHIFT) + & R300_ALU_START_MASK) + | ((alu_end << R300_ALU_SIZE_SHIFT) + & R300_ALU_SIZE_MASK) + | ((tex_offset << R300_TEX_START_SHIFT) + & R300_TEX_START_MASK) + | ((tex_end << R300_TEX_SIZE_SHIFT) + & R300_TEX_SIZE_MASK) + | emit->node_flags + | (get_msbs_tex(tex_offset, 5) + << R400_TEX_START_MSB_SHIFT) + | (get_msbs_tex(tex_end, 5) + << R400_TEX_SIZE_MSB_SHIFT) + ; + + /* Write r400 extended instruction fields. These will be ignored on + * r300 cards. */ + alu_offset_msbs = get_msbs_alu(alu_offset); + alu_end_msbs = get_msbs_alu(alu_end); + switch(emit->current_node) { + case 0: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START3_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE3_MSB_SHIFT; + break; + case 1: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START2_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE2_MSB_SHIFT; + break; + case 2: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START1_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE1_MSB_SHIFT; + break; + case 3: + code->r400_code_offset_ext |= + alu_offset_msbs << R400_ALU_START0_MSB_SHIFT + | alu_end_msbs << R400_ALU_SIZE0_MSB_SHIFT; + break; + } return 1; } @@ -348,7 +411,7 @@ static int emit_tex(struct r300_emit_state * emit, struct rc_instruction * inst) unsigned int opcode; PROG_CODE; - if (code->tex.length >= R300_PFS_MAX_TEX_INST) { + if (code->tex.length >= emit->compiler->Base.max_tex_insts) { error("Too many TEX instructions"); return 0; } @@ -376,10 +439,17 @@ static int emit_tex(struct r300_emit_state * emit, struct rc_instruction * inst) use_temporary(code, inst->U.I.SrcReg[0].Index); code->tex.inst[code->tex.length++] = - (inst->U.I.SrcReg[0].Index << R300_SRC_ADDR_SHIFT) | - (dest << R300_DST_ADDR_SHIFT) | - (unit << R300_TEX_ID_SHIFT) | - (opcode << R300_TEX_INST_SHIFT); + ((inst->U.I.SrcReg[0].Index << R300_SRC_ADDR_SHIFT) + & R300_SRC_ADDR_MASK) + | ((dest << R300_DST_ADDR_SHIFT) + & R300_DST_ADDR_MASK) + | (unit << R300_TEX_ID_SHIFT) + | (opcode << R300_TEX_INST_SHIFT) + | (inst->U.I.SrcReg[0].Index >= R300_PFS_NUM_TEMP_REGS ? + R400_SRC_ADDR_EXT_BIT : 0) + | (dest >= R300_PFS_NUM_TEMP_REGS ? + R400_DST_ADDR_EXT_BIT : 0) + ; return 1; } @@ -393,6 +463,7 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user) struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c; struct r300_emit_state emit; struct r300_fragment_program_code *code = &compiler->code->code.r300; + unsigned int tex_end; memset(&emit, 0, sizeof(emit)); emit.compiler = compiler; @@ -424,11 +495,28 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user) finish_node(&emit); code->config |= emit.current_node; /* FIRST_NODE_HAS_TEX set by finish_node */ + + /* Set r400 extended instruction fields. These values will be ignored + * on r300 cards. */ + code->r400_code_offset_ext |= + (get_msbs_alu(0) + << R400_ALU_OFFSET_MSB_SHIFT) + | (get_msbs_alu(code->alu.length - 1) + << R400_ALU_SIZE_MSB_SHIFT); + + tex_end = code->tex.length ? code->tex.length - 1 : 0; code->code_offset = - (0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT) | - ((code->alu.length-1) << R300_PFS_CNTL_ALU_END_SHIFT) | - (0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT) | - ((code->tex.length ? code->tex.length-1 : 0) << R300_PFS_CNTL_TEX_END_SHIFT); + ((0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT) + & R300_PFS_CNTL_ALU_OFFSET_MASK) + | (((code->alu.length - 1) << R300_PFS_CNTL_ALU_END_SHIFT) + & R300_PFS_CNTL_ALU_END_MASK) + | ((0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT) + & R300_PFS_CNTL_TEX_OFFSET_MASK) + | ((tex_end << R300_PFS_CNTL_TEX_END_SHIFT) + & R300_PFS_CNTL_TEX_END_MASK) + | (get_msbs_tex(0, 5) << R400_TEX_START_MSB_SHIFT) + | (get_msbs_tex(tex_end, 6) << R400_TEX_SIZE_MSB_SHIFT) + ; if (emit.current_node < 3) { int shift = 3 - emit.current_node; @@ -438,4 +526,11 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user) for(i = 0; i < shift; ++i) code->code_addr[i] = 0; } + + if (code->pixsize >= R300_PFS_NUM_TEMP_REGS + || code->alu.length > R300_PFS_MAX_ALU_INST + || code->tex.length > R300_PFS_MAX_TEX_INST) { + + code->r390_mode = 1; + } } diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c index 05d3da8a10d..fa906f2fdde 100644 --- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c +++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c @@ -222,13 +222,14 @@ unsigned int r300FPTranslateRGBSwizzle(unsigned int src, unsigned int swizzle) */ unsigned int r300FPTranslateAlphaSwizzle(unsigned int src, unsigned int swizzle) { + unsigned int swz = GET_SWZ(swizzle, 0); if (src == RC_PAIR_PRESUB_SRC) { - return R300_ALU_ARGA_SRCP_X + swizzle; + return R300_ALU_ARGA_SRCP_X + swz; } - if (swizzle < 3) - return swizzle + 3*src; + if (swz < 3) + return swz + 3*src; - switch(swizzle) { + switch(swz) { case RC_SWIZZLE_W: return R300_ALU_ARGA_SRC0A + src; case RC_SWIZZLE_ONE: return R300_ALU_ARGA_ONE; case RC_SWIZZLE_ZERO: return R300_ALU_ARGA_ZERO; diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c index e0d349b98ce..1616306afbd 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c @@ -124,7 +124,7 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c) /* This pass makes it easier for the scheduler to group TEX * instructions and reduces the chances of creating too * many texture indirections.*/ - {"register rename", 1, !is_r500 || opt, rc_rename_regs, NULL}, + {"register rename", 1, !is_r500, rc_rename_regs, NULL}, {"pair translate", 1, 1, rc_pair_translate, NULL}, {"pair scheduling", 1, 1, rc_pair_schedule, NULL}, {"register allocation", 1, opt, rc_pair_regalloc, NULL}, diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c index 472029f63d0..8ad2175eadf 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c @@ -490,13 +490,6 @@ static void translate_vertex_program(struct radeon_compiler *c, void *user) continue; if (info->HasDstReg) { - /* Relative addressing of destination operands is not supported yet. */ - if (vpi->DstReg.RelAddr) { - rc_error(&compiler->Base, "Vertex program does not support relative " - "addressing of destination operands (yet).\n"); - return; - } - /* Neither is Saturate. */ if (vpi->SaturateMode != RC_SATURATE_NONE) { rc_error(&compiler->Base, "Vertex program does not support the Saturate " @@ -668,7 +661,6 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) char hwtemps[RC_REGISTER_MAX_INDEX]; struct temporary_allocation * ta; unsigned int i, j; - struct rc_instruction *last_inst_src_reladdr = NULL; memset(hwtemps, 0, sizeof(hwtemps)); @@ -693,28 +685,11 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) } } - /* Pass 2: If there is relative addressing of dst temporaries, we cannot change register indices. Give up. - * For src temporaries, save the last instruction which uses relative addressing. */ - for (inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode); - - if (opcode->HasDstReg) - if (inst->U.I.DstReg.RelAddr) - return; - - for (i = 0; i < opcode->NumSrcRegs; ++i) { - if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY && - inst->U.I.SrcReg[i].RelAddr) { - last_inst_src_reladdr = inst; - } - } - } - ta = (struct temporary_allocation*)memory_pool_malloc(&compiler->Base.Pool, sizeof(struct temporary_allocation) * num_orig_temps); memset(ta, 0, sizeof(struct temporary_allocation) * num_orig_temps); - /* Pass 3: Determine original temporary lifetimes */ + /* Pass 2: Determine original temporary lifetimes */ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); /* Instructions inside of loops need to use the ENDLOOP @@ -744,41 +719,22 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) for (i = 0; i < opcode->NumSrcRegs; ++i) { if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { - struct rc_instruction *last_read; - - /* From "last_inst_src_reladdr", "end_loop", and "inst", - * select the instruction with the highest instruction index (IP). - * Note that "end_loop", if available, has always a higher index than "inst". */ - if (last_inst_src_reladdr) { - if (end_loop) { - last_read = last_inst_src_reladdr->IP > end_loop->IP ? - last_inst_src_reladdr : end_loop; - } else { - last_read = last_inst_src_reladdr->IP > inst->IP ? - last_inst_src_reladdr : inst; - } - } else { - last_read = end_loop ? end_loop : inst; - } - - ta[inst->U.I.SrcReg[i].Index].LastRead = last_read; + ta[inst->U.I.SrcReg[i].Index].LastRead = end_loop ? end_loop : inst; } } } - /* Pass 4: Register allocation */ + /* Pass 3: Register allocation */ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode); - if (!last_inst_src_reladdr || last_inst_src_reladdr->IP < inst->IP) { - for (i = 0; i < opcode->NumSrcRegs; ++i) { - if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { - unsigned int orig = inst->U.I.SrcReg[i].Index; - inst->U.I.SrcReg[i].Index = ta[orig].HwTemp; + for (i = 0; i < opcode->NumSrcRegs; ++i) { + if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) { + unsigned int orig = inst->U.I.SrcReg[i].Index; + inst->U.I.SrcReg[i].Index = ta[orig].HwTemp; - if (ta[orig].Allocated && inst == ta[orig].LastRead) - hwtemps[ta[orig].HwTemp] = 0; - } + if (ta[orig].Allocated && inst == ta[orig].LastRead) + hwtemps[ta[orig].HwTemp] = 0; } } @@ -792,12 +748,7 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user) break; } ta[orig].Allocated = 1; - if (last_inst_src_reladdr && - last_inst_src_reladdr->IP > inst->IP) { - ta[orig].HwTemp = orig; - } else { - ta[orig].HwTemp = j; - } + ta[orig].HwTemp = j; hwtemps[ta[orig].HwTemp] = 1; } diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c index 5da82d90f67..1febc19cc2d 100644 --- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c +++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c @@ -170,7 +170,7 @@ static unsigned int translate_arg_rgb(struct rc_pair_instruction *inst, int arg) static unsigned int translate_arg_alpha(struct rc_pair_instruction *inst, int i) { unsigned int t = inst->Alpha.Arg[i].Source; - t |= fix_hw_swizzle(inst->Alpha.Arg[i].Swizzle) << 2; + t |= fix_hw_swizzle(GET_SWZ(inst->Alpha.Arg[i].Swizzle, 0)) << 2; t |= inst->Alpha.Arg[i].Negate << 5; t |= inst->Alpha.Arg[i].Abs << 6; return t; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h index b69e81698ae..d1451668947 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h @@ -31,6 +31,9 @@ #define R300_PFS_NUM_TEMP_REGS 32 #define R300_PFS_NUM_CONST_REGS 32 +#define R400_PFS_MAX_ALU_INST 512 +#define R400_PFS_MAX_TEX_INST 512 + #define R500_PFS_MAX_INST 512 #define R500_PFS_NUM_TEMP_REGS 128 #define R500_PFS_NUM_CONST_REGS 256 @@ -187,24 +190,29 @@ struct r300_fragment_program_node { */ struct r300_fragment_program_code { struct { - int length; /**< total # of texture instructions used */ - uint32_t inst[R300_PFS_MAX_TEX_INST]; + unsigned int length; /**< total # of texture instructions used */ + uint32_t inst[R400_PFS_MAX_TEX_INST]; } tex; struct { - int length; /**< total # of ALU instructions used */ + unsigned int length; /**< total # of ALU instructions used */ struct { uint32_t rgb_inst; uint32_t rgb_addr; uint32_t alpha_inst; uint32_t alpha_addr; - } inst[R300_PFS_MAX_ALU_INST]; + uint32_t r400_ext_addr; + } inst[R400_PFS_MAX_ALU_INST]; } alu; uint32_t config; /* US_CONFIG */ uint32_t pixsize; /* US_PIXSIZE */ uint32_t code_offset; /* US_CODE_OFFSET */ + uint32_t r400_code_offset_ext; /* US_CODE_EXT */ uint32_t code_addr[4]; /* US_CODE_ADDR */ + /*US_CODE_BANK.R390_MODE: Enables 512 instructions and 64 temporaries + * for r400 cards */ + unsigned int r390_mode:1; }; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c index 65548604bcc..79cd7996f78 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c @@ -373,9 +373,11 @@ void rc_get_stats(struct radeon_compiler *c, struct rc_program_stats *s) const struct rc_opcode_info * info; rc_for_all_reads_mask(tmp, reg_count_callback, &max_reg); if (tmp->Type == RC_INSTRUCTION_NORMAL) { + info = rc_get_opcode_info(tmp->U.I.Opcode); + if (info->Opcode == RC_OPCODE_BEGIN_TEX) + continue; if (tmp->U.I.PreSub.Opcode != RC_PRESUB_NONE) s->num_presub_ops++; - info = rc_get_opcode_info(tmp->U.I.Opcode); } else { if (tmp->U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Used) s->num_presub_ops++; @@ -402,11 +404,11 @@ static void print_stats(struct radeon_compiler * c) { struct rc_program_stats s; - rc_get_stats(c, &s); - - if (s.num_insts < 4) + if (c->initial_num_insts <= 5) return; + rc_get_stats(c, &s); + switch (c->type) { case RC_VERTEX_PROGRAM: fprintf(stderr,"~~~~~~~~~ VERTEX PROGRAM ~~~~~~~~\n" @@ -461,6 +463,11 @@ void rc_run_compiler_passes(struct radeon_compiler *c, struct radeon_compiler_pa /* Executes a list of compiler passes given in the parameter 'list'. */ void rc_run_compiler(struct radeon_compiler *c, struct radeon_compiler_pass *list) { + struct rc_program_stats s; + + rc_get_stats(c, &s); + c->initial_num_insts = s.num_insts; + if (c->Debug & RC_DBG_LOG) { fprintf(stderr, "%s: before compilation\n", shader_name[c->type]); rc_print_program(&c->Program); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h index e6633395895..2d8e415f350 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h @@ -50,6 +50,7 @@ struct radeon_compiler { char * ErrorMsg; /* Hardware specification. */ + unsigned is_r400:1; unsigned is_r500:1; unsigned has_half_swizzles:1; unsigned has_presub:1; @@ -57,6 +58,7 @@ struct radeon_compiler { unsigned max_temp_regs; unsigned max_constants; int max_alu_insts; + unsigned max_tex_insts; /* Whether to remove unused constants and empty holes in constant space. */ unsigned remove_unused_constants:1; @@ -70,6 +72,8 @@ struct radeon_compiler { /*@}*/ struct emulate_loop_state loop_state; + + unsigned initial_num_insts; /* Number of instructions at start. */ }; void rc_init(struct radeon_compiler * c); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c index 2482fc68beb..15ec4418cb8 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c @@ -55,6 +55,24 @@ rc_swizzle get_swz(unsigned int swz, rc_swizzle idx) return GET_SWZ(swz, idx); } +/** + * The purpose of this function is to standardize the number channels used by + * swizzles. All swizzles regardless of what instruction they are a part of + * should have 4 channels initialized with values. + * @param channels The number of channels in initial_value that have a + * meaningful value. + * @return An initialized swizzle that has all of the unused channels set to + * RC_SWIZZLE_UNUSED. + */ +unsigned int rc_init_swizzle(unsigned int initial_value, unsigned int channels) +{ + unsigned int i; + for (i = channels; i < 4; i++) { + SET_SWZ(initial_value, i, RC_SWIZZLE_UNUSED); + } + return initial_value; +} + unsigned int combine_swizzles4(unsigned int src, rc_swizzle swz_x, rc_swizzle swz_y, rc_swizzle swz_z, rc_swizzle swz_w) { @@ -147,13 +165,17 @@ unsigned int rc_src_reads_dst_mask( return dst_mask & rc_swizzle_to_writemask(src_swz); } -unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels) +/** + * @return A bit mask specifying whether this swizzle will select from an RGB + * source, an Alpha source, or both. + */ +unsigned int rc_source_type_swz(unsigned int swizzle) { unsigned int chan; unsigned int swz = RC_SWIZZLE_UNUSED; unsigned int ret = RC_SOURCE_NONE; - for(chan = 0; chan < channels; chan++) { + for(chan = 0; chan < 4; chan++) { swz = GET_SWZ(swizzle, chan); if (swz == RC_SWIZZLE_W) { ret |= RC_SOURCE_ALPHA; @@ -202,7 +224,7 @@ static void can_use_presub_read_cb( if (d->RemoveSrcs[i].File == file && d->RemoveSrcs[i].Index == index) { src_type &= - ~rc_source_type_swz(d->RemoveSrcs[i].Swizzle, 4); + ~rc_source_type_swz(d->RemoveSrcs[i].Swizzle); } } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h index 461ab9ffb10..dd0f6c66156 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h @@ -10,6 +10,8 @@ unsigned int rc_swizzle_to_writemask(unsigned int swz); rc_swizzle get_swz(unsigned int swz, rc_swizzle idx); +unsigned int rc_init_swizzle(unsigned int initial_value, unsigned int channels); + unsigned int combine_swizzles4(unsigned int src, rc_swizzle swz_x, rc_swizzle swz_y, rc_swizzle swz_z, rc_swizzle swz_w); @@ -32,7 +34,7 @@ unsigned int rc_src_reads_dst_mask( unsigned int dst_idx, unsigned int dst_mask); -unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels); +unsigned int rc_source_type_swz(unsigned int swizzle); unsigned int rc_source_type_mask(unsigned int mask); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c index d0a64d936e0..c080d5aecc6 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c @@ -140,14 +140,8 @@ static void pair_sub_for_all_args( for(i = 0; i < info->NumSrcRegs; i++) { unsigned int src_type; - unsigned int channels = 0; - if (&fullinst->U.P.RGB == sub) - channels = 3; - else if (&fullinst->U.P.Alpha == sub) - channels = 1; - - assert(channels > 0); - src_type = rc_source_type_swz(sub->Arg[i].Swizzle, channels); + + src_type = rc_source_type_swz(sub->Arg[i].Swizzle); if (src_type == RC_SOURCE_NONE) continue; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c index 87906f37b12..678e1475883 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c @@ -160,12 +160,8 @@ static void update_instruction(struct deadcode_state * s, struct rc_instruction unsigned char * pused = get_used_ptr(s, inst->U.I.DstReg.File, inst->U.I.DstReg.Index); if (pused) { usedmask = *pused & inst->U.I.DstReg.WriteMask; - if (!inst->U.I.DstReg.RelAddr) - *pused &= ~usedmask; + *pused &= ~usedmask; } - - if (inst->U.I.DstReg.RelAddr) - mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X); } insts->WriteMask |= usedmask; @@ -219,22 +215,9 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user) { struct deadcode_state s; unsigned int nr_instructions; - unsigned has_temp_reladdr_src = 0; rc_dataflow_mark_outputs_fn dce = (rc_dataflow_mark_outputs_fn)user; unsigned int ip; - /* Give up if there is relative addressing of destination operands. */ - for(struct rc_instruction * inst = c->Program.Instructions.Next; - inst != &c->Program.Instructions; - inst = inst->Next) { - const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode); - if (opcode->HasDstReg && - inst->U.I.DstReg.WriteMask && - inst->U.I.DstReg.RelAddr) { - return; - } - } - memset(&s, 0, sizeof(s)); s.C = c; @@ -321,32 +304,6 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user) rc_error(c, "%s: Unhandled control flow instruction %s\n", __FUNCTION__, opcode->Name); } } - - if (!has_temp_reladdr_src) { - for (unsigned i = 0; i < opcode->NumSrcRegs; i++) { - if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY && - inst->U.I.SrcReg[i].RelAddr) { - /* If there is a register read from a temporary file with relative addressing, - * mark all preceding written registers as used. */ - for (struct rc_instruction *ptr = inst->Prev; - ptr != &c->Program.Instructions; - ptr = ptr->Prev) { - opcode = rc_get_opcode_info(ptr->U.I.Opcode); - if (opcode->HasDstReg && - ptr->U.I.DstReg.File == RC_FILE_TEMPORARY && - ptr->U.I.DstReg.WriteMask) { - mark_used(&s, - ptr->U.I.DstReg.File, - ptr->U.I.DstReg.Index, - ptr->U.I.DstReg.WriteMask); - } - } - - has_temp_reladdr_src = 1; - break; - } - } - } } update_instruction(&s, inst); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c index 44f4c0fbdc7..5caff91b00e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c @@ -139,7 +139,6 @@ static void copy_propagate(struct radeon_compiler * c, struct rc_instruction * i unsigned int i; if (inst_mov->U.I.DstReg.File != RC_FILE_TEMPORARY || - inst_mov->U.I.DstReg.RelAddr || inst_mov->U.I.WriteALUResult || inst_mov->U.I.SaturateMode) return; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c index 9beb5d63579..8e10813ff06 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c @@ -365,8 +365,8 @@ static int merge_presub_sources( for(arg = 0; arg < info->NumSrcRegs; arg++) { /*If this arg does not read from an rgb source, * do nothing. */ - if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle, - 3) & type)) { + if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle) + & type)) { continue; } @@ -423,11 +423,11 @@ static int destructive_merge_instructions( unsigned int index = 0; int source; - if (alpha->Alpha.Arg[arg].Swizzle < 3) { + if (GET_SWZ(alpha->Alpha.Arg[arg].Swizzle, 0) < 3) { srcrgb = 1; file = alpha->RGB.Src[oldsrc].File; index = alpha->RGB.Src[oldsrc].Index; - } else if (alpha->Alpha.Arg[arg].Swizzle < 4) { + } else if (GET_SWZ(alpha->Alpha.Arg[arg].Swizzle, 0) < 4) { srcalpha = 1; file = alpha->Alpha.Src[oldsrc].File; index = alpha->Alpha.Src[oldsrc].Index; @@ -544,18 +544,12 @@ static void rgb_to_alpha_remap ( { int new_src_index; unsigned int i; - struct rc_pair_instruction_source * old_src = - rc_pair_get_src(&inst->U.P, arg); - if (!old_src) { - return; - } for (i = 0; i < 3; i++) { if (get_swz(arg->Swizzle, i) == old_swz) { SET_SWZ(arg->Swizzle, i, RC_SWIZZLE_W); } } - memset(old_src, 0, sizeof(struct rc_pair_instruction_source)); new_src_index = rc_pair_alloc_source(&inst->U.P, 0, 1, old_file, new_index); /* This conversion is not possible, we must have made a mistake in @@ -728,7 +722,8 @@ static int convert_rgb_to_alpha( for (j = 0; j < 3; j++) { unsigned int swz = get_swz(pair_inst->Alpha.Arg[i].Swizzle, j); if (swz != RC_SWIZZLE_UNUSED) { - pair_inst->Alpha.Arg[i].Swizzle = swz; + pair_inst->Alpha.Arg[i].Swizzle = + rc_init_swizzle(swz, 1); break; } } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c index fc05366f50e..6d7263b4ab6 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c @@ -28,6 +28,7 @@ #include "radeon_program_pair.h" #include "radeon_compiler.h" +#include "radeon_compiler_util.h" /** @@ -232,7 +233,8 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c, return; } pair->RGB.Arg[i].Source = source; - pair->RGB.Arg[i].Swizzle = inst->SrcReg[i].Swizzle & 0x1ff; + pair->RGB.Arg[i].Swizzle = + rc_init_swizzle(inst->SrcReg[i].Swizzle, 3); pair->RGB.Arg[i].Abs = inst->SrcReg[i].Abs; pair->RGB.Arg[i].Negate = !!(inst->SrcReg[i].Negate & (RC_MASK_X | RC_MASK_Y | RC_MASK_Z)); } @@ -252,7 +254,7 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c, return; } pair->Alpha.Arg[i].Source = source; - pair->Alpha.Arg[i].Swizzle = swz; + pair->Alpha.Arg[i].Swizzle = rc_init_swizzle(swz, 1); pair->Alpha.Arg[i].Abs = inst->SrcReg[i].Abs; pair->Alpha.Arg[i].Negate = !!(inst->SrcReg[i].Negate & RC_MASK_W); } @@ -302,12 +304,6 @@ static void check_opcode_support(struct r300_fragment_program_compiler *c, const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode); if (opcode->HasDstReg) { - if (inst->DstReg.RelAddr) { - rc_error(&c->Base, "Fragment program does not support relative addressing " - "of destination operands.\n"); - return; - } - if (inst->SaturateMode == RC_SATURATE_MINUS_PLUS_ONE) { rc_error(&c->Base, "Fragment program does not support signed Saturate.\n"); return; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h index df6c94b35f9..a07f6b63c6e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h @@ -56,11 +56,7 @@ struct rc_src_register { struct rc_dst_register { unsigned int File:3; - - /** Negative values may be used for relative addressing. */ - signed int Index:(RC_REGISTER_INDEX_BITS+1); - unsigned int RelAddr:1; - + unsigned int Index:RC_REGISTER_INDEX_BITS; unsigned int WriteMask:4; }; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c index c8063171b81..9fc991166a3 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c @@ -91,7 +91,6 @@ static struct rc_dst_register dstregtmpmask(int index, int mask) dst.File = RC_FILE_TEMPORARY; dst.Index = index; dst.WriteMask = mask; - dst.RelAddr = 0; return dst; } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c index 5905d26e521..68874795b8a 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c @@ -211,27 +211,9 @@ struct rc_pair_instruction_source * rc_pair_get_src( struct rc_pair_instruction * pair_inst, struct rc_pair_instruction_arg * arg) { - unsigned int i, type; - unsigned int channels = 0; + unsigned int type; - for(i = 0; i < 3; i++) { - if (arg == pair_inst->RGB.Arg + i) { - channels = 3; - break; - } - } - - if (channels == 0) { - for (i = 0; i < 3; i++) { - if (arg == pair_inst->Alpha.Arg + i) { - channels = 1; - break; - } - } - } - - assert(channels > 0); - type = rc_source_type_swz(arg->Swizzle, channels); + type = rc_source_type_swz(arg->Swizzle); if (type & RC_SOURCE_RGB) { return &pair_inst->RGB.Src[arg->Source]; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h index ccf7a0070cd..6708b16d29a 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h @@ -63,7 +63,7 @@ struct rc_pair_instruction_source { struct rc_pair_instruction_arg { unsigned int Source:2; - unsigned int Swizzle:9; + unsigned int Swizzle:12; unsigned int Abs:1; unsigned int Negate:1; }; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c index ae13f6742f8..390d1319460 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c @@ -110,7 +110,7 @@ static void rc_print_mask(FILE * f, unsigned int mask) static void rc_print_dst_register(FILE * f, struct rc_dst_register dst) { - rc_print_register(f, dst.File, dst.Index, dst.RelAddr); + rc_print_register(f, dst.File, dst.Index, 0); if (dst.WriteMask != RC_MASK_XYZW) { fprintf(f, "."); rc_print_mask(f, dst.WriteMask); @@ -379,7 +379,7 @@ static void rc_print_pair_instruction(FILE * f, struct rc_instruction * fullinst else fprintf(f,"%d", inst->Alpha.Arg[arg].Source); fprintf(f,".%c%s", - rc_swizzle_char(inst->Alpha.Arg[arg].Swizzle), abs); + rc_swizzle_char(GET_SWZ(inst->Alpha.Arg[arg].Swizzle, 0)), abs); } fprintf(f, "\n"); } diff --git a/src/mesa/drivers/dri/r300/r300_blit.c b/src/mesa/drivers/dri/r300/r300_blit.c index 9fd8e8fde5f..14e60866d93 100644 --- a/src/mesa/drivers/dri/r300/r300_blit.c +++ b/src/mesa/drivers/dri/r300/r300_blit.c @@ -63,7 +63,6 @@ static void create_vertex_program(struct r300_context *r300) inst->U.I.Opcode = RC_OPCODE_MOV; inst->U.I.DstReg.File = RC_FILE_OUTPUT; inst->U.I.DstReg.Index = VERT_RESULT_HPOS; - inst->U.I.DstReg.RelAddr = 0; inst->U.I.DstReg.WriteMask = RC_MASK_XYZW; inst->U.I.SrcReg[0].Abs = 0; inst->U.I.SrcReg[0].File = RC_FILE_INPUT; @@ -76,7 +75,6 @@ static void create_vertex_program(struct r300_context *r300) inst->U.I.Opcode = RC_OPCODE_MOV; inst->U.I.DstReg.File = RC_FILE_OUTPUT; inst->U.I.DstReg.Index = VERT_RESULT_TEX0; - inst->U.I.DstReg.RelAddr = 0; inst->U.I.DstReg.WriteMask = RC_MASK_XYZW; inst->U.I.SrcReg[0].Abs = 0; inst->U.I.SrcReg[0].File = RC_FILE_INPUT; @@ -131,6 +129,7 @@ static void create_fragment_program(struct r300_context *r300) compiler.Base.max_temp_regs = (compiler.Base.is_r500) ? 128 : 32; compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32; compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64; + compiler.Base.max_tex_insts = compiler.Base.is_r500 ? 512 : 32; compiler.code = &r300->blit.fp_code; compiler.AllocateHwInputs = fp_allocate_hw_inputs; diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_common.c b/src/mesa/drivers/dri/r300/r300_fragprog_common.c index 4e457b51eba..a0a26f1b38d 100644 --- a/src/mesa/drivers/dri/r300/r300_fragprog_common.c +++ b/src/mesa/drivers/dri/r300/r300_fragprog_common.c @@ -226,6 +226,7 @@ static void translate_fragment_program(struct gl_context *ctx, struct r300_fragm compiler.Base.max_temp_regs = (compiler.Base.is_r500) ? 128 : 32; compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32; compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64; + compiler.Base.max_tex_insts = compiler.Base.is_r500 ? 512 : 32; compiler.OutputDepth = FRAG_RESULT_DEPTH; memset(compiler.OutputColor, 0, 4 * sizeof(unsigned)); compiler.OutputColor[0] = FRAG_RESULT_COLOR; diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h index f7705b0f6fe..2b9d85fae8b 100644 --- a/src/mesa/drivers/dri/r300/r300_reg.h +++ b/src/mesa/drivers/dri/r300/r300_reg.h @@ -1658,6 +1658,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 13) # define R300_PFS_CNTL_TEX_END_SHIFT 18 # define R300_PFS_CNTL_TEX_END_MASK (31 << 18) +# define R400_PFS_CNTL_TEX_OFFSET_MSB_SHIFT 24 +# define R400_PFS_CNTL_TEX_OFFSET_MSB_MASK (0xf << 24) +# define R400_PFS_CNTL_TEX_END_MSB_SHIFT 28 +# define R400_PFS_CNTL_TEX_END_MSB_MASK (0xf << 28) /* gap */ @@ -1682,6 +1686,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TEX_SIZE_MASK (31 << 17) # define R300_RGBA_OUT (1 << 22) # define R300_W_OUT (1 << 23) +# define R400_TEX_START_MSB_SHIFT 24 +# define R400_TEX_START_MSG_MASK (0xf << 24) +# define R400_TEX_SIZE_MSB_SHIFT 28 +# define R400_TEX_SIZE_MSG_MASK (0xf << 28) /* TEX * As far as I can tell, texture instructions cannot write into output @@ -1702,6 +1710,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TEX_OP_TXP 3 # define R300_TEX_OP_TXB 4 # define R300_TEX_INST_MASK (7 << 15) +# define R400_SRC_ADDR_EXT_BIT (1 << 19) +# define R400_DST_ADDR_EXT_BIT (1 << 20) /* Output format from the unfied shader */ #define R300_US_OUT_FMT 0x46A4 @@ -1979,6 +1989,40 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_ALU_OUTA_CLAMP (1 << 30) /* END: Fragment program instruction set */ +/* R4xx extended fragment shader registers. */ +#define R400_US_ALU_EXT_ADDR_0 0x4ac0 /* up to 63 (0x4bbc) */ +# define R400_ADDR_EXT_RGB_MSB_BIT(x) (1 << (x)) +# define R400_ADDRD_EXT_RGB_MSB_BIT 0x08 +# define R400_ADDR_EXT_A_MSB_BIT(x) (1 << ((x) + 4)) +# define R400_ADDRD_EXT_A_MSB_BIT 0x80 + +#define R400_US_CODE_BANK 0x46b8 +# define R400_BANK_SHIFT 0 +# define R400_BANK_MASK 0xf +# define R400_R390_MODE_ENABLE (1 << 4) +#define R400_US_CODE_EXT 0x46bc +# define R400_ALU_OFFSET_MSB_SHIFT 0 +# define R400_ALU_OFFSET_MSB_MASK (0x7 << 0) +# define R400_ALU_SIZE_MSB_SHIFT 3 +# define R400_ALU_SIZE_MSB_MASK (0x7 << 3) +# define R400_ALU_START0_MSB_SHIFT 6 +# define R400_ALU_START0_MSB_MASK (0x7 << 6) +# define R400_ALU_SIZE0_MSB_SHIFT 9 +# define R400_ALU_SIZE0_MSB_MASK (0x7 << 9) +# define R400_ALU_START1_MSB_SHIFT 12 +# define R400_ALU_START1_MSB_MASK (0x7 << 12) +# define R400_ALU_SIZE1_MSB_SHIFT 15 +# define R400_ALU_SIZE1_MSB_MASK (0x7 << 15) +# define R400_ALU_START2_MSB_SHIFT 18 +# define R400_ALU_START2_MSB_MASK (0x7 << 18) +# define R400_ALU_SIZE2_MSB_SHIFT 21 +# define R400_ALU_SIZE2_MSB_MASK (0x7 << 21) +# define R400_ALU_START3_MSB_SHIFT 24 +# define R400_ALU_START3_MSB_MASK (0x7 << 24) +# define R400_ALU_SIZE3_MSB_SHIFT 27 +# define R400_ALU_SIZE3_MSB_MASK (0x7 << 27) +/* END: R4xx extended fragment shader registers. */ + /* Fog: Fog Blending Enable */ #define R300_FG_FOG_BLEND 0x4bc0 # define R300_FG_FOG_BLEND_DISABLE (0 << 0) diff --git a/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c b/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c index 471a3723cb9..232603ece59 100644 --- a/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c +++ b/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c @@ -128,7 +128,6 @@ static void translate_dstreg(struct rc_dst_register * dest, struct prog_dst_regi { dest->File = translate_register_file(src->File); dest->Index = src->Index; - dest->RelAddr = src->RelAddr; dest->WriteMask = src->WriteMask; } diff --git a/src/mesa/drivers/dri/r600/evergreen_fragprog.c b/src/mesa/drivers/dri/r600/evergreen_fragprog.c index cfb923efdd5..e527c379b62 100644 --- a/src/mesa/drivers/dri/r600/evergreen_fragprog.c +++ b/src/mesa/drivers/dri/r600/evergreen_fragprog.c @@ -624,10 +624,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << VERT_RESULT_COL0; @@ -663,10 +660,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } for(i=0; i<8; i++) @@ -694,10 +688,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << FRAG_ATTRIB_PNTC; if(mesa_fp->Base.InputsRead & unBit) @@ -706,10 +697,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, PT_SPRITE_TEX_bit); } @@ -725,10 +713,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx) SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } } diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.c b/src/mesa/drivers/dri/r600/r700_fragprog.c index 0323e32d705..40494cd6af0 100644 --- a/src/mesa/drivers/dri/r600/r700_fragprog.c +++ b/src/mesa/drivers/dri/r600/r700_fragprog.c @@ -657,10 +657,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << VERT_RESULT_COL0; @@ -696,10 +693,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } for(i=0; i<8; i++) @@ -728,10 +722,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } unBit = 1 << FRAG_ATTRIB_PNTC; if(mesa_fp->Base.InputsRead & unBit) @@ -759,10 +750,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx) SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, SEMANTIC_shift, SEMANTIC_mask); - if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) - SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); - else - CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); } } diff --git a/src/mesa/drivers/dri/radeon/radeon_chipset.h b/src/mesa/drivers/dri/radeon/radeon_chipset.h index 399052cbcbd..bd6f1c79504 100644 --- a/src/mesa/drivers/dri/radeon/radeon_chipset.h +++ b/src/mesa/drivers/dri/radeon/radeon_chipset.h @@ -34,7 +34,6 @@ #define PCI_CHIP_RV350_AV 0x4156 #define PCI_CHIP_RS250_4237 0x4237 #define PCI_CHIP_R200_BB 0x4242 -#define PCI_CHIP_R200_BC 0x4243 #define PCI_CHIP_RS100_4336 0x4336 #define PCI_CHIP_RS200_4337 0x4337 #define PCI_CHIP_RS250_4437 0x4437 diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c index 7361adffcf7..0d73c0e3b1b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common.c +++ b/src/mesa/drivers/dri/radeon/radeon_common.c @@ -905,7 +905,7 @@ void radeon_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GL if (!driContext->driScreenPriv->dri2.enabled) return; - if (!radeon->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) { + if (ctx->DrawBuffer->Name == 0) { if (radeon->is_front_buffer_rendering) { ctx->Driver.Flush(ctx); } diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c index 819d9dd5750..405aecb19ec 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c @@ -204,7 +204,7 @@ GLboolean radeonInitContext(radeonContextPtr radeon, shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx; else shareCtx = NULL; - radeon->glCtx = _mesa_create_context(glVisual, shareCtx, + radeon->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx, functions, (void *)radeon); if (!radeon->glCtx) return GL_FALSE; @@ -212,8 +212,6 @@ GLboolean radeonInitContext(radeonContextPtr radeon, ctx = radeon->glCtx; driContextPriv->driverPrivate = radeon; - meta_init_metaops(ctx, &radeon->meta); - _mesa_meta_init(ctx); /* DRI fields */ @@ -320,7 +318,6 @@ void radeonDestroyContext(__DRIcontext *driContextPriv ) radeonFreeDmaRegions(radeon); radeonReleaseArrays(radeon->glCtx, ~0); - meta_destroy_metaops(&radeon->meta); if (radeon->vtbl.free_context) radeon->vtbl.free_context(radeon->glCtx); _swsetup_DestroyContext( radeon->glCtx ); diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index c62913afd0c..3895ab8c4d8 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -14,7 +14,6 @@ #include "dri_util.h" #include "tnl/t_vertex.h" -#include "dri_metaops.h" struct radeon_context; #include "radeon_bocs_wrapper.h" @@ -509,8 +508,6 @@ struct radeon_context { */ GLboolean is_front_buffer_reading; - struct dri_metaops meta; - struct { struct radeon_query_object *current; struct radeon_state_atom queryobj; diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c index 6656d391e09..d3c9257fb66 100644 --- a/src/mesa/drivers/dri/radeon/radeon_fbo.c +++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c @@ -485,6 +485,8 @@ radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb, case MESA_FORMAT_S8_Z24: rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT; break; + default: + _mesa_problem(ctx, "Unexpected texture format in radeon_update_wrapper()"); } rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c index a35fcfe9d7f..56c5959b0aa 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.c +++ b/src/mesa/drivers/dri/radeon/radeon_screen.c @@ -628,7 +628,6 @@ static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id) break; case PCI_CHIP_R200_BB: - case PCI_CHIP_R200_BC: case PCI_CHIP_R200_QH: case PCI_CHIP_R200_QL: case PCI_CHIP_R200_QM: diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c index 92fb4f44884..681ed9aae34 100644 --- a/src/mesa/drivers/dri/savage/savage_xmesa.c +++ b/src/mesa/drivers/dri/savage/savage_xmesa.c @@ -314,7 +314,7 @@ savageCreateContext( gl_api api, shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx; else shareCtx = NULL; - ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa); + ctx = _mesa_create_context(api, mesaVis, shareCtx, &functions, imesa); if (!ctx) { free(imesa); return GL_FALSE; diff --git a/src/mesa/drivers/dri/sis/sis_context.c b/src/mesa/drivers/dri/sis/sis_context.c index c5a9fdfb2a0..26ecfc463ca 100644 --- a/src/mesa/drivers/dri/sis/sis_context.c +++ b/src/mesa/drivers/dri/sis/sis_context.c @@ -186,7 +186,7 @@ sisCreateContext( gl_api api, shareCtx = ((sisContextPtr)sharedContextPrivate)->glCtx; else shareCtx = NULL; - smesa->glCtx = _mesa_create_context( glVisual, shareCtx, + smesa->glCtx = _mesa_create_context( API_OPENGL, glVisual, shareCtx, &functions, (void *) smesa); if (!smesa->glCtx) { FREE(smesa); diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c index c7940e9c0da..719b406ec05 100644 --- a/src/mesa/drivers/dri/swrast/swrast.c +++ b/src/mesa/drivers/dri/swrast/swrast.c @@ -561,6 +561,60 @@ swrast_init_driver_functions(struct dd_function_table *driver) driver->ChooseTextureFormat = swrastChooseTextureFormat; } +static const char *es2_extensions[] = { + /* Used by mesa internally (cf all_mesa_extensions in ../common/utils.c) */ + "GL_ARB_draw_buffers", + "GL_ARB_multisample", + "GL_ARB_texture_compression", + "GL_ARB_transpose_matrix", + "GL_ARB_vertex_buffer_object", + "GL_ARB_window_pos", + "GL_EXT_blend_func_separate", + "GL_EXT_compiled_vertex_array", + "GL_EXT_framebuffer_blit", + "GL_EXT_multi_draw_arrays", + "GL_EXT_polygon_offset", + "GL_EXT_texture_object", + "GL_EXT_vertex_array", + "GL_IBM_multimode_draw_arrays", + "GL_MESA_window_pos", + "GL_NV_vertex_program", + + /* Required by GLES2 */ + "GL_ARB_fragment_program", + "GL_ARB_fragment_shader", + "GL_ARB_multitexture", + "GL_ARB_shader_objects", + "GL_ARB_texture_cube_map", + "GL_ARB_texture_mirrored_repeat", + "GL_ARB_texture_non_power_of_two", + "GL_ARB_vertex_shader", + "GL_EXT_blend_color", + "GL_EXT_blend_equation_separate", + "GL_EXT_blend_minmax", + "GL_EXT_blend_subtract", + "GL_EXT_stencil_wrap", + + /* Optional GLES2 */ + "GL_ARB_framebuffer_object", + "GL_EXT_texture_filter_anisotropic", + "GL_ARB_depth_texture", + "GL_EXT_packed_depth_stencil", + "GL_EXT_framebuffer_object", + NULL, +}; + +static void +InitExtensionsES2(struct gl_context *ctx) +{ + int i; + + /* Can't use driInitExtensions() since it uses extensions from + * main/remap_helper.h when called the first time. */ + + for (i = 0; es2_extensions[i]; i++) + _mesa_enable_extension(ctx, es2_extensions[i]); +} /** * Context-related functions. @@ -597,7 +651,7 @@ dri_create_context(gl_api api, mesaCtx = &ctx->Base; /* basic context setup */ - if (!_mesa_initialize_context(mesaCtx, visual, sharedCtx, &functions, (void *) cPriv)) { + if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) { goto context_fail; } @@ -617,16 +671,29 @@ dri_create_context(gl_api api, tnl->Driver.RunPipeline = _tnl_run_pipeline; } - _mesa_enable_sw_extensions(mesaCtx); - _mesa_enable_1_3_extensions(mesaCtx); - _mesa_enable_1_4_extensions(mesaCtx); - _mesa_enable_1_5_extensions(mesaCtx); - _mesa_enable_2_0_extensions(mesaCtx); - _mesa_enable_2_1_extensions(mesaCtx); - _mesa_meta_init(mesaCtx); + _mesa_enable_sw_extensions(mesaCtx); - driInitExtensions( mesaCtx, NULL, GL_FALSE ); + switch (api) { + case API_OPENGL: + _mesa_enable_1_3_extensions(mesaCtx); + _mesa_enable_1_4_extensions(mesaCtx); + _mesa_enable_1_5_extensions(mesaCtx); + _mesa_enable_2_0_extensions(mesaCtx); + _mesa_enable_2_1_extensions(mesaCtx); + + driInitExtensions( mesaCtx, NULL, GL_FALSE ); + break; + case API_OPENGLES: + _mesa_enable_1_3_extensions(mesaCtx); + _mesa_enable_1_4_extensions(mesaCtx); + _mesa_enable_1_5_extensions(mesaCtx); + + break; + case API_OPENGLES2: + InitExtensionsES2( mesaCtx); + break; + } return GL_TRUE; diff --git a/src/mesa/drivers/dri/tdfx/tdfx_context.c b/src/mesa/drivers/dri/tdfx/tdfx_context.c index 63dfa5ae746..ad151359e67 100644 --- a/src/mesa/drivers/dri/tdfx/tdfx_context.c +++ b/src/mesa/drivers/dri/tdfx/tdfx_context.c @@ -194,7 +194,7 @@ GLboolean tdfxCreateContext( gl_api api, else shareCtx = NULL; - fxMesa->glCtx = _mesa_create_context(mesaVis, shareCtx, + fxMesa->glCtx = _mesa_create_context(api, mesaVis, shareCtx, &functions, (void *) fxMesa); if (!fxMesa->glCtx) { FREE(fxMesa); diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c index 963609bde4a..77d7116611a 100644 --- a/src/mesa/drivers/dri/unichrome/via_context.c +++ b/src/mesa/drivers/dri/unichrome/via_context.c @@ -542,7 +542,7 @@ viaCreateContext(gl_api api, else shareCtx = NULL; - vmesa->glCtx = _mesa_create_context(visual, shareCtx, &functions, + vmesa->glCtx = _mesa_create_context(API_OPENGL, visual, shareCtx, &functions, (void*) vmesa); vmesa->shareCtx = shareCtx; diff --git a/src/mesa/drivers/fbdev/glfbdev.c b/src/mesa/drivers/fbdev/glfbdev.c index 5195bca97fa..1e0ac4c7a1f 100644 --- a/src/mesa/drivers/fbdev/glfbdev.c +++ b/src/mesa/drivers/fbdev/glfbdev.c @@ -722,7 +722,7 @@ glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share ) functions.GetBufferSize = get_buffer_size; functions.Viewport = viewport; - if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual, + if (!_mesa_initialize_context(&ctx->glcontext, API_OPENGL, &visual->glvisual, share ? &share->glcontext : NULL, &functions, (void *) ctx)) { free(ctx); diff --git a/src/mesa/drivers/osmesa/Makefile b/src/mesa/drivers/osmesa/Makefile index 50dd4526e19..39ab09af805 100644 --- a/src/mesa/drivers/osmesa/Makefile +++ b/src/mesa/drivers/osmesa/Makefile @@ -40,7 +40,7 @@ $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OBJECTS) $(CORE_MESA) -major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \ -install $(TOP)/$(LIB_DIR) -cplusplus $(MKLIB_OPTIONS) \ -id $(INSTALL_LIB_DIR)/lib$(OSMESA_LIB).$(MESA_MAJOR).dylib \ - $(OSMESA_LIB_DEPS) $(OBJECTS) $(CORE_MESA) $(TALLOC_LIBS) + $(OSMESA_LIB_DEPS) $(OBJECTS) $(CORE_MESA) diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c index e1f0c69bacf..98f01fe057e 100644 --- a/src/mesa/drivers/osmesa/osmesa.c +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -1155,6 +1155,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, functions.GetBufferSize = NULL; if (!_mesa_initialize_context(&osmesa->mesa, + API_OPENGL, osmesa->gl_visual, sharelist ? &sharelist->mesa : (struct gl_context *) NULL, diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c index 833e2526f3c..4a8b1b283d5 100644 --- a/src/mesa/drivers/windows/gdi/wmesa.c +++ b/src/mesa/drivers/windows/gdi/wmesa.c @@ -1479,7 +1479,8 @@ WMesaContext WMesaCreateContext(HDC hDC, /* initialize the Mesa context data */ ctx = &c->gl_ctx; - _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c); + _mesa_initialize_context(ctx, API_OPENGL, visual, + NULL, &functions, (void *)c); /* visual no longer needed - it was copied by _mesa_initialize_context() */ _mesa_destroy_visual(visual); diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.c b/src/mesa/drivers/windows/gldirect/dglcontext.c index 10ea0578506..9aedd2e3c4d 100644 --- a/src/mesa/drivers/windows/gldirect/dglcontext.c +++ b/src/mesa/drivers/windows/gldirect/dglcontext.c @@ -1414,7 +1414,7 @@ SkipPrimaryCreate: } #ifdef _USE_GLD3_WGL - lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE); + lpCtx->glCtx = _mesa_create_context(API_OPENGL, lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE); #else // Create the Mesa context lpCtx->glCtx = (*mesaFuncs.gl_create_context)( diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c index 1c43a38557d..1b070f0a11e 100644 --- a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c @@ -944,7 +944,6 @@ void gld_update_state_DX7( // Stubs for future use. /* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_STATE(_NEW_ACCUM); _GLD_TEST_STATE(_NEW_EVAL); _GLD_TEST_STATE(_NEW_HINT); _GLD_TEST_STATE(_NEW_LINE); @@ -967,7 +966,6 @@ void gld_update_state_DX7( } _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c index 7fc50004de8..d66318e1149 100644 --- a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c @@ -62,7 +62,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c index c4c2e0b5676..4c272c95d6c 100644 --- a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c @@ -924,7 +924,6 @@ void gld_update_state_DX8( // Stubs for future use. /* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_STATE(_NEW_ACCUM); _GLD_TEST_STATE(_NEW_EVAL); _GLD_TEST_STATE(_NEW_HINT); _GLD_TEST_STATE(_NEW_LINE); @@ -947,7 +946,6 @@ void gld_update_state_DX8( } _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c index 5b9dac09c6d..a2c5d87ecd5 100644 --- a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c @@ -62,7 +62,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c index aab70852016..171585dcf81 100644 --- a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c @@ -955,7 +955,6 @@ void gld_update_state_DX9( // Stubs for future use. /* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_STATE(_NEW_ACCUM); _GLD_TEST_STATE(_NEW_EVAL); _GLD_TEST_STATE(_NEW_HINT); _GLD_TEST_STATE(_NEW_LINE); @@ -977,7 +976,6 @@ void gld_update_state_DX9( } _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); - _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c index 99edd26e9d2..65a00ae1b59 100644 --- a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c @@ -62,7 +62,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c index 7a26df8071e..bc66ec79888 100644 --- a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c +++ b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c @@ -61,7 +61,6 @@ #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" -#include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c index 577e27d4da3..48657b44be1 100644 --- a/src/mesa/drivers/x11/fakeglx.c +++ b/src/mesa/drivers/x11/fakeglx.c @@ -1292,7 +1292,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, /* deallocate unused windows/buffers */ #if 0 - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); #endif xmvis = find_glx_visual( dpy, visinfo ); @@ -1533,7 +1533,7 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) MakeCurrent_PrevDrawBuffer = 0; MakeCurrent_PrevReadBuffer = 0; XMesaDestroyContext( glxCtx->xmesaContext ); - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); free(glxCtx); } @@ -2327,7 +2327,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, return 0; /* deallocate unused windows/buffers */ - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx ? shareCtx->xmesaContext : NULL); @@ -2542,7 +2542,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re return 0; /* deallocate unused windows/buffers */ - XMesaGarbageCollect(); + XMesaGarbageCollect(dpy); glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx ? shareCtx->xmesaContext : NULL); diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index b5eabadf486..aad902d1eda 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -1398,7 +1398,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) /* initialize with default driver functions, then plug in XMesa funcs */ _mesa_init_driver_functions(&functions); xmesa_init_driver_functions(v, &functions); - if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual, + if (!_mesa_initialize_context(mesaCtx, API_OPENGL, &v->mesa_visual, share_list ? &(share_list->mesa) : (struct gl_context *) NULL, &functions, (void *) c)) { free(c); @@ -2064,12 +2064,12 @@ void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) * Look for XMesaBuffers whose X window has been destroyed. * Deallocate any such XMesaBuffers. */ -void XMesaGarbageCollect( void ) +void XMesaGarbageCollect( XMesaDisplay* dpy ) { XMesaBuffer b, next; for (b=XMesaBufferList; b; b=next) { next = b->Next; - if (b->display && b->frontxrb->drawable && b->type == WINDOW) { + if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) { XSync(b->display, False); if (!window_exists( b->display, b->frontxrb->drawable )) { /* found a dead window, free the ancillary info */ diff --git a/src/mesa/drivers/x11/xmesa.h b/src/mesa/drivers/x11/xmesa.h index 98737fab248..347394e0a26 100644 --- a/src/mesa/drivers/x11/xmesa.h +++ b/src/mesa/drivers/x11/xmesa.h @@ -324,7 +324,7 @@ extern const char *XMesaGetString( XMesaContext c, int name ); * * New in Mesa 2.3. */ -extern void XMesaGarbageCollect( void ); +extern void XMesaGarbageCollect( XMesaDisplay* dpy ); diff --git a/src/mesa/main/APIspec.xml b/src/mesa/main/APIspec.xml index 50446a9093a..0f82d0a38e1 100644 --- a/src/mesa/main/APIspec.xml +++ b/src/mesa/main/APIspec.xml @@ -379,15 +379,68 @@ <value name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES" category="OES_texture_cube_map"/> </desc> - <desc name="internalFormat" error="GL_INVALID_VALUE"> + <desc name="internalFormat"> <value name="GL_ALPHA"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_ALPHA"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_RGB"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_RGB"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_RGBA"/> - <value name="GL_BGRA_EXT"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_RGBA"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_LUMINANCE"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_LUMINANCE"/> + </desc> + </desc> + + <desc name="internalFormat"> <value name="GL_LUMINANCE_ALPHA"/> - <value name="GL_DEPTH_COMPONENT" category="OES_depth_texture"/> - <value name="GL_DEPTH_STENCIL_OES" category="OES_packed_depth_stencil"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_LUMINANCE_ALPHA"/> + </desc> + </desc> + + <desc name="internalFormat" category="OES_depth_texture"> + <value name="GL_DEPTH_COMPONENT"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_DEPTH_COMPONENT"/> + </desc> + </desc> + + <desc name="internalFormat" category="OES_packed_depth_stencil"> + <value name="GL_DEPTH_STENCIL_OES"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_DEPTH_STENCIL_OES"/> + </desc> + </desc> + + <desc name="internalFormat" category="EXT_texture_format_BGRA8888"> + <value name="GL_BGRA_EXT"/> + + <desc name="format" error="GL_INVALID_VALUE"> + <value name="GL_BGRA_EXT"/> + </desc> </desc> <desc name="border" error="GL_INVALID_VALUE"> diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c index 940f398f023..6a83930a13d 100644 --- a/src/mesa/main/accum.c +++ b/src/mesa/main/accum.c @@ -51,7 +51,6 @@ _mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) if (TEST_EQ_4V(tmp, ctx->Accum.ClearColor)) return; - FLUSH_VERTICES(ctx, _NEW_ACCUM); COPY_4FV( ctx->Accum.ClearColor, tmp ); } diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index 9e9728c2c62..46010223370 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -234,7 +234,7 @@ _mesa_initialize_array_object( struct gl_context *ctx, init_array(ctx, &obj->Weight, 1, GL_FLOAT); init_array(ctx, &obj->Normal, 3, GL_FLOAT); init_array(ctx, &obj->Color, 4, GL_FLOAT); - init_array(ctx, &obj->SecondaryColor, 4, GL_FLOAT); + init_array(ctx, &obj->SecondaryColor, 3, GL_FLOAT); init_array(ctx, &obj->FogCoord, 1, GL_FLOAT); init_array(ctx, &obj->Index, 1, GL_FLOAT); for (i = 0; i < Elements(obj->TexCoord); i++) { diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c index 43e2f7f8617..c74a168036a 100644 --- a/src/mesa/main/blend.c +++ b/src/mesa/main/blend.c @@ -317,7 +317,7 @@ _mesa_BlendEquation( GLenum mode ) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBlendEquation %s\n", + _mesa_debug(ctx, "glBlendEquation(%s)\n", _mesa_lookup_enum_by_nr(mode)); if (!legal_blend_equation(ctx, mode, GL_FALSE)) { @@ -398,7 +398,7 @@ _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n", + _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n", _mesa_lookup_enum_by_nr(modeRGB), _mesa_lookup_enum_by_nr(modeA)); @@ -454,7 +454,7 @@ _mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBlendEquationSeparatei %u, %s %s\n", buf, + _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf, _mesa_lookup_enum_by_nr(modeRGB), _mesa_lookup_enum_by_nr(modeA)); @@ -545,6 +545,10 @@ _mesa_AlphaFunc( GLenum func, GLclampf ref ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n", + _mesa_lookup_enum_by_nr(func), ref); + switch (func) { case GL_NEVER: case GL_LESS: @@ -590,6 +594,9 @@ _mesa_LogicOp( GLenum opcode ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode)); + switch (opcode) { case GL_CLEAR: case GL_SET: @@ -664,7 +671,8 @@ _mesa_ColorMask( GLboolean red, GLboolean green, ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha); + _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n", + red, green, blue, alpha); /* Shouldn't have any information about channel depth in core mesa * -- should probably store these as the native booleans: diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 1f9a5212c04..75afae0add1 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -970,6 +970,10 @@ _mesa_BindBufferARB(GLenum target, GLuint buffer) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBindBuffer(%s, %u)\n", + _mesa_lookup_enum_by_nr(target), buffer); + bind_buffer_object(ctx, target, buffer); } @@ -1064,6 +1068,9 @@ _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGenBuffers(%d)\n", n); + if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); return; @@ -1121,6 +1128,12 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, struct gl_buffer_object *bufObj; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n", + _mesa_lookup_enum_by_nr(target), + (long int) size, data, + _mesa_lookup_enum_by_nr(usage)); + if (size < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); return; diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index e017939a45c..a942314552e 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -886,12 +886,12 @@ _mesa_alloc_dispatch_table(int size) * \param driverContext pointer to driver-specific context data */ GLboolean -_mesa_initialize_context_for_api(struct gl_context *ctx, - gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) +_mesa_initialize_context(struct gl_context *ctx, + gl_api api, + const struct gl_config *visual, + struct gl_context *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext) { struct gl_shared_state *shared; int i; @@ -1029,25 +1029,6 @@ _mesa_initialize_context_for_api(struct gl_context *ctx, /** - * Initialize an OpenGL context. - */ -GLboolean -_mesa_initialize_context(struct gl_context *ctx, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) -{ - return _mesa_initialize_context_for_api(ctx, - API_OPENGL, - visual, - share_list, - driverFunctions, - driverContext); -} - - -/** * Allocate and initialize a struct gl_context structure. * Note that the driver needs to pass in its dd_function_table here since * we need to at least call driverFunctions->NewTextureObject to initialize @@ -1063,11 +1044,11 @@ _mesa_initialize_context(struct gl_context *ctx, * \return pointer to a new __struct gl_contextRec or NULL if error. */ struct gl_context * -_mesa_create_context_for_api(gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) +_mesa_create_context(gl_api api, + const struct gl_config *visual, + struct gl_context *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext) { struct gl_context *ctx; @@ -1078,8 +1059,8 @@ _mesa_create_context_for_api(gl_api api, if (!ctx) return NULL; - if (_mesa_initialize_context_for_api(ctx, api, visual, share_list, - driverFunctions, driverContext)) { + if (_mesa_initialize_context(ctx, api, visual, share_list, + driverFunctions, driverContext)) { return ctx; } else { @@ -1090,22 +1071,6 @@ _mesa_create_context_for_api(gl_api api, /** - * Create an OpenGL context. - */ -struct gl_context * -_mesa_create_context(const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext) -{ - return _mesa_create_context_for_api(API_OPENGL, visual, - share_list, - driverFunctions, - driverContext); -} - - -/** * Free the data associated with the given context. * * But doesn't free the struct gl_context struct itself. diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h index 8fb9b4c6b7a..4e391dde494 100644 --- a/src/mesa/main/context.h +++ b/src/mesa/main/context.h @@ -99,33 +99,20 @@ _mesa_destroy_visual( struct gl_config *vis ); /** \name Context-related functions */ /*@{*/ -extern struct gl_context * -_mesa_create_context( const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext ); - extern GLboolean _mesa_initialize_context( struct gl_context *ctx, + gl_api api, const struct gl_config *visual, struct gl_context *share_list, const struct dd_function_table *driverFunctions, void *driverContext ); extern struct gl_context * -_mesa_create_context_for_api(gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext); - -extern GLboolean -_mesa_initialize_context_for_api(struct gl_context *ctx, - gl_api api, - const struct gl_config *visual, - struct gl_context *share_list, - const struct dd_function_table *driverFunctions, - void *driverContext); +_mesa_create_context(gl_api api, + const struct gl_config *visual, + struct gl_context *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext); extern void _mesa_free_context_data( struct gl_context *ctx ); diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c index a6a909b48ce..78881668e49 100644 --- a/src/mesa/main/debug.c +++ b/src/mesa/main/debug.c @@ -65,13 +65,12 @@ void _mesa_print_state( const char *msg, GLuint state ) { _mesa_debug(NULL, - "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", msg, state, (state & _NEW_MODELVIEW) ? "ctx->ModelView, " : "", (state & _NEW_PROJECTION) ? "ctx->Projection, " : "", (state & _NEW_TEXTURE_MATRIX) ? "ctx->TextureMatrix, " : "", - (state & _NEW_ACCUM) ? "ctx->Accum, " : "", (state & _NEW_COLOR) ? "ctx->Color, " : "", (state & _NEW_DEPTH) ? "ctx->Depth, " : "", (state & _NEW_EVAL) ? "ctx->Eval/EvalMap, " : "", @@ -214,16 +213,6 @@ void _mesa_init_debug( struct gl_context *ctx ) { char *c; - - /* Dither disable */ - ctx->NoDither = _mesa_getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE; - if (ctx->NoDither) { - if (_mesa_getenv("MESA_DEBUG")) { - _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n"); - } - ctx->Color.DitherFlag = GL_FALSE; - } - c = _mesa_getenv("MESA_DEBUG"); if (c) add_debug_flags(c); @@ -307,8 +296,8 @@ write_texture_image(struct gl_texture_object *texObj, /** * Write renderbuffer image to a ppm file. */ -static void -write_renderbuffer_image(const struct gl_renderbuffer *rb) +void +_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb) { GET_CURRENT_CONTEXT(ctx); GLubyte *buffer; @@ -325,6 +314,10 @@ write_renderbuffer_image(const struct gl_renderbuffer *rb) type = GL_UNSIGNED_INT_24_8; } else { + _mesa_debug(NULL, + "Unsupported BaseFormat 0x%x in " + "_mesa_write_renderbuffer_image()\n", + rb->_BaseFormat); return; } @@ -335,8 +328,12 @@ write_renderbuffer_image(const struct gl_renderbuffer *rb) /* make filename */ _mesa_snprintf(s, sizeof(s), "/tmp/renderbuffer%u.ppm", rb->Name); + _mesa_snprintf(s, sizeof(s), "C:\\renderbuffer%u.ppm", rb->Name); printf(" Writing renderbuffer image to %s\n", s); + + _mesa_debug(NULL, " Writing renderbuffer image to %s\n", s); + write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE); free(buffer); @@ -423,7 +420,7 @@ dump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage) rb->Name, rb->Width, rb->Height, _mesa_lookup_enum_by_nr(rb->InternalFormat)); if (writeImage) { - write_renderbuffer_image(rb); + _mesa_write_renderbuffer_image(rb); } } diff --git a/src/mesa/main/debug.h b/src/mesa/main/debug.h index 17aa897e8d1..4968a9f1979 100644 --- a/src/mesa/main/debug.h +++ b/src/mesa/main/debug.h @@ -64,6 +64,9 @@ extern void _mesa_init_debug( struct gl_context *ctx ); #endif extern void +_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb); + +extern void _mesa_dump_texture(GLuint texture, GLuint writeImages); extern void diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c index 0bb47731ea3..52c69a6bcd9 100644 --- a/src/mesa/main/depth.c +++ b/src/mesa/main/depth.c @@ -44,6 +44,9 @@ _mesa_ClearDepth( GLclampd depth ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glClearDepth(%f)\n", depth); + depth = CLAMP( depth, 0.0, 1.0 ); if (ctx->Depth.Clear == depth) @@ -133,6 +136,9 @@ _mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDepthBounds(%f, %f)\n", zmin, zmax); + if (zmin > zmax) { _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)"); return; diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index cdf349104a4..8e904c7787a 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -8419,8 +8419,6 @@ _mesa_CallList(GLuint list) GLboolean save_compile_flag; GET_CURRENT_CONTEXT(ctx); FLUSH_CURRENT(ctx, 0); - /* VERY IMPORTANT: Save the CompileFlag status, turn it off, */ - /* execute the display list, and restore the CompileFlag. */ if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCallList %d\n", list); @@ -8430,8 +8428,12 @@ _mesa_CallList(GLuint list) return; } -/* mesa_print_display_list( list ); */ + if (0) + mesa_print_display_list( list ); + /* VERY IMPORTANT: Save the CompileFlag status, turn it off, + * execute the display list, and restore the CompileFlag. + */ save_compile_flag = ctx->CompileFlag; if (save_compile_flag) { ctx->CompileFlag = GL_FALSE; diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index 6fda3c5665c..df4712de894 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -49,6 +49,17 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n", + width, height, + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type), + pixels, + _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + IROUND(ctx->Current.RasterPos[0]), + IROUND(ctx->Current.RasterPos[1])); + + if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); return; @@ -124,6 +135,18 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _mesa_finish(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n", + srcx, srcy, width, height, + _mesa_lookup_enum_by_nr(type), + _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer), + _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + IROUND(ctx->Current.RasterPos[0]), + IROUND(ctx->Current.RasterPos[1])); + if (width < 0 || height < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); return; diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index c4c4e1bb29d..ea3b8214c3b 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -352,9 +352,6 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) ctx->Depth.Test = state; break; case GL_DITHER: - if (ctx->NoDither) { - state = GL_FALSE; /* MESA_NO_DITHER env var */ - } if (ctx->Color.DitherFlag == state) return; FLUSH_VERTICES(ctx, _NEW_COLOR); @@ -970,9 +967,10 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) /* GL3.0 - GL_framebuffer_sRGB */ case GL_FRAMEBUFFER_SRGB_EXT: - CHECK_EXTENSION(EXT_framebuffer_sRGB, cap); - ctx->Color.sRGBEnabled = state; - break; + CHECK_EXTENSION(EXT_framebuffer_sRGB, cap); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + ctx->Color.sRGBEnabled = state; + break; default: goto invalid_enum_error; diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 113ac405073..7504b8a85db 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -89,6 +89,7 @@ static const struct extension extension_table[] = { { "GL_ARB_fragment_program_shadow", o(ARB_fragment_program_shadow), GL }, { "GL_ARB_fragment_shader", o(ARB_fragment_shader), GL }, { "GL_ARB_framebuffer_object", o(ARB_framebuffer_object), GL }, + { "GL_ARB_framebuffer_sRGB", o(EXT_framebuffer_sRGB), GL }, { "GL_ARB_half_float_pixel", o(ARB_half_float_pixel), GL }, { "GL_ARB_half_float_vertex", o(ARB_half_float_vertex), GL }, { "GL_ARB_instanced_arrays", o(ARB_instanced_arrays), GL }, @@ -249,6 +250,7 @@ static const struct extension extension_table[] = { /* Vendor extensions */ { "GL_3DFX_texture_compression_FXT1", o(TDFX_texture_compression_FXT1), GL }, + { "GL_AMD_conservative_depth", o(AMD_conservative_depth), GL }, { "GL_APPLE_client_storage", o(APPLE_client_storage), GL }, { "GL_APPLE_object_purgeable", o(APPLE_object_purgeable), GL }, { "GL_APPLE_packed_pixels", o(APPLE_packed_pixels), GL }, @@ -729,78 +731,67 @@ _mesa_extension_is_enabled( struct gl_context *ctx, const char *name ) /** - * Append string 'b' onto string 'a'. Free 'a' and return new string. - */ -static char * -append(const char *a, const char *b) -{ - const GLuint aLen = a ? strlen(a) : 0; - const GLuint bLen = b ? strlen(b) : 0; - char *s = calloc(1, aLen + bLen + 1); - if (s) { - if (a) - memcpy(s, a, aLen); - if (b) - memcpy(s + aLen, b, bLen); - s[aLen + bLen] = '\0'; - } - if (a) - free((void *) a); - return s; -} - - -/** - * Check the MESA_EXTENSION_OVERRIDE env var. - * For extension names that are recognized, turn them on. For extension - * names that are recognized and prefixed with '-', turn them off. - * Return a string of the unknown/leftover names. + * \brief Apply the \c MESA_EXTENSION_OVERRIDE environment variable. + * + * \c MESA_EXTENSION_OVERRIDE is a space-separated list of extensions to + * enable or disable. The list is processed thus: + * - Enable recognized extension names that are prefixed with '+'. + * - Disable recognized extension names that are prefixed with '-'. + * - Enable recognized extension names that are not prefixed. + * - Collect unrecognized extension names in a new string. * - * Returnd string needs to be freed. + * \return Space-separated list of unrecognized extension names (which must + * be freed). Does not return \c NULL. */ static char * get_extension_override( struct gl_context *ctx ) { - const char *envExt = _mesa_getenv("MESA_EXTENSION_OVERRIDE"); - char *extraExt = NULL; - char ext[1000]; - GLuint extLen = 0; - GLuint i; - GLboolean disableExt = GL_FALSE; - - if (!envExt) - return NULL; + const char *env_const= _mesa_getenv("MESA_EXTENSION_OVERRIDE"); + char *env; + char *ext; + char *extra_exts; + int len; + + if (env_const == NULL) { + /* Return the empty string rather than NULL. This simplifies the logic + * of client functions. */ + return calloc(1, sizeof(char)); + } - for (i = 0; ; i++) { - if (envExt[i] == '\0' || envExt[i] == ' ') { - /* terminate/process 'ext' if extLen > 0 */ - if (extLen > 0) { - assert(extLen < sizeof(ext)); - /* enable extension named by 'ext' */ - ext[extLen] = 0; - if (!set_extension(ctx, ext, !disableExt)) { - /* unknown extension name, append it to extraExt */ - if (extraExt) { - extraExt = append(extraExt, " "); - } - extraExt = append(extraExt, ext); - } - extLen = 0; - disableExt = GL_FALSE; - } - if (envExt[i] == '\0') - break; - } - else if (envExt[i] == '-') { - disableExt = GL_TRUE; + /* extra_exts: List of unrecognized extensions. */ + extra_exts = calloc(strlen(env_const), sizeof(char)); + + /* Copy env_const because strtok() is destructive. */ + env = strdup(env_const); + for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) { + int enable; + int recognized; + switch (ext[0]) { + case '+': + enable = 1; + ++ext; + break; + case '-': + enable = 0; + ++ext; + break; + default: + enable = 1; + break; } - else { - /* accumulate this non-space character */ - ext[extLen++] = envExt[i]; + recognized = set_extension(ctx, ext, enable); + if (!recognized) { + strcat(extra_exts, ext); + strcat(extra_exts, " "); } } - return extraExt; + /* Remove trailing space. */ + len = strlen(extra_exts); + if (extra_exts[len - 1] == ' ') + extra_exts[len - 1] = '\0'; + + return extra_exts; } diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index f31d8b36db8..ab6b2a9b17b 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -373,6 +373,37 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, /** + * Fallback for ctx->Driver.ValidateFramebuffer() + * Check if the renderbuffer's formats are supported by the software + * renderer. + * Drivers should probably override this. + */ +void +_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + gl_buffer_index buf; + for (buf = 0; buf < BUFFER_COUNT; buf++) { + const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer; + if (rb) { + switch (rb->_BaseFormat) { + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + case GL_RED: + case GL_RG: + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; + return; + default: + /* render buffer format is supported by software rendering */ + ; + } + } + } +} + + +/** * For debug only. */ static void @@ -960,42 +991,104 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) /** - * Given an internal format token for a renderbuffer, return the - * corresponding base format. + * Given an internal format token for a render buffer, return the + * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, + * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE, + * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc). + * + * This is similar to _mesa_base_tex_format() but the set of valid + * internal formats is different. + * + * Note that even if a format is determined to be legal here, validation + * of the FBO may fail if the format is not supported by the driver/GPU. + * + * \param internalFormat as passed to glRenderbufferStorage() + * \return the base internal format, or 0 if internalFormat is illegal */ GLenum _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) { - GLenum baseFormat; - + /* + * Notes: some formats such as alpha, luminance, etc. were added + * with GL_ARB_framebuffer_object. + */ switch (internalFormat) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case GL_SRGB8_EXT: + return GL_RGB; + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: case GL_RGBA16_SNORM: - /* This is used internally by Mesa for accum buffers. */ + case GL_SRGB8_ALPHA8_EXT: return GL_RGBA; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: - /* This is not a valid texture internalFormat, but valid for - * renderbuffers. - */ return GL_STENCIL_INDEX; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: - /* This is an override of _mesa_base_tex_format's check that - * ARB_depth_texture is present. We allow depth RBs without it. - */ return GL_DEPTH_COMPONENT; - } - - baseFormat = _mesa_base_tex_format(ctx, internalFormat); - if (baseFormat < 0) + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + if (ctx->Extensions.EXT_packed_depth_stencil) + return GL_DEPTH_STENCIL_EXT; + else + return 0; + case GL_RED: + case GL_R8: + case GL_R16: + return ctx->Extensions.ARB_texture_rg ? GL_RED : 0; + case GL_RG: + case GL_RG8: + case GL_RG16: + return ctx->Extensions.ARB_texture_rg ? GL_RG : 0; + /* XXX add floating point and integer formats eventually */ + default: return 0; - - return baseFormat; + } } @@ -1031,14 +1124,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, return; } - if (baseFormat != GL_DEPTH_COMPONENT && - baseFormat != GL_STENCIL_INDEX && - baseFormat != GL_DEPTH_STENCIL && - !_mesa_is_legal_color_format(ctx, baseFormat)) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func); - return; - } - if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); return; @@ -2072,7 +2157,14 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, "glGetFramebufferAttachmentParameterivEXT(pname)"); } else { - *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); + if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) { + *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); + } + else { + /* According to ARB_framebuffer_sRGB, we should return LINEAR + * if the sRGB conversion is unsupported. */ + *params = GL_LINEAR; + } } return; case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: @@ -2184,7 +2276,8 @@ _mesa_GenerateMipmapEXT(GLenum target) #if FEATURE_EXT_framebuffer_blit static const struct gl_renderbuffer_attachment * -find_attachment(const struct gl_framebuffer *fb, const struct gl_renderbuffer *rb) +find_attachment(const struct gl_framebuffer *fb, + const struct gl_renderbuffer *rb) { GLuint i; for (i = 0; i < Elements(fb->Attachment); i++) { @@ -2217,6 +2310,13 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_BUFFERS); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, _mesa_lookup_enum_by_nr(filter)); + if (ctx->NewState) { _mesa_update_state(ctx); } diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h index 8763f99c4a7..ba74a95b74c 100644 --- a/src/mesa/main/fbobject.h +++ b/src/mesa/main/fbobject.h @@ -69,6 +69,9 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb GLenum attachment, struct gl_renderbuffer *rb); extern void +_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb); + +extern void _mesa_test_framebuffer_completeness(struct gl_context *ctx, struct gl_framebuffer *fb); extern GLboolean diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index b8fed182570..1e395363475 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -1372,7 +1372,11 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 4; return; - case MESA_FORMAT_AL44: /* XXX this isn't plain GL_UNSIGNED_BYTE */ + case MESA_FORMAT_AL44: + *datatype = MESA_UNSIGNED_BYTE_4_4; + *comps = 2; + return; + case MESA_FORMAT_AL88: case MESA_FORMAT_AL88_REV: case MESA_FORMAT_RG88: diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h index d4dc5eac03e..9a5cef37788 100644 --- a/src/mesa/main/formats.h +++ b/src/mesa/main/formats.h @@ -35,6 +35,9 @@ #include <GL/gl.h> +/* OpenGL doesn't have GL_UNSIGNED_BYTE_4_4, so we must define our own type + * for GL_LUMINANCE4_ALPHA4. */ +#define MESA_UNSIGNED_BYTE_4_4 (GL_UNSIGNED_BYTE<<1) /** diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 63da71c95b4..948b3b7b5a2 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -553,6 +553,8 @@ _mesa_update_framebuffer_visual(struct gl_context *ctx, + fb->Visual.greenBits + fb->Visual.blueBits; fb->Visual.floatMode = GL_FALSE; fb->Visual.samples = rb->NumSamples; + if (_mesa_get_format_color_encoding(fmt) == GL_SRGB) + fb->Visual.sRGBCapable = ctx->Const.sRGBCapable; break; } } diff --git a/src/mesa/main/hint.c b/src/mesa/main/hint.c index bdbd7519d37..ff8d88fffe0 100644 --- a/src/mesa/main/hint.c +++ b/src/mesa/main/hint.c @@ -40,8 +40,9 @@ _mesa_Hint( GLenum target, GLenum mode ) ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glHint %s %d\n", - _mesa_lookup_enum_by_nr(target), mode); + _mesa_debug(ctx, "glHint %s %s\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(mode)); if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) { _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)"); diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index 909c18e7e60..63936132f98 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -68,6 +68,7 @@ _mesa_type_is_packed(GLenum type) switch (type) { case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: + case MESA_UNSIGNED_BYTE_4_4: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_4_4_4_4: @@ -194,6 +195,8 @@ _mesa_sizeof_packed_type( GLenum type ) return sizeof(GLubyte); case GL_UNSIGNED_BYTE_2_3_3_REV: return sizeof(GLubyte); + case MESA_UNSIGNED_BYTE_4_4: + return sizeof(GLubyte); case GL_UNSIGNED_SHORT_5_6_5: return sizeof(GLushort); case GL_UNSIGNED_SHORT_5_6_5_REV: @@ -1581,8 +1584,8 @@ _mesa_clip_drawpixels(const struct gl_context *ctx, * scissor box is ignored, and we use the bounds of the current readbuffer * surface. * - * \return GL_TRUE if image is ready for drawing or - * GL_FALSE if image was completely clipped away (draw nothing) + * \return GL_TRUE if region to read is in bounds + * GL_FALSE if region is completely out of bounds (nothing to read) */ GLboolean _mesa_clip_readpixels(const struct gl_context *ctx, diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c index bd1fd7cfbf8..bf89815f2d3 100644 --- a/src/mesa/main/imports.c +++ b/src/mesa/main/imports.c @@ -453,6 +453,7 @@ _mesa_inv_sqrtf(float n) #endif } +#ifndef __GNUC__ /** * Find the first bit set in a word. */ @@ -496,9 +497,6 @@ _mesa_ffs(int32_t i) int _mesa_ffsll(int64_t val) { -#ifdef ffsll - return ffsll(val); -#else int bit; assert(sizeof(val) == 8); @@ -512,27 +510,24 @@ _mesa_ffsll(int64_t val) return 32 + bit; return 0; -#endif } +#if ((_GNUC__ == 3 && __GNUC_MINOR__ < 4) || __GNUC__ < 4) /** * Return number of bits set in given GLuint. */ unsigned int _mesa_bitcount(unsigned int n) { -#if defined(__GNUC__) && \ - ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) - return __builtin_popcount(n); -#else unsigned int bits; for (bits = 0; n > 0; n = n >> 1) { bits += (n & 1); } return bits; -#endif } +#endif +#endif /** @@ -942,7 +937,7 @@ _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) va_end( args ); fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str); - fprintf(stderr, "Please report at bugzilla.freedesktop.org\n"); + fprintf(stderr, "Please report at bugs.freedesktop.org\n"); } diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index 5ea647ad8d7..ce7baabe2c7 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -539,6 +539,24 @@ _mesa_inv_sqrtf(float x); extern void _mesa_init_sqrt_table(void); +#ifdef __GNUC__ + +#ifdef __MINGW32__ +#define ffs __builtin_ffs +#define ffsll __builtin_ffsll +#endif + +#define _mesa_ffs(i) ffs(i) +#define _mesa_ffsll(i) ffsll(i) + +#if ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) +#define _mesa_bitcount(i) __builtin_popcount(i) +#else +extern unsigned int +_mesa_bitcount(unsigned int n); +#endif + +#else extern int _mesa_ffs(int32_t i); @@ -547,6 +565,7 @@ _mesa_ffsll(int64_t i); extern unsigned int _mesa_bitcount(unsigned int n); +#endif extern GLhalfARB _mesa_float_to_half(float f); diff --git a/src/mesa/main/lines.c b/src/mesa/main/lines.c index 81e179a9254..79bf5679d8a 100644 --- a/src/mesa/main/lines.c +++ b/src/mesa/main/lines.c @@ -43,6 +43,9 @@ _mesa_LineWidth( GLfloat width ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLineWidth %f\n", width); + if (width<=0.0) { _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" ); return; @@ -77,6 +80,9 @@ _mesa_LineStipple( GLint factor, GLushort pattern ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLineStipple %d %u\n", factor, pattern); + factor = CLAMP( factor, 1, 256 ); if (ctx->Line.StippleFactor == factor && diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index e073e17039f..d8a56103800 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -612,6 +612,28 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, dst[i] = (blue << 5) | (green << 2) | red; } } + + else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { + GLuint i, j, k; + const GLubyte *rowA = (const GLubyte *) srcRowA; + const GLubyte *rowB = (const GLubyte *) srcRowB; + GLubyte *dst = (GLubyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint r = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint g = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + dst[i] = (g << 4) | r; + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } @@ -1078,7 +1100,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } } else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) { - DECLARE_ROW_POINTERS0(GLushort); + DECLARE_ROW_POINTERS0(GLubyte); for (i = j = 0, k = k0; i < (GLuint) dstWidth; i++, j += colStride, k += colStride) { @@ -1115,6 +1137,34 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, dst[i] = (b << 5) | (g << 2) | r; } } + else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) { + DECLARE_ROW_POINTERS0(GLubyte); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowCr0 = rowC[j] & 0xf; + const GLint rowCr1 = rowC[k] & 0xf; + const GLint rowDr0 = rowD[j] & 0xf; + const GLint rowDr1 = rowD[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint rowCg0 = (rowC[j] >> 4) & 0xf; + const GLint rowCg1 = (rowC[k] >> 4) & 0xf; + const GLint rowDg0 = (rowD[j] >> 4) & 0xf; + const GLint rowDg1 = (rowD[k] >> 4) & 0xf; + const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + dst[i] = (g << 4) | r; + } + } else { _mesa_problem(NULL, "bad format in do_row()"); } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 34003b4b6fb..b237063a6d8 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -84,23 +84,8 @@ /*@{*/ typedef GLuint64 GLbitfield64; -#define BITFIELD64_ONE 1ULL -#define BITFIELD64_ALLONES ~0ULL - /** Set a single bit */ -#define BITFIELD64_BIT(b) (BITFIELD64_ONE << (b)) - -/** Set a mask of the least significant \c b bits */ -#define BITFIELD64_MASK(b) (((b) >= 64) ? BITFIELD64_ALLONES : \ - (BITFIELD64_BIT(b) - 1)) - -/** - * Set all bits from l (low bit) to h (high bit), inclusive. - * - * \note \C BITFIELD_64_RANGE(0, 63) return 64 set bits. - */ -#define BITFIELD64_RANGE(l, h) (BITFIELD64_MASK((h) + 1) & ~BITFIELD64_MASK(l)) -/*@}*/ +#define BITFIELD64_BIT(b) (1ULL << (b)) /** @@ -867,6 +852,23 @@ struct gl_fog_attrib }; +/** + * \brief Layout qualifiers for gl_FragDepth. + * + * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with + * a layout qualifier. + * + * \see enum ir_depth_layout + */ +enum gl_frag_depth_layout { + FRAG_DEPTH_LAYOUT_NONE, /**< No layout is specified. */ + FRAG_DEPTH_LAYOUT_ANY, + FRAG_DEPTH_LAYOUT_GREATER, + FRAG_DEPTH_LAYOUT_LESS, + FRAG_DEPTH_LAYOUT_UNCHANGED +}; + + /** * Hint attribute group (GL_HINT_BIT). * @@ -1238,7 +1240,7 @@ struct gl_texture_image * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT * only. Used for choosing TexEnv arithmetic. */ - GLuint TexFormat; /**< The actual format: MESA_FORMAT_x */ + gl_format TexFormat; /**< The actual texture memory format */ GLuint Border; /**< 0 or 1 */ GLuint Width; /**< = 2^WidthLog2 + 2*Border */ @@ -1641,6 +1643,7 @@ struct gl_array_attrib GLuint RestartIndex; GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */ + GLboolean RebindArrays; /**< whether the VBO module should rebind arrays */ /* GL_ARB_vertex_buffer_object */ struct gl_buffer_object *ArrayBufferObj; @@ -1889,6 +1892,7 @@ struct gl_fragment_program GLboolean UsesKill; /**< shader uses KIL instruction */ GLboolean OriginUpperLeft; GLboolean PixelCenterInteger; + enum gl_frag_depth_layout FragDepthLayout; }; @@ -2100,8 +2104,6 @@ struct gl_shader GLint RefCount; /**< Reference count */ GLboolean DeletePending; GLboolean CompileStatus; - GLboolean Main; /**< shader defines main() */ - GLboolean UnresolvedRefs; const GLchar *Source; /**< Source code string */ GLuint SourceChecksum; /**< for debug/logging purposes */ struct gl_program *Program; /**< Post-compile assembly code */ @@ -2378,7 +2380,7 @@ struct gl_renderbuffer GLenum InternalFormat; /**< The user-specified format */ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or GL_STENCIL_INDEX. */ - GLuint Format; /**< The actual format: MESA_FORMAT_x */ + gl_format Format; /**< The actual renderbuffer memory format */ GLubyte NumSamples; @@ -2692,6 +2694,9 @@ struct gl_constants /** GL_EXT_gpu_shader4 */ GLint MinProgramTexelOffset, MaxProgramTexelOffset; + + /* GL_EXT_framebuffer_sRGB */ + GLboolean sRGBCapable; /* can enable sRGB blend/update on FBOs */ }; @@ -2824,6 +2829,7 @@ struct gl_extensions GLboolean EXT_vertex_array_set; GLboolean OES_standard_derivatives; /* vendor extensions */ + GLboolean AMD_conservative_depth; GLboolean APPLE_client_storage; GLboolean APPLE_packed_pixels; GLboolean APPLE_vertex_array_object; @@ -2901,40 +2907,37 @@ struct gl_matrix_stack /** * \name Bits to indicate what state has changed. - * - * 4 unused flags. */ /*@{*/ -#define _NEW_MODELVIEW 0x1 /**< __struct gl_contextRec::ModelView */ -#define _NEW_PROJECTION 0x2 /**< __struct gl_contextRec::Projection */ -#define _NEW_TEXTURE_MATRIX 0x4 /**< __struct gl_contextRec::TextureMatrix */ -#define _NEW_ACCUM 0x10 /**< __struct gl_contextRec::Accum */ -#define _NEW_COLOR 0x20 /**< __struct gl_contextRec::Color */ -#define _NEW_DEPTH 0x40 /**< __struct gl_contextRec::Depth */ -#define _NEW_EVAL 0x80 /**< __struct gl_contextRec::Eval, __struct gl_contextRec::EvalMap */ -#define _NEW_FOG 0x100 /**< __struct gl_contextRec::Fog */ -#define _NEW_HINT 0x200 /**< __struct gl_contextRec::Hint */ -#define _NEW_LIGHT 0x400 /**< __struct gl_contextRec::Light */ -#define _NEW_LINE 0x800 /**< __struct gl_contextRec::Line */ -#define _NEW_PIXEL 0x1000 /**< __struct gl_contextRec::Pixel */ -#define _NEW_POINT 0x2000 /**< __struct gl_contextRec::Point */ -#define _NEW_POLYGON 0x4000 /**< __struct gl_contextRec::Polygon */ -#define _NEW_POLYGONSTIPPLE 0x8000 /**< __struct gl_contextRec::PolygonStipple */ -#define _NEW_SCISSOR 0x10000 /**< __struct gl_contextRec::Scissor */ -#define _NEW_STENCIL 0x20000 /**< __struct gl_contextRec::Stencil */ -#define _NEW_TEXTURE 0x40000 /**< __struct gl_contextRec::Texture */ -#define _NEW_TRANSFORM 0x80000 /**< __struct gl_contextRec::Transform */ -#define _NEW_VIEWPORT 0x100000 /**< __struct gl_contextRec::Viewport */ -#define _NEW_PACKUNPACK 0x200000 /**< __struct gl_contextRec::Pack, __struct gl_contextRec::Unpack */ -#define _NEW_ARRAY 0x400000 /**< __struct gl_contextRec::Array */ -#define _NEW_RENDERMODE 0x800000 /**< __struct gl_contextRec::RenderMode, __struct gl_contextRec::Feedback, __struct gl_contextRec::Select */ -#define _NEW_BUFFERS 0x1000000 /**< __struct gl_contextRec::Visual, __struct gl_contextRec::DrawBuffer, */ -#define _NEW_MULTISAMPLE 0x2000000 /**< __struct gl_contextRec::Multisample */ -#define _NEW_TRACK_MATRIX 0x4000000 /**< __struct gl_contextRec::VertexProgram */ -#define _NEW_PROGRAM 0x8000000 /**< __struct gl_contextRec::VertexProgram */ -#define _NEW_CURRENT_ATTRIB 0x10000000 /**< __struct gl_contextRec::Current */ -#define _NEW_PROGRAM_CONSTANTS 0x20000000 -#define _NEW_BUFFER_OBJECT 0x40000000 +#define _NEW_MODELVIEW (1 << 0) /**< gl_context::ModelView */ +#define _NEW_PROJECTION (1 << 1) /**< gl_context::Projection */ +#define _NEW_TEXTURE_MATRIX (1 << 2) /**< gl_context::TextureMatrix */ +#define _NEW_COLOR (1 << 3) /**< gl_context::Color */ +#define _NEW_DEPTH (1 << 4) /**< gl_context::Depth */ +#define _NEW_EVAL (1 << 5) /**< gl_context::Eval, EvalMap */ +#define _NEW_FOG (1 << 6) /**< gl_context::Fog */ +#define _NEW_HINT (1 << 7) /**< gl_context::Hint */ +#define _NEW_LIGHT (1 << 8) /**< gl_context::Light */ +#define _NEW_LINE (1 << 9) /**< gl_context::Line */ +#define _NEW_PIXEL (1 << 10) /**< gl_context::Pixel */ +#define _NEW_POINT (1 << 11) /**< gl_context::Point */ +#define _NEW_POLYGON (1 << 12) /**< gl_context::Polygon */ +#define _NEW_POLYGONSTIPPLE (1 << 13) /**< gl_context::PolygonStipple */ +#define _NEW_SCISSOR (1 << 14) /**< gl_context::Scissor */ +#define _NEW_STENCIL (1 << 15) /**< gl_context::Stencil */ +#define _NEW_TEXTURE (1 << 16) /**< gl_context::Texture */ +#define _NEW_TRANSFORM (1 << 17) /**< gl_context::Transform */ +#define _NEW_VIEWPORT (1 << 18) /**< gl_context::Viewport */ +#define _NEW_PACKUNPACK (1 << 19) /**< gl_context::Pack, Unpack */ +#define _NEW_ARRAY (1 << 20) /**< gl_context::Array */ +#define _NEW_RENDERMODE (1 << 21) /**< gl_context::RenderMode, etc */ +#define _NEW_BUFFERS (1 << 22) /**< gl_context::Visual, DrawBuffer, */ +#define _NEW_CURRENT_ATTRIB (1 << 23) /**< gl_context::Current */ +#define _NEW_MULTISAMPLE (1 << 24) /**< gl_context::Multisample */ +#define _NEW_TRACK_MATRIX (1 << 25) /**< gl_context::VertexProgram */ +#define _NEW_PROGRAM (1 << 26) /**< New program/shader state */ +#define _NEW_PROGRAM_CONSTANTS (1 << 27) +#define _NEW_BUFFER_OBJECT (1 << 28) #define _NEW_ALL ~0 /*@}*/ @@ -3292,9 +3295,6 @@ struct gl_context GLboolean FirstTimeCurrent; /*@}*/ - /** Dither disable via MESA_NO_DITHER env var */ - GLboolean NoDither; - /** software compression/decompression supported or not */ GLboolean Mesa_DXTn; diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index ef6460b2f97..fa35c6ce58a 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -25,6 +25,7 @@ #include "glheader.h" #include "context.h" +#include "enums.h" #include "hash.h" #include "imports.h" #include "queryobj.h" @@ -179,6 +180,9 @@ _mesa_GenQueriesARB(GLsizei n, GLuint *ids) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGenQueries(%d)\n", n); + if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); return; @@ -215,6 +219,9 @@ _mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n); + if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); return; @@ -246,6 +253,9 @@ _mesa_IsQueryARB(GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glIsQuery(%u)\n", id); + if (id && _mesa_lookup_query_object(ctx, id)) return GL_TRUE; else @@ -260,6 +270,10 @@ _mesa_BeginQueryARB(GLenum target, GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBeginQuery(%s, %u)\n", + _mesa_lookup_enum_by_nr(target), id); + FLUSH_VERTICES(ctx, _NEW_DEPTH); bindpt = get_query_binding_point(ctx, target); @@ -311,6 +325,9 @@ _mesa_EndQueryARB(GLenum target) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target)); + FLUSH_VERTICES(ctx, _NEW_DEPTH); bindpt = get_query_binding_point(ctx, target); @@ -341,6 +358,11 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(pname)); + bindpt = get_query_binding_point(ctx, target); if (!bindpt) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); @@ -370,6 +392,10 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -417,6 +443,10 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -467,6 +497,10 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -504,6 +538,10 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c index e5b85ca32b4..9a4f15f7279 100644 --- a/src/mesa/main/readpix.c +++ b/src/mesa/main/readpix.c @@ -26,6 +26,7 @@ #include "imports.h" #include "bufferobj.h" #include "context.h" +#include "enums.h" #include "readpix.h" #include "framebuffer.h" #include "formats.h" @@ -173,6 +174,13 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, FLUSH_CURRENT(ctx, 0); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n", + width, height, + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type), + pixels); + if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(width=%d height=%d)", width, height ); diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c index 23c662bab7f..67ee589d776 100644 --- a/src/mesa/main/renderbuffer.c +++ b/src/mesa/main/renderbuffer.c @@ -1086,7 +1086,7 @@ _mesa_soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer * pixelSize = sizeof(GLuint); break; default: - _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage"); + /* unsupported format */ return GL_FALSE; } diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index a5e90d7cbd1..11b0f884fa4 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -48,7 +48,7 @@ #include "program/program.h" #include "program/prog_parameter.h" #include "program/prog_uniform.h" -#include "talloc.h" +#include "ralloc.h" #include <stdbool.h> #include "../glsl/glsl_parser_extras.h" @@ -1137,9 +1137,9 @@ validate_program(struct gl_context *ctx, GLuint program) if (!shProg->Validated) { /* update info log */ if (shProg->InfoLog) { - talloc_free(shProg->InfoLog); + ralloc_free(shProg->InfoLog); } - shProg->InfoLog = talloc_strdup(shProg, errMsg); + shProg->InfoLog = ralloc_strdup(shProg, errMsg); } } @@ -1184,6 +1184,8 @@ void GLAPIENTRY _mesa_CompileShaderARB(GLhandleARB shaderObj) { GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCompileShader %u\n", shaderObj); compile_shader(ctx, shaderObj); } @@ -1192,6 +1194,8 @@ GLuint GLAPIENTRY _mesa_CreateShader(GLenum type) { GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type)); return create_shader(ctx, type); } @@ -1208,6 +1212,8 @@ GLuint GLAPIENTRY _mesa_CreateProgram(void) { GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCreateProgram\n"); return create_shader_program(ctx); } @@ -1223,6 +1229,11 @@ _mesa_CreateProgramObjectARB(void) void GLAPIENTRY _mesa_DeleteObjectARB(GLhandleARB obj) { + if (MESA_VERBOSE & VERBOSE_API) { + GET_CURRENT_CONTEXT(ctx); + _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj); + } + if (obj) { GET_CURRENT_CONTEXT(ctx); if (is_program(ctx, obj)) { @@ -1855,7 +1866,7 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) #endif } - shProg->InfoLog = talloc_strdup_append(shProg->InfoLog, sh->InfoLog); + ralloc_strcat(&shProg->InfoLog, sh->InfoLog); } delete_shader(ctx, shader); diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 647fd31cab4..1d75845590f 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -38,7 +38,7 @@ #include "program/program.h" #include "program/prog_parameter.h" #include "program/prog_uniform.h" -#include "talloc.h" +#include "ralloc.h" /**********************************************************************/ /*** Shader object functions ***/ @@ -105,7 +105,7 @@ _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type) struct gl_shader *shader; assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER || type == GL_GEOMETRY_SHADER_ARB); - shader = talloc_zero(NULL, struct gl_shader); + shader = rzalloc(NULL, struct gl_shader); if (shader) { shader->Type = type; shader->Name = name; @@ -125,7 +125,7 @@ _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh) if (sh->Source) free((void *) sh->Source); _mesa_reference_program(ctx, &sh->Program, NULL); - talloc_free(sh); + ralloc_free(sh); } @@ -252,7 +252,7 @@ static struct gl_shader_program * _mesa_new_shader_program(struct gl_context *ctx, GLuint name) { struct gl_shader_program *shProg; - shProg = talloc_zero(NULL, struct gl_shader_program); + shProg = rzalloc(NULL, struct gl_shader_program); if (shProg) { shProg->Name = name; _mesa_init_shader_program(ctx, shProg); @@ -316,7 +316,7 @@ _mesa_free_shader_program_data(struct gl_context *ctx, } if (shProg->InfoLog) { - talloc_free(shProg->InfoLog); + ralloc_free(shProg->InfoLog); shProg->InfoLog = NULL; } @@ -347,7 +347,7 @@ _mesa_delete_shader_program(struct gl_context *ctx, struct gl_shader_program *sh { _mesa_free_shader_program_data(ctx, shProg); - talloc_free(shProg); + ralloc_free(shProg); } diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index cce1b464f0c..502c429294c 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -662,6 +662,8 @@ _mesa_update_state_locked( struct gl_context *ctx ) ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); ctx->Array.NewState = 0; + if (!ctx->Array.RebindArrays) + ctx->Array.RebindArrays = (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) != 0; } diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c index 93e2e97ce0c..d898bf1d749 100644 --- a/src/mesa/main/stencil.c +++ b/src/mesa/main/stencil.c @@ -147,6 +147,9 @@ _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLui const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilFuncSeparateATI()\n"); + if (!validate_stencil_func(ctx, frontfunc)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparateATI(frontfunc)"); @@ -203,6 +206,9 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask ) const GLint face = ctx->Stencil.ActiveFace; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilFunc()\n"); + if (!validate_stencil_func(ctx, func)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)"); return; @@ -267,6 +273,9 @@ _mesa_StencilMask( GLuint mask ) GET_CURRENT_CONTEXT(ctx); const GLint face = ctx->Stencil.ActiveFace; + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilMask()\n"); + ASSERT_OUTSIDE_BEGIN_END(ctx); if (face != 0) { @@ -321,6 +330,9 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) GET_CURRENT_CONTEXT(ctx); const GLint face = ctx->Stencil.ActiveFace; + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilOp()\n"); + ASSERT_OUTSIDE_BEGIN_END(ctx); if (!validate_stencil_op(ctx, fail)) { @@ -386,6 +398,9 @@ _mesa_ActiveStencilFaceEXT(GLenum face) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glActiveStencilFaceEXT()\n"); + if (!ctx->Extensions.EXT_stencil_two_side) { _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT"); return; @@ -416,6 +431,9 @@ _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilOpSeparate()\n"); + if (!validate_stencil_op(ctx, sfail)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)"); return; @@ -471,6 +489,9 @@ _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilFuncSeparate()\n"); + if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)"); return; @@ -509,6 +530,9 @@ _mesa_StencilMaskSeparate(GLenum face, GLuint mask) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glStencilMaskSeparate()\n"); + if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)"); return; diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c index 146b2b340e7..2542cea856b 100644 --- a/src/mesa/main/texformat.c +++ b/src/mesa/main/texformat.c @@ -591,6 +591,17 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, } } + if (ctx->Extensions.EXT_texture_format_BGRA8888) { + switch (internalFormat) { + case GL_BGRA: + RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888); + break; + + default: + ; /* fallthrough */ + } + } + _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()"); return MESA_FORMAT_NONE; } diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c index da610798e12..28829694153 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -805,8 +805,8 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format, * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean -getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, - GLvoid *img) +getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, + GLint level, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 47d509396a7..1f2ad7f266b 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -183,6 +183,15 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) ; /* fallthrough */ } + if (ctx->Extensions.EXT_texture_format_BGRA8888) { + switch (internalFormat) { + case GL_BGRA_EXT: + return GL_RGBA; + default: + ; /* fallthrough */ + } + } + if (ctx->Extensions.EXT_paletted_texture) { switch (internalFormat) { case GL_COLOR_INDEX: @@ -694,6 +703,9 @@ _mesa_select_tex_object(struct gl_context *ctx, const struct gl_texture_unit *texUnit, GLenum target) { + const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); + switch (target) { case GL_TEXTURE_1D: return texUnit->CurrentTex[TEXTURE_1D_INDEX]; @@ -726,17 +738,13 @@ _mesa_select_tex_object(struct gl_context *ctx, return ctx->Extensions.NV_texture_rectangle ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; case GL_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; + return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; case GL_PROXY_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; + return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; case GL_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; + return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array - ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; + return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; default: _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); return NULL; @@ -921,7 +929,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) case GL_PROXY_TEXTURE_1D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array) ? ctx->Const.MaxTextureLevels : 0; default: return 0; /* bad target */ @@ -1373,7 +1382,8 @@ target_can_be_compressed(const struct gl_context *ctx, GLenum target, return ctx->Extensions.ARB_texture_cube_map; case GL_PROXY_TEXTURE_2D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1414,7 +1424,8 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) return ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY_EXT: case GL_PROXY_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1425,7 +1436,8 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) return GL_TRUE; case GL_TEXTURE_2D_ARRAY_EXT: case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1462,7 +1474,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) case GL_TEXTURE_RECTANGLE_NV: return ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } @@ -1471,7 +1484,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) case GL_TEXTURE_3D: return GL_TRUE; case GL_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array; + return (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array); default: return GL_FALSE; } diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 29e409d0b8c..6e14face4dd 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -33,6 +33,7 @@ #include "main/glheader.h" #include "main/colormac.h" #include "main/context.h" +#include "main/enums.h" #include "main/formats.h" #include "main/macros.h" #include "main/mfeatures.h" @@ -116,12 +117,14 @@ get_texobj(struct gl_context *ctx, GLenum target, GLboolean get) } break; case GL_TEXTURE_1D_ARRAY_EXT: - if (ctx->Extensions.MESA_texture_array) { + if (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array) { return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX]; } break; case GL_TEXTURE_2D_ARRAY_EXT: - if (ctx->Extensions.MESA_texture_array) { + if (ctx->Extensions.MESA_texture_array || + ctx->Extensions.EXT_texture_array) { return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX]; } break; @@ -175,13 +178,26 @@ set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz) /** - * This is called just prior to changing any texture object state. + * This is called just prior to changing any texture object state which + * will not effect texture completeness. + */ +static INLINE void +flush(struct gl_context *ctx) +{ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); +} + + +/** + * This is called just prior to changing any texture object state which + * can effect texture completeness (texture base level, max level, + * minification filter). * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE * state flag and then mark the texture object as 'incomplete' so that any * per-texture derived state gets recomputed. */ static INLINE void -flush(struct gl_context *ctx, struct gl_texture_object *texObj) +incomplete(struct gl_context *ctx, struct gl_texture_object *texObj) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); texObj->_Complete = GL_FALSE; @@ -204,7 +220,7 @@ set_tex_parameteri(struct gl_context *ctx, switch (params[0]) { case GL_NEAREST: case GL_LINEAR: - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->MinFilter = params[0]; return GL_TRUE; case GL_NEAREST_MIPMAP_NEAREST: @@ -212,14 +228,13 @@ set_tex_parameteri(struct gl_context *ctx, case GL_NEAREST_MIPMAP_LINEAR: case GL_LINEAR_MIPMAP_LINEAR: if (texObj->Target != GL_TEXTURE_RECTANGLE_NV) { - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->MinFilter = params[0]; return GL_TRUE; } /* fall-through */ default: - _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", - params[0] ); + goto invalid_param; } return GL_FALSE; @@ -229,12 +244,11 @@ set_tex_parameteri(struct gl_context *ctx, switch (params[0]) { case GL_NEAREST: case GL_LINEAR: - flush(ctx, texObj); + flush(ctx); /* does not effect completeness */ texObj->MagFilter = params[0]; return GL_TRUE; default: - _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", - params[0]); + goto invalid_param; } return GL_FALSE; @@ -242,7 +256,7 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->WrapS == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { - flush(ctx, texObj); + flush(ctx); texObj->WrapS = params[0]; return GL_TRUE; } @@ -252,7 +266,7 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->WrapT == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { - flush(ctx, texObj); + flush(ctx); texObj->WrapT = params[0]; return GL_TRUE; } @@ -262,7 +276,7 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->WrapR == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { - flush(ctx, texObj); + flush(ctx); texObj->WrapR = params[0]; return GL_TRUE; } @@ -277,7 +291,7 @@ set_tex_parameteri(struct gl_context *ctx, "glTexParameter(param=%d)", params[0]); return GL_FALSE; } - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->BaseLevel = params[0]; return GL_TRUE; @@ -289,34 +303,31 @@ set_tex_parameteri(struct gl_context *ctx, "glTexParameter(param=%d)", params[0]); return GL_FALSE; } - flush(ctx, texObj); + incomplete(ctx, texObj); texObj->MaxLevel = params[0]; return GL_TRUE; case GL_GENERATE_MIPMAP_SGIS: if (texObj->GenerateMipmap != params[0]) { - flush(ctx, texObj); + /* no flush() */ texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE; return GL_TRUE; } return GL_FALSE; case GL_TEXTURE_COMPARE_MODE_ARB: - if (ctx->Extensions.ARB_shadow && - (params[0] == GL_NONE || - params[0] == GL_COMPARE_R_TO_TEXTURE_ARB)) { - if (texObj->CompareMode != params[0]) { - flush(ctx, texObj); + if (ctx->Extensions.ARB_shadow) { + if (texObj->CompareMode == params[0]) + return GL_FALSE; + if (params[0] == GL_NONE || + params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) { + flush(ctx); texObj->CompareMode = params[0]; return GL_TRUE; } - return GL_FALSE; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(GL_TEXTURE_COMPARE_MODE_ARB)"); + goto invalid_param; } - return GL_FALSE; + goto invalid_pname; case GL_TEXTURE_COMPARE_FUNC_ARB: if (ctx->Extensions.ARB_shadow) { @@ -325,7 +336,7 @@ set_tex_parameteri(struct gl_context *ctx, switch (params[0]) { case GL_LEQUAL: case GL_GEQUAL: - flush(ctx, texObj); + flush(ctx); texObj->CompareFunc = params[0]; return GL_TRUE; case GL_EQUAL: @@ -335,38 +346,32 @@ set_tex_parameteri(struct gl_context *ctx, case GL_ALWAYS: case GL_NEVER: if (ctx->Extensions.EXT_shadow_funcs) { - flush(ctx, texObj); + flush(ctx); texObj->CompareFunc = params[0]; return GL_TRUE; } /* fall-through */ default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(GL_TEXTURE_COMPARE_FUNC_ARB)"); + goto invalid_param; } } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - } - return GL_FALSE; + goto invalid_pname; case GL_DEPTH_TEXTURE_MODE_ARB: - if (ctx->Extensions.ARB_depth_texture && - (params[0] == GL_LUMINANCE || - params[0] == GL_INTENSITY || - params[0] == GL_ALPHA || - (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED))) { - if (texObj->DepthMode != params[0]) { - flush(ctx, texObj); + if (ctx->Extensions.ARB_depth_texture) { + if (texObj->DepthMode == params[0]) + return GL_FALSE; + if (params[0] == GL_LUMINANCE || + params[0] == GL_INTENSITY || + params[0] == GL_ALPHA || + (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) { + flush(ctx); texObj->DepthMode = params[0]; return GL_TRUE; } + goto invalid_param; } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(GL_DEPTH_TEXTURE_MODE_ARB)"); - } - return GL_FALSE; + goto invalid_pname; #if FEATURE_OES_draw_texture case GL_TEXTURE_CROP_RECT_OES: @@ -391,19 +396,18 @@ set_tex_parameteri(struct gl_context *ctx, } ASSERT(comp < 4); if (swz >= 0) { - flush(ctx, texObj); + flush(ctx); texObj->Swizzle[comp] = params[0]; set_swizzle_component(&texObj->_Swizzle, comp, swz); return GL_TRUE; } } - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - return GL_FALSE; + goto invalid_pname; case GL_TEXTURE_SWIZZLE_RGBA_EXT: if (ctx->Extensions.EXT_texture_swizzle) { GLuint comp; - flush(ctx, texObj); + flush(ctx); for (comp = 0; comp < 4; comp++) { const GLint swz = comp_to_swizzle(params[comp]); if (swz >= 0) { @@ -418,25 +422,34 @@ set_tex_parameteri(struct gl_context *ctx, } return GL_TRUE; } - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - return GL_FALSE; + goto invalid_pname; + case GL_TEXTURE_SRGB_DECODE_EXT: if (ctx->Extensions.EXT_texture_sRGB_decode) { GLenum decode = params[0]; if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) { if (texObj->sRGBDecode != decode) { - flush(ctx, texObj); + flush(ctx); texObj->sRGBDecode = decode; _mesa_update_fetch_functions(texObj); } return GL_TRUE; } } - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); - return GL_FALSE; + goto invalid_pname; + default: - _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname); + goto invalid_pname; } + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); + return GL_FALSE; + +invalid_param: + _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)", + _mesa_lookup_enum_by_nr(params[0])); return GL_FALSE; } @@ -454,19 +467,19 @@ set_tex_parameterf(struct gl_context *ctx, case GL_TEXTURE_MIN_LOD: if (texObj->MinLod == params[0]) return GL_FALSE; - flush(ctx, texObj); + flush(ctx); texObj->MinLod = params[0]; return GL_TRUE; case GL_TEXTURE_MAX_LOD: if (texObj->MaxLod == params[0]) return GL_FALSE; - flush(ctx, texObj); + flush(ctx); texObj->MaxLod = params[0]; return GL_TRUE; case GL_TEXTURE_PRIORITY: - flush(ctx, texObj); + flush(ctx); texObj->Priority = CLAMP(params[0], 0.0F, 1.0F); return GL_TRUE; @@ -478,7 +491,7 @@ set_tex_parameterf(struct gl_context *ctx, _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); return GL_FALSE; } - flush(ctx, texObj); + flush(ctx); /* clamp to max, that's what NVIDIA does */ texObj->MaxAnisotropy = MIN2(params[0], ctx->Const.MaxTextureMaxAnisotropy); @@ -495,7 +508,7 @@ set_tex_parameterf(struct gl_context *ctx, case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: if (ctx->Extensions.ARB_shadow_ambient) { if (texObj->CompareFailValue != params[0]) { - flush(ctx, texObj); + flush(ctx); texObj->CompareFailValue = CLAMP(params[0], 0.0F, 1.0F); return GL_TRUE; } @@ -510,7 +523,7 @@ set_tex_parameterf(struct gl_context *ctx, /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */ if (ctx->Extensions.EXT_texture_lod_bias) { if (texObj->LodBias != params[0]) { - flush(ctx, texObj); + flush(ctx); texObj->LodBias = params[0]; return GL_TRUE; } @@ -519,7 +532,7 @@ set_tex_parameterf(struct gl_context *ctx, break; case GL_TEXTURE_BORDER_COLOR: - flush(ctx, texObj); + flush(ctx); texObj->BorderColor.f[RCOMP] = params[0]; texObj->BorderColor.f[GCOMP] = params[1]; texObj->BorderColor.f[BCOMP] = params[2]; @@ -821,7 +834,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, const struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; const struct gl_texture_image *img = NULL; - GLboolean isProxy; GLint maxLevels; gl_format texFormat; GET_CURRENT_CONTEXT(ctx); @@ -849,7 +861,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, } texObj = _mesa_select_tex_object(ctx, texUnit, target); - _mesa_lock_texture(ctx, texObj); img = _mesa_select_tex_image(ctx, texObj, target, level); if (!img || !img->TexFormat) { @@ -858,13 +869,11 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = 1; else *params = 0; - goto out; + return; } texFormat = img->TexFormat; - isProxy = _mesa_is_proxy_texture(target); - switch (pname) { case GL_TEXTURE_WIDTH: *params = img->Width; @@ -876,9 +885,9 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = img->Depth; break; case GL_TEXTURE_INTERNAL_FORMAT: - if (_mesa_is_format_compressed(img->TexFormat)) { + if (_mesa_is_format_compressed(texFormat)) { /* need to return the actual compressed format */ - *params = _mesa_compressed_format_to_glenum(ctx, img->TexFormat); + *params = _mesa_compressed_format_to_glenum(ctx, texFormat); } else { /* return the user's requested internal format */ @@ -949,8 +958,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, if (ctx->Extensions.ARB_depth_texture) *params = _mesa_get_format_bits(texFormat, pname); else - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; break; case GL_TEXTURE_STENCIL_SIZE_EXT: if (ctx->Extensions.EXT_packed_depth_stencil || @@ -958,8 +966,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = _mesa_get_format_bits(texFormat, pname); } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_SHARED_SIZE: @@ -970,14 +977,14 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = 0; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; /* GL_ARB_texture_compression */ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: - if (_mesa_is_format_compressed(img->TexFormat) && !isProxy) { + if (_mesa_is_format_compressed(texFormat) && + !_mesa_is_proxy_texture(target)) { *params = _mesa_format_image_size(texFormat, img->Width, img->Height, img->Depth); } @@ -987,7 +994,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, } break; case GL_TEXTURE_COMPRESSED: - *params = (GLint) _mesa_is_format_compressed(img->TexFormat); + *params = (GLint) _mesa_is_format_compressed(texFormat); break; /* GL_ARB_texture_float */ @@ -997,8 +1004,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_GREEN_TYPE_ARB: @@ -1007,8 +1013,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_BLUE_TYPE_ARB: @@ -1017,8 +1022,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_ALPHA_TYPE_ARB: @@ -1027,8 +1031,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_LUMINANCE_TYPE_ARB: @@ -1037,8 +1040,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_INTENSITY_TYPE_ARB: @@ -1047,8 +1049,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; case GL_TEXTURE_DEPTH_TYPE_ARB: @@ -1057,18 +1058,21 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, _mesa_get_format_datatype(texFormat) : GL_NONE; } else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } break; default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetTexLevelParameter[if]v(pname)"); + goto invalid_pname; } - out: - _mesa_unlock_texture(ctx, texObj); + /* no error if we get here */ + return; + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); } diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index aee2e6b4e9b..eb289722d1a 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -450,6 +450,36 @@ _mesa_get_active_uniform(struct gl_context *ctx, GLuint program, GLuint index, } +static unsigned +get_vector_elements(GLenum type) +{ + switch (type) { + case GL_FLOAT: + case GL_INT: + case GL_BOOL: + case GL_UNSIGNED_INT: + default: /* Catch all the various sampler types. */ + return 1; + + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 2; + + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 3; + + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 4; + } +} static void get_matrix_dims(GLenum type, GLint *rows, GLint *cols) @@ -508,17 +538,8 @@ get_uniform_rows_cols(const struct gl_program_parameter *p, get_matrix_dims(p->DataType, rows, cols); if (*rows == 0 && *cols == 0) { /* not a matrix type, probably a float or vector */ - if (p->Size <= 4) { - *rows = 1; - *cols = p->Size; - } - else { - *rows = (p->Size + 3) / 4; - if (p->Size % 4 == 0) - *cols = 4; - else - *cols = p->Size % 4; - } + *rows = 1; + *cols = get_vector_elements(p->DataType); } } @@ -642,8 +663,10 @@ _mesa_get_uniformfv(struct gl_context *ctx, GLuint program, GLint location, k = 0; for (i = 0; i < rows; i++) { + const int base = paramPos + offset + i; + for (j = 0; j < cols; j++ ) { - params[k++] = prog->Parameters->ParameterValues[paramPos+i][j]; + params[k++] = prog->Parameters->ParameterValues[base][j]; } } } @@ -675,8 +698,10 @@ _mesa_get_uniformiv(struct gl_context *ctx, GLuint program, GLint location, k = 0; for (i = 0; i < rows; i++) { + const int base = paramPos + offset + i; + for (j = 0; j < cols; j++ ) { - params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j]; + params[k++] = (GLint) prog->Parameters->ParameterValues[base][j]; } } } @@ -709,8 +734,10 @@ _mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location, k = 0; for (i = 0; i < rows; i++) { + const int base = paramPos + offset + i; + for (j = 0; j < cols; j++ ) { - params[k++] = (GLuint) prog->Parameters->ParameterValues[paramPos+i][j]; + params[k++] = (GLuint) prog->Parameters->ParameterValues[base][j]; } } } diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 29d8a8827e3..cfed4b506a5 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -508,7 +508,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, { const struct gl_client_array *array; - if (index >= MAX_VERTEX_GENERIC_ATTRIBS) { + if (index >= ctx->Const.VertexProgram.MaxAttribs) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index); return 0; } @@ -550,6 +550,25 @@ error: } +static const GLfloat * +get_current_attrib(struct gl_context *ctx, GLuint index, const char *function) +{ + if (index == 0) { + if (ctx->API != API_OPENGLES2) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function); + return NULL; + } + } + else if (index >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function); + return NULL; + } + + FLUSH_CURRENT(ctx, 0); + return ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; +} + void GLAPIENTRY _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params) { @@ -557,13 +576,8 @@ _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribfv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv"); + if (v != NULL) { COPY_4V(params, v); } } @@ -581,13 +595,8 @@ _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribdv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv"); + if (v != NULL) { params[0] = (GLdouble) v[0]; params[1] = (GLdouble) v[1]; params[2] = (GLdouble) v[2]; @@ -608,13 +617,8 @@ _mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribiv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv"); + if (v != NULL) { /* XXX should floats in[0,1] be scaled to full int range? */ params[0] = (GLint) v[0]; params[1] = (GLint) v[1]; @@ -637,13 +641,9 @@ _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribIiv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = + get_current_attrib(ctx, index, "glGetVertexAttribIiv"); + if (v != NULL) { /* XXX we don't have true integer-valued vertex attribs yet */ params[0] = (GLint) v[0]; params[1] = (GLint) v[1]; @@ -666,13 +666,9 @@ _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params) ASSERT_OUTSIDE_BEGIN_END(ctx); if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { - if (index == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetVertexAttribIuiv(index==0)"); - } - else { - const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]; - FLUSH_CURRENT(ctx, 0); + const GLfloat *v = + get_current_attrib(ctx, index, "glGetVertexAttribIuiv"); + if (v != NULL) { /* XXX we don't have true integer-valued vertex attribs yet */ params[0] = (GLuint) v[0]; params[1] = (GLuint) v[1]; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 786fdfbd231..33c262f8ca4 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -105,13 +105,13 @@ extern ir_to_mesa_src_reg ir_to_mesa_undef; class ir_to_mesa_instruction : public exec_node { public: - /* Callers of this talloc-based new need not call delete. It's - * easier to just talloc_free 'ctx' (or any of its ancestors). */ + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ static void* operator new(size_t size, void *ctx) { void *node; - node = talloc_zero_size(ctx, size); + node = rzalloc_size(ctx, size); assert(node != NULL); return node; @@ -318,7 +318,7 @@ fail_link(struct gl_shader_program *prog, const char *fmt, ...) { va_list args; va_start(args, fmt); - prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); + ralloc_vasprintf_append(&prog->InfoLog, fmt, args); va_end(args); prog->LinkStatus = GL_FALSE; @@ -651,6 +651,7 @@ type_size(const struct glsl_type *type) return 1; } case GLSL_TYPE_ARRAY: + assert(type->length > 0); return type_size(type->fields.array) * type->length; case GLSL_TYPE_STRUCT: size = 0; @@ -726,6 +727,29 @@ ir_to_mesa_visitor::visit(ir_variable *ir) fp->OriginUpperLeft = ir->origin_upper_left; fp->PixelCenterInteger = ir->pixel_center_integer; + + } else if (strcmp(ir->name, "gl_FragDepth") == 0) { + struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; + switch (ir->depth_layout) { + case ir_depth_layout_none: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE; + break; + case ir_depth_layout_any: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY; + break; + case ir_depth_layout_greater: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER; + break; + case ir_depth_layout_less: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS; + break; + case ir_depth_layout_unchanged: + fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED; + break; + default: + assert(0); + break; + } } if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { @@ -1451,18 +1475,17 @@ void ir_to_mesa_visitor::visit(ir_dereference_variable *ir) { variable_storage *entry = find_variable_storage(ir->var); + ir_variable *var = ir->var; if (!entry) { - switch (ir->var->mode) { + switch (var->mode) { case ir_var_uniform: - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM, - ir->var->location); + entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM, + var->location); this->variables.push_tail(entry); break; case ir_var_in: - case ir_var_out: case ir_var_inout: - case ir_var_system_value: /* The linker assigns locations for varyings and attributes, * including deprecated builtins (like gl_Color), user-assign * generic attributes (glBindVertexLocation), and @@ -1470,49 +1493,47 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) * * FINISHME: We would hit this path for function arguments. Fix! */ - assert(ir->var->location != -1); - if (ir->var->mode == ir_var_in || - ir->var->mode == ir_var_inout) { - entry = new(mem_ctx) variable_storage(ir->var, - PROGRAM_INPUT, - ir->var->location); - - if (this->prog->Target == GL_VERTEX_PROGRAM_ARB && - ir->var->location >= VERT_ATTRIB_GENERIC0) { - _mesa_add_attribute(prog->Attributes, - ir->var->name, - _mesa_sizeof_glsl_type(ir->var->type->gl_type), - ir->var->type->gl_type, - ir->var->location - VERT_ATTRIB_GENERIC0); - } - } else if (ir->var->mode == ir_var_system_value) { - entry = new(mem_ctx) variable_storage(ir->var, - PROGRAM_SYSTEM_VALUE, - ir->var->location); - } else { - entry = new(mem_ctx) variable_storage(ir->var, - PROGRAM_OUTPUT, - ir->var->location); - } - + assert(var->location != -1); + entry = new(mem_ctx) variable_storage(var, + PROGRAM_INPUT, + var->location); + if (this->prog->Target == GL_VERTEX_PROGRAM_ARB && + var->location >= VERT_ATTRIB_GENERIC0) { + _mesa_add_attribute(this->prog->Attributes, + var->name, + _mesa_sizeof_glsl_type(var->type->gl_type), + var->type->gl_type, + var->location - VERT_ATTRIB_GENERIC0); + } + break; + case ir_var_out: + assert(var->location != -1); + entry = new(mem_ctx) variable_storage(var, + PROGRAM_OUTPUT, + var->location); break; + case ir_var_system_value: + entry = new(mem_ctx) variable_storage(var, + PROGRAM_SYSTEM_VALUE, + var->location); + break; case ir_var_auto: case ir_var_temporary: - entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY, + entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY, this->next_temp); this->variables.push_tail(entry); - next_temp += type_size(ir->var->type); + next_temp += type_size(var->type); break; } if (!entry) { - printf("Failed to make storage for %s\n", ir->var->name); + printf("Failed to make storage for %s\n", var->name); exit(1); } } - this->result = ir_to_mesa_src_reg(entry->file, entry->index, ir->var->type); + this->result = ir_to_mesa_src_reg(entry->file, entry->index, var->type); } void @@ -1549,7 +1570,7 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir) this->result, src_reg_for_float(element_size)); } - src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg); + src_reg.reladdr = ralloc(mem_ctx, ir_to_mesa_src_reg); memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg)); } @@ -1906,7 +1927,7 @@ ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig) return entry; } - entry = talloc(mem_ctx, function_entry); + entry = ralloc(mem_ctx, function_entry); entry->sig = sig; entry->sig_id = this->next_signature_id++; entry->bgn_inst = NULL; @@ -2243,12 +2264,12 @@ ir_to_mesa_visitor::ir_to_mesa_visitor() next_temp = 1; next_signature_id = 1; current_function = NULL; - mem_ctx = talloc_new(NULL); + mem_ctx = ralloc_context(NULL); } ir_to_mesa_visitor::~ir_to_mesa_visitor() { - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } static struct prog_src_register @@ -2297,8 +2318,8 @@ set_branchtargets(ir_to_mesa_visitor *v, } } - if_stack = talloc_zero_array(v->mem_ctx, int, if_count); - loop_stack = talloc_zero_array(v->mem_ctx, int, loop_count); + if_stack = rzalloc_array(v->mem_ctx, int, if_count); + loop_stack = rzalloc_array(v->mem_ctx, int, loop_count); for (i = 0; i < num_instructions; i++) { switch (mesa_instructions[i].Opcode) { @@ -2441,7 +2462,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, unsigned int next_sampler = 0, num_uniforms = 0; struct uniform_sort *sorted_uniforms; - sorted_uniforms = talloc_array(NULL, struct uniform_sort, + sorted_uniforms = ralloc_array(NULL, struct uniform_sort, shader_program->Uniforms->NumUniforms); for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) { @@ -2520,7 +2541,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, } } - talloc_free(sorted_uniforms); + ralloc_free(sorted_uniforms); } static void @@ -2536,7 +2557,7 @@ set_uniform_initializer(struct gl_context *ctx, void *mem_ctx, for (unsigned int i = 0; i < type->length; i++) { const glsl_type *field_type = type->fields.structure[i].type; - const char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name, + const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name, type->fields.structure[i].name); set_uniform_initializer(ctx, mem_ctx, shader_program, field_name, field_type, field_constant); @@ -2567,7 +2588,7 @@ set_uniform_initializer(struct gl_context *ctx, void *mem_ctx, void *values; if (element_type->base_type == GLSL_TYPE_BOOL) { - int *conv = talloc_array(mem_ctx, int, element_type->components()); + int *conv = ralloc_array(mem_ctx, int, element_type->components()); for (unsigned int j = 0; j < element_type->components(); j++) { conv[j] = element->value.b[j]; } @@ -2613,14 +2634,14 @@ set_uniform_initializers(struct gl_context *ctx, continue; if (!mem_ctx) - mem_ctx = talloc_new(NULL); + mem_ctx = ralloc_context(NULL); set_uniform_initializer(ctx, mem_ctx, shader_program, var->name, var->type, var->constant_value); } } - talloc_free(mem_ctx); + ralloc_free(mem_ctx); } /* @@ -2646,13 +2667,18 @@ set_uniform_initializers(struct gl_context *ctx, void ir_to_mesa_visitor::copy_propagate(void) { - ir_to_mesa_instruction **acp = talloc_zero_array(mem_ctx, + ir_to_mesa_instruction **acp = rzalloc_array(mem_ctx, ir_to_mesa_instruction *, this->next_temp * 4); + int *acp_level = rzalloc_array(mem_ctx, int, this->next_temp * 4); + int level = 0; foreach_iter(exec_list_iterator, iter, this->instructions) { ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get(); + assert(inst->dst_reg.file != PROGRAM_TEMPORARY + || inst->dst_reg.index < this->next_temp); + /* First, do any copy propagation possible into the src regs. */ for (int r = 0; r < 3; r++) { ir_to_mesa_instruction *first = NULL; @@ -2676,6 +2702,8 @@ ir_to_mesa_visitor::copy_propagate(void) break; } + assert(acp_level[acp_base + src_chan] <= level); + if (!first) { first = copy_chan; } else { @@ -2708,23 +2736,79 @@ ir_to_mesa_visitor::copy_propagate(void) switch (inst->op) { case OPCODE_BGNLOOP: case OPCODE_ENDLOOP: - case OPCODE_ELSE: - case OPCODE_ENDIF: /* End of a basic block, clear the ACP entirely. */ memset(acp, 0, sizeof(*acp) * this->next_temp * 4); break; + case OPCODE_IF: + ++level; + break; + + case OPCODE_ENDIF: + case OPCODE_ELSE: + /* Clear all channels written inside the block from the ACP, but + * leaving those that were not touched. + */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (!acp[4 * r + c]) + continue; + + if (acp_level[4 * r + c] >= level) + acp[4 * r + c] = NULL; + } + } + if (inst->op == OPCODE_ENDIF) + --level; + break; + default: /* Continuing the block, clear any written channels from * the ACP. */ - if (inst->dst_reg.file == PROGRAM_TEMPORARY) { - if (inst->dst_reg.reladdr) { - memset(acp, 0, sizeof(*acp) * this->next_temp * 4); - } else { - for (int i = 0; i < 4; i++) { - if (inst->dst_reg.writemask & (1 << i)) { - acp[4 * inst->dst_reg.index + i] = NULL; + if (inst->dst_reg.file == PROGRAM_TEMPORARY && inst->dst_reg.reladdr) { + /* Any temporary might be written, so no copy propagation + * across this instruction. + */ + memset(acp, 0, sizeof(*acp) * this->next_temp * 4); + } else if (inst->dst_reg.file == PROGRAM_OUTPUT && + inst->dst_reg.reladdr) { + /* Any output might be written, so no copy propagation + * from outputs across this instruction. + */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (!acp[4 * r + c]) + continue; + + if (acp[4 * r + c]->src_reg[0].file == PROGRAM_OUTPUT) + acp[4 * r + c] = NULL; + } + } + } else if (inst->dst_reg.file == PROGRAM_TEMPORARY || + inst->dst_reg.file == PROGRAM_OUTPUT) { + /* Clear where it's used as dst. */ + if (inst->dst_reg.file == PROGRAM_TEMPORARY) { + for (int c = 0; c < 4; c++) { + if (inst->dst_reg.writemask & (1 << c)) { + acp[4 * inst->dst_reg.index + c] = NULL; + } + } + } + + /* Clear where it's used as src. */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (!acp[4 * r + c]) + continue; + + int src_chan = GET_SWZ(acp[4 * r + c]->src_reg[0].swizzle, c); + + if (acp[4 * r + c]->src_reg[0].file == inst->dst_reg.file && + acp[4 * r + c]->src_reg[0].index == inst->dst_reg.index && + inst->dst_reg.writemask & (1 << src_chan)) + { + acp[4 * r + c] = NULL; } } } @@ -2742,12 +2826,14 @@ ir_to_mesa_visitor::copy_propagate(void) for (int i = 0; i < 4; i++) { if (inst->dst_reg.writemask & (1 << i)) { acp[4 * inst->dst_reg.index + i] = inst; + acp_level[4 * inst->dst_reg.index + i] = level; } } } } - talloc_free(acp); + ralloc_free(acp_level); + ralloc_free(acp); } @@ -2846,7 +2932,7 @@ get_mesa_program(struct gl_context *ctx, mesa_instructions = (struct prog_instruction *)calloc(num_instructions, sizeof(*mesa_instructions)); - mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *, + mesa_instruction_annotation = ralloc_array(v.mem_ctx, ir_instruction *, num_instructions); v.copy_propagate(); @@ -3103,7 +3189,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) _mesa_glsl_lexer_dtor(state); } - talloc_free(shader->ir); + ralloc_free(shader->ir); shader->ir = new(shader) exec_list; if (!state->error && !state->translation_unit.is_empty()) _mesa_ast_to_hir(shader->ir, state); @@ -3150,7 +3236,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader->ir); - talloc_free(state); + ralloc_free(state); if (shader->CompileStatus) { if (!ctx->Driver.CompileShader(ctx, shader)) diff --git a/src/mesa/program/register_allocate.c b/src/mesa/program/register_allocate.c index f984e2f1402..95a9bde401a 100644 --- a/src/mesa/program/register_allocate.c +++ b/src/mesa/program/register_allocate.c @@ -30,7 +30,7 @@ * Graph-coloring register allocator. */ -#include <talloc.h> +#include <ralloc.h> #include "main/imports.h" #include "main/macros.h" @@ -96,15 +96,15 @@ ra_alloc_reg_set(unsigned int count) unsigned int i; struct ra_regs *regs; - regs = talloc_zero(NULL, struct ra_regs); + regs = rzalloc(NULL, struct ra_regs); regs->count = count; - regs->regs = talloc_zero_array(regs, struct ra_reg, count); + regs->regs = rzalloc_array(regs, struct ra_reg, count); for (i = 0; i < count; i++) { - regs->regs[i].conflicts = talloc_zero_array(regs->regs, GLboolean, count); + regs->regs[i].conflicts = rzalloc_array(regs->regs, GLboolean, count); regs->regs[i].conflicts[i] = GL_TRUE; - regs->regs[i].conflict_list = talloc_array(regs->regs, unsigned int, 4); + regs->regs[i].conflict_list = ralloc_array(regs->regs, unsigned int, 4); regs->regs[i].conflict_list_size = 4; regs->regs[i].conflict_list[0] = i; regs->regs[i].num_conflicts = 1; @@ -120,10 +120,8 @@ ra_add_conflict_list(struct ra_regs *regs, unsigned int r1, unsigned int r2) if (reg1->conflict_list_size == reg1->num_conflicts) { reg1->conflict_list_size *= 2; - reg1->conflict_list = talloc_realloc(regs, - reg1->conflict_list, - unsigned int, - reg1->conflict_list_size); + reg1->conflict_list = reralloc(regs->regs, reg1->conflict_list, + unsigned int, reg1->conflict_list_size); } reg1->conflict_list[reg1->num_conflicts++] = r2; reg1->conflicts[r2] = GL_TRUE; @@ -143,14 +141,13 @@ ra_alloc_reg_class(struct ra_regs *regs) { struct ra_class *class; - regs->classes = talloc_realloc(regs, regs->classes, - struct ra_class *, - regs->class_count + 1); + regs->classes = reralloc(regs->regs, regs->classes, struct ra_class *, + regs->class_count + 1); - class = talloc_zero(regs, struct ra_class); + class = rzalloc(regs, struct ra_class); regs->classes[regs->class_count] = class; - class->regs = talloc_zero_array(class, GLboolean, regs->count); + class->regs = rzalloc_array(class, GLboolean, regs->count); return regs->class_count++; } @@ -174,7 +171,7 @@ ra_set_finalize(struct ra_regs *regs) unsigned int b, c; for (b = 0; b < regs->class_count; b++) { - regs->classes[b]->q = talloc_array(regs, unsigned int, regs->class_count); + regs->classes[b]->q = ralloc_array(regs, unsigned int, regs->class_count); } /* Compute, for each class B and C, how many regs of B an @@ -218,16 +215,16 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count) struct ra_graph *g; unsigned int i; - g = talloc_zero(regs, struct ra_graph); + g = rzalloc(regs, struct ra_graph); g->regs = regs; - g->nodes = talloc_zero_array(g, struct ra_node, count); + g->nodes = rzalloc_array(g, struct ra_node, count); g->count = count; - g->stack = talloc_zero_array(g, unsigned int, count); + g->stack = rzalloc_array(g, unsigned int, count); for (i = 0; i < count; i++) { - g->nodes[i].adjacency = talloc_zero_array(g, GLboolean, count); - g->nodes[i].adjacency_list = talloc_array(g, unsigned int, count); + g->nodes[i].adjacency = rzalloc_array(g, GLboolean, count); + g->nodes[i].adjacency_list = ralloc_array(g, unsigned int, count); g->nodes[i].adjacency_count = 0; ra_add_node_adjacency(g, i, i); g->nodes[i].reg = ~0; diff --git a/src/mesa/program/sampler.cpp b/src/mesa/program/sampler.cpp index 9a813c87955..1457d1199fa 100644 --- a/src/mesa/program/sampler.cpp +++ b/src/mesa/program/sampler.cpp @@ -23,7 +23,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include <cstdio> #include "ir.h" #include "glsl_types.h" #include "ir_visitor.h" @@ -40,7 +39,7 @@ static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) { va_list args; va_start(args, fmt); - prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); + ralloc_vasprintf_append(&prog->InfoLog, fmt, args); va_end(args); prog->LinkStatus = GL_FALSE; @@ -52,7 +51,7 @@ public: get_sampler_name(ir_dereference *last, struct gl_shader_program *shader_program) { - this->mem_ctx = talloc_new(NULL); + this->mem_ctx = ralloc_context(NULL); this->shader_program = shader_program; this->name = NULL; this->offset = 0; @@ -61,7 +60,7 @@ public: ~get_sampler_name() { - talloc_free(this->mem_ctx); + ralloc_free(this->mem_ctx); } virtual ir_visitor_status visit(ir_dereference_variable *ir) @@ -72,7 +71,7 @@ public: virtual ir_visitor_status visit_leave(ir_dereference_record *ir) { - this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field); + this->name = ralloc_asprintf(mem_ctx, "%s.%s", name, ir->field); return visit_continue; } @@ -91,16 +90,14 @@ public: * all that would work would be an unrolled loop counter that ends * up being constant above. */ - shader_program->InfoLog = - talloc_asprintf_append(shader_program->InfoLog, - "warning: Variable sampler array index " - "unsupported.\nThis feature of the language " - "was removed in GLSL 1.20 and is unlikely " - "to be supported for 1.10 in Mesa.\n"); + ralloc_strcat(&shader_program->InfoLog, + "warning: Variable sampler array index unsupported.\n" + "This feature of the language was removed in GLSL 1.20 " + "and is unlikely to be supported for 1.10 in Mesa.\n"); i = 0; } if (ir != last) { - this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i); + this->name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i); } else { offset = i; } diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c index 8a3609e569f..fb1c7a4efee 100644 --- a/src/mesa/state_tracker/st_atom_blend.c +++ b/src/mesa/state_tracker/st_atom_blend.c @@ -191,7 +191,7 @@ update_blend( struct st_context *st ) { struct pipe_blend_state *blend = &st->state.blend; unsigned num_state = 1; - unsigned i; + unsigned i, j; memset(blend, 0, sizeof(*blend)); @@ -214,12 +214,15 @@ update_blend( struct st_context *st ) } else if (st->ctx->Color.BlendEnabled) { /* blending enabled */ - for (i = 0; i < num_state; i++) { + for (i = 0, j = 0; i < num_state; i++) { blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1; + if (st->ctx->Extensions.ARB_draw_buffers_blend) + j = i; + blend->rt[i].rgb_func = - translate_blend(st->ctx->Color.Blend[i].EquationRGB); + translate_blend(st->ctx->Color.Blend[j].EquationRGB); if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN || st->ctx->Color.Blend[i].EquationRGB == GL_MAX) { @@ -229,13 +232,13 @@ update_blend( struct st_context *st ) } else { blend->rt[i].rgb_src_factor = - translate_blend(st->ctx->Color.Blend[i].SrcRGB); + translate_blend(st->ctx->Color.Blend[j].SrcRGB); blend->rt[i].rgb_dst_factor = - translate_blend(st->ctx->Color.Blend[i].DstRGB); + translate_blend(st->ctx->Color.Blend[j].DstRGB); } blend->rt[i].alpha_func = - translate_blend(st->ctx->Color.Blend[i].EquationA); + translate_blend(st->ctx->Color.Blend[j].EquationA); if (st->ctx->Color.Blend[i].EquationA == GL_MIN || st->ctx->Color.Blend[i].EquationA == GL_MAX) { @@ -245,9 +248,9 @@ update_blend( struct st_context *st ) } else { blend->rt[i].alpha_src_factor = - translate_blend(st->ctx->Color.Blend[i].SrcA); + translate_blend(st->ctx->Color.Blend[j].SrcA); blend->rt[i].alpha_dst_factor = - translate_blend(st->ctx->Color.Blend[i].DstA); + translate_blend(st->ctx->Color.Blend[j].DstA); } } } diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index 2843b7b1764..76386fe017a 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -39,7 +39,7 @@ #include "cso_cache/cso_context.h" #include "util/u_math.h" #include "util/u_inlines.h" - +#include "util/u_format.h" /** @@ -55,8 +55,10 @@ update_renderbuffer_surface(struct st_context *st, struct pipe_resource *resource = strb->rtt->pt; int rtt_width = strb->Base.Width; int rtt_height = strb->Base.Height; + enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format); if (!strb->surface || + strb->surface->format != format || strb->surface->texture != resource || strb->surface->width != rtt_width || strb->surface->height != rtt_height) { @@ -67,7 +69,7 @@ update_renderbuffer_surface(struct st_context *st, u_minify(resource->height0, level) == rtt_height) { struct pipe_surface surf_tmpl; memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = resource->format; + surf_tmpl.format = format; surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index 378b30e57cc..739a2eaab7e 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -99,7 +99,7 @@ create_color_map_texture(struct gl_context *ctx) /* create texture for color map/table */ pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0, - texSize, texSize, 1, PIPE_BIND_SAMPLER_VIEW); + texSize, texSize, 1, 1, PIPE_BIND_SAMPLER_VIEW); return pt; } diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index f92ca13d5e4..8bccceeec53 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -70,14 +70,16 @@ static void update_raster_state( struct st_context *st ) { raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW); - /* XXX - * I think the intention here is that user-created framebuffer objects - * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout. - * Flipping Y changes CW to CCW and vice-versa. - * But this is an implementation/driver-specific artifact - remove... + /* + * Gallium's surfaces are Y=0=TOP orientation. OpenGL is the + * opposite. Window system surfaces are Y=0=TOP. Mesa's FBOs + * must match OpenGL conventions so FBOs use Y=0=BOTTOM. In that + * case, we must invert Y and flip the notion of front vs. back. */ - if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { + /* Drawing to an FBO. The viewport will be inverted. */ raster->front_ccw ^= 1; + } } /* _NEW_LIGHT diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index b67068df373..474cbd5897d 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -36,6 +36,7 @@ #include "st_context.h" #include "st_cb_texture.h" +#include "st_format.h" #include "st_atom.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -117,49 +118,6 @@ gl_filter_to_img_filter(GLenum filter) } -static void -xlate_border_color(const GLfloat *colorIn, GLenum baseFormat, GLfloat *colorOut) -{ - switch (baseFormat) { - case GL_RED: - colorOut[0] = colorIn[0]; - colorOut[1] = 0.0F; - colorOut[2] = 0.0F; - colorOut[3] = 1.0F; - break; - case GL_RG: - colorOut[0] = colorIn[0]; - colorOut[1] = colorIn[1]; - colorOut[2] = 0.0F; - colorOut[3] = 1.0F; - break; - case GL_RGB: - colorOut[0] = colorIn[0]; - colorOut[1] = colorIn[1]; - colorOut[2] = colorIn[2]; - colorOut[3] = 1.0F; - break; - case GL_ALPHA: - colorOut[0] = colorOut[1] = colorOut[2] = 0.0; - colorOut[3] = colorIn[3]; - break; - case GL_LUMINANCE: - colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; - colorOut[3] = 1.0; - break; - case GL_LUMINANCE_ALPHA: - colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; - colorOut[3] = colorIn[3]; - break; - case GL_INTENSITY: - colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0]; - break; - default: - COPY_4V(colorOut, colorIn); - } -} - - static void update_samplers(struct st_context *st) { @@ -223,7 +181,7 @@ update_samplers(struct st_context *st) assert(sampler->min_lod <= sampler->max_lod); } - xlate_border_color(texobj->BorderColor.f, + st_translate_color(texobj->BorderColor.f, teximg ? teximg->_BaseFormat : GL_RGBA, sampler->border_color); diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c index d10f1840df6..133cc49eaf0 100644 --- a/src/mesa/state_tracker/st_atom_viewport.c +++ b/src/mesa/state_tracker/st_atom_viewport.c @@ -47,10 +47,14 @@ update_viewport( struct st_context *st ) /* _NEW_BUFFERS */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + /* Drawing to a window. The corresponding gallium surface uses + * Y=0=TOP but OpenGL is Y=0=BOTTOM. So we need to invert the viewport. + */ yScale = -1; yBias = (GLfloat)ctx->DrawBuffer->Height; } else { + /* Drawing to an FBO where Y=0=BOTTOM, like OpenGL - don't invert */ yScale = 1.0; yBias = 0.0; } diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index 35921f4f614..3e01c440bda 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -42,6 +42,7 @@ #include "st_texture.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_tile.h" @@ -146,7 +147,9 @@ accum_accum(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -183,7 +186,6 @@ accum_load(struct st_context *st, GLfloat value, GLubyte *data = acc_strb->data; GLfloat *buf; - if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -194,7 +196,9 @@ accum_load(struct st_context *st, GLfloat value, buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + util_format_linear(color_strb->texture->format), + buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -232,6 +236,7 @@ accum_return(struct gl_context *ctx, GLfloat value, size_t stride = acc_strb->stride; const GLubyte *data = acc_strb->data; GLfloat *buf; + enum pipe_format format = util_format_linear(color_strb->texture->format); if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -250,7 +255,8 @@ accum_return(struct gl_context *ctx, GLfloat value, width, height); if (usage & PIPE_TRANSFER_READ) - pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: @@ -279,7 +285,8 @@ accum_return(struct gl_context *ctx, GLfloat value, _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - pipe_put_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); + pipe_put_tile_rgba_format(pipe, color_trans, 0, 0, width, height, + format, buf); free(buf); pipe->transfer_destroy(pipe, color_trans); diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index e23fe86daeb..0ea5671557c 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -276,7 +276,7 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, * Create texture to hold bitmap pattern. */ pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format, - 0, width, height, 1, + 0, width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); if (!pt) { _mesa_unmap_pbo_source(ctx, unpack); @@ -349,6 +349,7 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, if (!st->bitmap.vbuf) { st->bitmap.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, max_slots * sizeof(st->bitmap.vertices)); } @@ -456,6 +457,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); /* rasterizer state: just scissor */ st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled; @@ -517,7 +519,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color); - util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset, + util_draw_vertex_buffer(pipe, st->cso_context, st->bitmap.vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 3); /* attribs/vert */ @@ -531,6 +533,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); } @@ -559,7 +562,7 @@ reset_cache(struct st_context *st) cache->texture = st_texture_create(st, PIPE_TEXTURE_2D, st->bitmap.tex_format, 0, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, - 1, + 1, 1, PIPE_BIND_SAMPLER_VIEW); } diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index d4d9af4ada3..12528f49ff7 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -171,7 +171,7 @@ st_bufferobj_data(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - unsigned buffer_usage; + unsigned bind, pipe_usage; st_obj->Base.Size = size; st_obj->Base.Usage = usage; @@ -179,22 +179,43 @@ st_bufferobj_data(struct gl_context *ctx, switch(target) { case GL_PIXEL_PACK_BUFFER_ARB: case GL_PIXEL_UNPACK_BUFFER_ARB: - buffer_usage = PIPE_BIND_RENDER_TARGET; + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; break; case GL_ARRAY_BUFFER_ARB: - buffer_usage = PIPE_BIND_VERTEX_BUFFER; + bind = PIPE_BIND_VERTEX_BUFFER; break; case GL_ELEMENT_ARRAY_BUFFER_ARB: - buffer_usage = PIPE_BIND_INDEX_BUFFER; + bind = PIPE_BIND_INDEX_BUFFER; break; default: - buffer_usage = 0; + bind = 0; + } + + switch (usage) { + case GL_STATIC_DRAW: + case GL_STATIC_READ: + case GL_STATIC_COPY: + pipe_usage = PIPE_USAGE_STATIC; + break; + case GL_DYNAMIC_DRAW: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + pipe_usage = PIPE_USAGE_DYNAMIC; + break; + case GL_STREAM_DRAW: + case GL_STREAM_READ: + case GL_STREAM_COPY: + pipe_usage = PIPE_USAGE_STREAM; + break; + default: + pipe_usage = PIPE_USAGE_DEFAULT; } pipe_resource_reference( &st_obj->buffer, NULL ); if (size != 0) { - st_obj->buffer = pipe_buffer_create(pipe->screen, buffer_usage, size); + st_obj->buffer = pipe_buffer_create(pipe->screen, bind, + pipe_usage, size); if (!st_obj->buffer) { return GL_FALSE; diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 6571bf237fb..0e0c4326ed7 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -42,6 +42,7 @@ #include "st_cb_accum.h" #include "st_cb_clear.h" #include "st_cb_fbo.h" +#include "st_format.h" #include "st_program.h" #include "pipe/p_context.h" @@ -138,6 +139,7 @@ draw_quad(struct st_context *st, if (!st->clear.vbuf) { st->clear.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, max_slots * sizeof(st->clear.vertices)); } @@ -172,7 +174,8 @@ draw_quad(struct st_context *st, st->clear.vertices); /* draw */ - util_draw_vertex_buffer(pipe, + util_draw_vertex_buffer(pipe, + st->cso_context, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), PIPE_PRIM_TRIANGLE_FAN, @@ -202,6 +205,7 @@ clear_with_quad(struct gl_context *ctx, const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; + float clearColor[4]; /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, @@ -221,6 +225,7 @@ clear_with_quad(struct gl_context *ctx, cso_save_fragment_shader(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); + cso_save_vertex_buffers(st->cso_context); /* blend state: RGBA masking */ { @@ -295,9 +300,14 @@ clear_with_quad(struct gl_context *ctx, cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); - /* draw quad matching scissor rect (XXX verify coord round-off) */ - draw_quad(st, x0, y0, x1, y1, - (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor); + if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { + st_translate_color(ctx->Color.ClearColor, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); + } + + /* draw quad matching scissor rect */ + draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, clearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); @@ -309,6 +319,7 @@ clear_with_quad(struct gl_context *ctx, cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); + cso_restore_vertex_buffers(st->cso_context); } @@ -537,12 +548,21 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) * required from the visual. Hence fix this up to avoid potential * read-modify-write in the driver. */ + float clearColor[4]; + if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) && ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && (depthRb == stencilRb) && (ctx->DrawBuffer->Visual.depthBits == 0 || ctx->DrawBuffer->Visual.stencilBits == 0)) clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + + if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { + st_translate_color(ctx->Color.ClearColor, + ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, + clearColor); + } + st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor, ctx->Depth.Clear, ctx->Stencil.Clear); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index d128ff98f02..c0da1696247 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -343,7 +343,7 @@ alloc_texture(struct st_context *st, GLsizei width, GLsizei height, struct pipe_resource *pt; pt = st_texture_create(st, st->internal_target, texFormat, 0, - width, height, 1, PIPE_BIND_SAMPLER_VIEW); + width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); return pt; } @@ -522,10 +522,11 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z, /* allocate/load buffer object with vertex data */ buf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, sizeof(verts)); pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts); - util_draw_vertex_buffer(pipe, buf, 0, + util_draw_vertex_buffer(pipe, st->cso_context, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ 3); /* attribs/vert */ @@ -570,6 +571,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); if (write_stencil) { cso_save_depth_stencil_alpha(cso); cso_save_blend(cso); @@ -686,6 +688,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); if (write_stencil) { cso_restore_depth_stencil_alpha(cso); cso_restore_blend(cso); @@ -1139,6 +1142,110 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, } +/** Do the src/dest regions overlap? */ +static GLboolean +regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY, + GLsizei width, GLsizei height) +{ + if (srcX + width <= dstX || + dstX + width <= srcX || + srcY + height <= dstY || + dstY + height <= srcY) + return GL_FALSE; + else + return GL_TRUE; +} + + +/** + * Try to do a glCopyPixels for simple cases with a blit by calling + * pipe->resource_copy_region(). + * + * We can do this when we're copying color pixels (depth/stencil + * eventually) with no pixel zoom, no pixel transfer ops, no + * per-fragment ops, the src/dest regions don't overlap and the + * src/dest pixel formats are the same. + */ +static GLboolean +blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, GLenum type) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct gl_pixelstore_attrib pack, unpack; + GLint readX, readY, readW, readH; + + if (type == GL_COLOR && + ctx->Pixel.ZoomX == 1.0 && + ctx->Pixel.ZoomY == 1.0 && + ctx->_ImageTransferState == 0x0 && + !ctx->Color.BlendEnabled && + !ctx->Color.AlphaEnabled && + !ctx->Depth.Test && + !ctx->Fog.Enabled && + !ctx->Stencil.Enabled && + !ctx->FragmentProgram.Enabled && + !ctx->VertexProgram.Enabled && + !ctx->Shader.CurrentFragmentProgram && + st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) && + ctx->DrawBuffer->_NumColorDrawBuffers == 1) { + struct st_renderbuffer *rbRead, *rbDraw; + GLint drawX, drawY; + + /* + * Clip the read region against the src buffer bounds. + * We'll still allocate a temporary buffer/texture for the original + * src region size but we'll only read the region which is on-screen. + * This may mean that we draw garbage pixels into the dest region, but + * that's expected. + */ + readX = srcx; + readY = srcy; + readW = width; + readH = height; + pack = ctx->DefaultPacking; + if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) + return GL_TRUE; /* all done */ + + /* clip against dest buffer bounds and scissor box */ + drawX = dstx + pack.SkipPixels; + drawY = dsty + pack.SkipRows; + unpack = pack; + if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack)) + return GL_TRUE; /* all done */ + + readX = readX - pack.SkipPixels + unpack.SkipPixels; + readY = readY - pack.SkipRows + unpack.SkipRows; + + rbRead = st_get_color_read_renderbuffer(ctx); + rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); + + if ((rbRead != rbDraw || + !regions_overlap(readX, readY, drawX, drawY, readW, readH)) && + rbRead->Base.Format == rbDraw->Base.Format) { + struct pipe_box srcBox; + + /* flip src/dst position if needed */ + if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + /* both buffers will have the same orientation */ + readY = ctx->ReadBuffer->Height - readY - readH; + drawY = ctx->DrawBuffer->Height - drawY - readH; + } + + u_box_2d(readX, readY, readW, readH, &srcBox); + + pipe->resource_copy_region(pipe, + rbDraw->texture, 0, drawX, drawY, 0, + rbRead->texture, 0, &srcBox); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + static void st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, @@ -1168,6 +1275,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, return; } + if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type)) + return; + + /* + * The subsequent code implements glCopyPixels by copying the source + * pixels into a temporary texture that's then applied to a textured quad. + * When we draw the textured quad, all the usual per-fragment operations + * are handled. + */ + + /* * Get vertex/fragment shaders */ @@ -1268,7 +1386,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, if (srcFormat == texFormat) { struct pipe_box src_box; u_box_2d(readX, readY, readW, readH, &src_box); - /* copy source framebuffer surface into mipmap/texture */ + /* copy source framebuffer surface into mipmap/texture */ pipe->resource_copy_region(pipe, pt, /* dest tex */ 0, @@ -1281,7 +1399,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = - pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, + pipe_get_transfer(st->pipe, rbRead->texture, + 0, 0, /* level, layer */ PIPE_TRANSFER_READ, readX, readY, readW, readH); struct pipe_transfer *ptTex; @@ -1302,15 +1421,19 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf); - pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows, - readW, readH, buf); + enum pipe_format readFormat, drawFormat; + readFormat = util_format_linear(rbRead->texture->format); + drawFormat = util_format_linear(pt->format); + pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH, + readFormat, buf); + pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows, + readW, readH, drawFormat, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf); pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, readW, readH, buf); free(buf); diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index b540a79331b..86ceb9d78b3 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -139,6 +139,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, /* create the vertex buffer */ vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, numAttribs * 4 * 4 * sizeof(GLfloat)); /* load vertex buffer */ @@ -230,6 +231,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_save_viewport(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); + cso_save_vertex_buffers(cso); { void *vs = lookup_shader(pipe, numAttribs, @@ -264,7 +266,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, } - util_draw_vertex_buffer(pipe, vbuffer, + util_draw_vertex_buffer(pipe, cso, vbuffer, 0, /* offset */ PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ @@ -277,6 +279,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_restore_viewport(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); + cso_restore_vertex_buffers(cso); } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 0c7641f8623..5eda2346c60 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -84,6 +84,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, strb->Base.Width = width; strb->Base.Height = height; strb->Base.Format = st_pipe_format_to_mesa_format(format); + strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); strb->Base.DataType = st_format_datatype(format); strb->defined = GL_FALSE; /* undefined contents now */ @@ -234,6 +235,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) strb->Base.ClassID = 0x4242; /* just a unique value */ strb->Base.NumSamples = samples; strb->Base.Format = st_pipe_format_to_mesa_format(format); + strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format); strb->Base.DataType = st_format_datatype(format); strb->format = format; strb->software = sw; @@ -390,7 +392,7 @@ st_render_texture(struct gl_context *ctx, /* new surface for rendering into the texture */ memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = strb->texture->format; + surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; @@ -448,11 +450,14 @@ st_finish_render_texture(struct gl_context *ctx, * Validate a renderbuffer attachment for a particular set of bindings. */ static GLboolean -st_validate_attachment(struct pipe_screen *screen, +st_validate_attachment(struct gl_context *ctx, + struct pipe_screen *screen, const struct gl_renderbuffer_attachment *att, unsigned bindings) { const struct st_texture_object *stObj = st_texture_object(att->Texture); + enum pipe_format format; + gl_format texFormat; /* Only validate texture attachments for now, since * st_renderbuffer_alloc_storage makes sure that @@ -464,7 +469,20 @@ st_validate_attachment(struct pipe_screen *screen, if (!stObj) return GL_FALSE; - return screen->is_format_supported(screen, stObj->pt->format, + format = stObj->pt->format; + texFormat = + stObj->base.Image[att->CubeMapFace][att->TextureLevel]->TexFormat; + + /* If the encoding is sRGB and sRGB rendering cannot be enabled, + * check for linear format support instead. + * Later when we create a surface, we change the format to a linear one. */ + if (!ctx->Const.sRGBCapable && + _mesa_get_format_color_encoding(texFormat) == GL_SRGB) { + const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat); + format = st_mesa_format_to_pipe_format(linearFormat); + } + + return screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, stObj->pt->nr_samples, bindings, 0); } @@ -528,20 +546,23 @@ st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) return; } - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, depth, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, stencil, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { - if (!st_validate_attachment(screen, + if (!st_validate_attachment(ctx, + screen, &fb->Attachment[BUFFER_COLOR0 + i], PIPE_BIND_RENDER_TARGET)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 0507be74578..4689a0032b7 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -41,6 +41,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_tile.h" @@ -336,6 +337,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h struct st_renderbuffer *strb; struct gl_pixelstore_attrib clippedPacking = *pack; struct pipe_transfer *trans; + enum pipe_format pformat; assert(ctx->ReadBuffer->Width > 0); @@ -421,6 +423,9 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h yStep = 1; } + /* possibly convert sRGB format to linear RGB format */ + pformat = util_format_linear(trans->resource->format); + if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -435,8 +440,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width, format, type); - if (trans->resource->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || - trans->resource->format == PIPE_FORMAT_Z24X8_UNORM) { + if (pformat == PIPE_FORMAT_Z24_UNORM_S8_USCALED || + pformat == PIPE_FORMAT_Z24X8_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -467,8 +472,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h } } } - else if (trans->resource->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM || - trans->resource->format == PIPE_FORMAT_X8Z24_UNORM) { + else if (pformat == PIPE_FORMAT_S8_USCALED_Z24_UNORM || + pformat == PIPE_FORMAT_X8Z24_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -494,7 +499,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h } } } - else if (trans->resource->format == PIPE_FORMAT_Z16_UNORM) { + else if (pformat == PIPE_FORMAT_Z16_UNORM) { for (i = 0; i < height; i++) { GLushort ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; @@ -509,7 +514,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h dst += dstStride; } } - else if (trans->resource->format == PIPE_FORMAT_Z32_UNORM) { + else if (pformat == PIPE_FORMAT_Z32_UNORM) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; @@ -528,7 +533,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h /* RGBA format */ /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { - pipe_get_tile_rgba(pipe, trans, 0, y, width, 1, df); + pipe_get_tile_rgba_format(pipe, trans, 0, y, width, 1, + pformat, df); y += yStep; df += dfStride; if (!dfStride) { diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 09a10ba5819..08c498b1491 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -74,19 +74,18 @@ gl_target_to_pipe(GLenum target) switch (target) { case GL_TEXTURE_1D: return PIPE_TEXTURE_1D; - case GL_TEXTURE_2D: return PIPE_TEXTURE_2D; - case GL_TEXTURE_RECTANGLE_NV: return PIPE_TEXTURE_RECT; - case GL_TEXTURE_3D: return PIPE_TEXTURE_3D; - case GL_TEXTURE_CUBE_MAP_ARB: return PIPE_TEXTURE_CUBE; - + case GL_TEXTURE_1D_ARRAY_EXT: + return PIPE_TEXTURE_1D_ARRAY; + case GL_TEXTURE_2D_ARRAY_EXT: + return PIPE_TEXTURE_2D_ARRAY; default: assert(0); return 0; @@ -261,6 +260,55 @@ get_texture_dims(GLenum target) /** + * Given the size of a mipmap image, try to compute the size of the level=0 + * mipmap image. + * + * Note that this isn't always accurate for odd-sized, non-POW textures. + * For example, if level=1 and width=40 then the level=0 width may be 80 or 81. + * + * \return GL_TRUE for success, GL_FALSE for failure + */ +static GLboolean +guess_base_level_size(GLenum target, + GLuint width, GLuint height, GLuint depth, GLuint level, + GLuint *width0, GLuint *height0, GLuint *depth0) +{ + const GLuint dims = get_texture_dims(target); + + assert(width >= 1); + assert(height >= 1); + assert(depth >= 1); + + if (level > 0) { + /* Depending on the image's size, we can't always make a guess here */ + if ((dims >= 1 && width == 1) || + (dims >= 2 && height == 1) || + (dims >= 3 && depth == 1)) { + /* we can't determine the image size at level=0 */ + return GL_FALSE; + } + + /* grow the image size until we hit level = 0 */ + while (level > 0) { + if (width > 1) + width <<= 1; + if (height > 1) + height <<= 1; + if (depth > 1) + depth <<= 1; + level--; + } + } + + *width0 = width; + *height0 = height; + *depth0 = depth; + + return GL_TRUE; +} + + +/** * Try to allocate a pipe_resource object for the given st_texture_object. * * We use the given st_texture_image as a clue to determine the size of the @@ -273,50 +321,27 @@ guess_and_alloc_texture(struct st_context *st, struct st_texture_object *stObj, const struct st_texture_image *stImage) { - const GLuint dims = get_texture_dims(stObj->base.Target); - GLuint level, lastLevel, width, height, depth; + GLuint lastLevel, width, height, depth; GLuint bindings; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; enum pipe_format fmt; DBG("%s\n", __FUNCTION__); assert(!stObj->pt); - level = stImage->level; - width = stImage->base.Width2; /* size w/out border */ - height = stImage->base.Height2; - depth = stImage->base.Depth2; - - assert(width > 0); - assert(height > 0); - assert(depth > 0); - - /* Depending on the image's size, we can't always make a guess here. - */ - if (level > 0) { - if ( (dims >= 1 && width == 1) || - (dims >= 2 && height == 1) || - (dims >= 3 && depth == 1) ) { - /* we can't determine the image size at level=0 */ - stObj->width0 = stObj->height0 = stObj->depth0 = 0; - /* this is not an out of memory error */ - return GL_TRUE; - } + if (!guess_base_level_size(stObj->base.Target, + stImage->base.Width2, + stImage->base.Height2, + stImage->base.Depth2, + stImage->level, + &width, &height, &depth)) { + /* we can't determine the image size at level=0 */ + stObj->width0 = stObj->height0 = stObj->depth0 = 0; + /* this is not an out of memory error */ + return GL_TRUE; } - /* grow the image size until we hit level = 0 */ - while (level > 0) { - if (width != 1) - width <<= 1; - if (height != 1) - height <<= 1; - if (depth != 1) - depth <<= 1; - level--; - } - - assert(level == 0); - /* At this point, (width x height x depth) is the expected size of * the level=0 mipmap image. */ @@ -353,13 +378,18 @@ guess_and_alloc_texture(struct st_context *st, bindings = default_bindings(st, fmt); + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, + width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), fmt, lastLevel, - width, - height, - depth, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); @@ -407,125 +437,6 @@ strip_texture_border(GLint border, /** - * Try to do texture compression via rendering. If the Gallium driver - * can render into a compressed surface this will allow us to do texture - * compression. - * \return GL_TRUE for success, GL_FALSE for failure - */ -static GLboolean -compress_with_blit(struct gl_context * ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, GLint depth, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_image *texImage) -{ - const GLuint dstImageOffsets[1] = {0}; - struct st_texture_image *stImage = st_texture_image(texImage); - struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; - gl_format mesa_format; - struct pipe_resource templ; - struct pipe_resource *src_tex; - struct pipe_sampler_view view_templ; - struct pipe_sampler_view *src_view; - struct pipe_surface *dst_surface, surf_tmpl; - struct pipe_transfer *tex_xfer; - void *map; - - if (!stImage->pt) { - /* XXX: Can this happen? Should we assert? */ - return GL_FALSE; - } - - /* get destination surface (in the compressed texture) */ - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = stImage->pt->format; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; - surf_tmpl.u.tex.level = stImage->level; - surf_tmpl.u.tex.first_layer = stImage->face; - surf_tmpl.u.tex.last_layer = stImage->face; - dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl); - if (!dst_surface) { - /* can't render into this format (or other problem) */ - return GL_FALSE; - } - - /* Choose format for the temporary RGBA texture image. - */ - mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type); - assert(mesa_format); - if (!mesa_format) - return GL_FALSE; - - /* Create the temporary source texture - */ - memset(&templ, 0, sizeof(templ)); - templ.target = st->internal_target; - templ.format = st_mesa_format_to_pipe_format(mesa_format); - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - templ.usage = PIPE_USAGE_DEFAULT; - templ.bind = PIPE_BIND_SAMPLER_VIEW; - src_tex = screen->resource_create(screen, &templ); - - if (!src_tex) - return GL_FALSE; - - /* Put user's tex data into the temporary texture - */ - tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex, - 0, 0, /* layer, level are zero */ - PIPE_TRANSFER_WRITE, - 0, 0, width, height); /* x, y, w, h */ - map = pipe_transfer_map(pipe, tex_xfer); - - _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, - map, /* dest ptr */ - 0, 0, 0, /* dest x/y/z offset */ - tex_xfer->stride, /* dest row stride (bytes) */ - dstImageOffsets, /* image offsets (for 3D only) */ - width, height, 1, /* size */ - format, type, /* source format/type */ - pixels, /* source data */ - unpack); /* source data packing */ - - pipe_transfer_unmap(pipe, tex_xfer); - pipe->transfer_destroy(pipe, tex_xfer); - - /* Create temporary sampler view */ - u_sampler_view_default_template(&view_templ, - src_tex, - src_tex->format); - src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ); - - - /* copy / compress image */ - util_blit_pixels_tex(st->blit, - src_view, /* sampler view (src) */ - 0, 0, /* src x0, y0 */ - width, height, /* src x1, y1 */ - dst_surface, /* pipe_surface (dst) */ - xoffset, yoffset, /* dst x0, y0 */ - xoffset + width, /* dst x1 */ - yoffset + height, /* dst y1 */ - 0.0, /* z */ - PIPE_TEX_MIPFILTER_NEAREST); - - pipe_surface_reference(&dst_surface, NULL); - pipe_resource_reference(&src_tex, NULL); - pipe_sampler_view_reference(&src_view, NULL); - - return GL_TRUE; -} - - -/** * Do glTexImage1/2/3D(). */ static void @@ -542,7 +453,6 @@ st_TexImage(struct gl_context * ctx, GLsizei imageSize, GLboolean compressed_src) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride = 0; @@ -669,22 +579,10 @@ st_TexImage(struct gl_context * ctx, pixels, unpack, "glTexImage"); } - /* See if we can do texture compression with a blit/render. - */ - if (!compressed_src && - !ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (!pixels) - goto done; - - if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth, - format, type, pixels, unpack, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* @@ -918,6 +816,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, else { /* format translation via floats */ GLuint row; + enum pipe_format format = util_format_linear(dst_texture->format); for (row = 0; row < height; row++) { const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ GLfloat rgba[4 * MAX_WIDTH]; @@ -928,7 +827,8 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, debug_printf("%s: fallback format translation\n", __FUNCTION__); /* get float[4] rgba row from surface */ - pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba); + pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1, + format, rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dest, &ctx->Pack, transferOps); @@ -1073,7 +973,6 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride; const GLuint srcImageStride = @@ -1093,20 +992,10 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, if (!pixels) return; - /* See if we can do texture compression with a blit/render. - */ - if (!ctx->Mesa_DXTn && - _mesa_is_format_compressed(texImage->TexFormat) && - screen->is_format_supported(screen, - stImage->pt->format, - stImage->pt->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { - if (compress_with_blit(ctx, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texImage)) { - goto done; - } + /* for a 1D array upload the image as a series of layer with height = 1 */ + if (target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; } /* Map buffer if necessary. Need to lock to prevent other contexts @@ -1387,7 +1276,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. */ - pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc); + pipe_get_tile_rgba_format(pipe, src_trans, 0, 0, width, height, + util_format_linear(strb->texture->format), + tempSrc); /* Store into texture memory. * Note that this does some special things such as pixel transfer @@ -1834,6 +1725,7 @@ st_finalize_texture(struct gl_context *ctx, GLuint face; struct st_texture_image *firstImage; enum pipe_format firstImageFormat; + GLuint ptWidth, ptHeight, ptDepth, ptLayers; if (stObj->base._Complete) { /* The texture is complete and we know exactly how many mipmap levels @@ -1867,6 +1759,24 @@ st_finalize_texture(struct gl_context *ctx, /* Find gallium format for the Mesa texture */ firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); + /* Find size of level=0 Gallium mipmap image, plus number of texture layers */ + { + GLuint width, height, depth; + if (!guess_base_level_size(stObj->base.Target, + firstImage->base.Width2, + firstImage->base.Height2, + firstImage->base.Depth2, + stObj->base.BaseLevel, + &width, &height, &depth)) { + width = stObj->width0; + height = stObj->height0; + depth = stObj->depth0; + } + /* convert GL dims to Gallium dims */ + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + } + /* If we already have a gallium texture, check that it matches the texture * object's format, target, size, num_levels, etc. */ @@ -1874,9 +1784,10 @@ st_finalize_texture(struct gl_context *ctx, if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) || stObj->pt->last_level < stObj->lastLevel || - stObj->pt->width0 != stObj->width0 || - stObj->pt->height0 != stObj->height0 || - stObj->pt->depth0 != stObj->depth0) + stObj->pt->width0 != ptWidth || + stObj->pt->height0 != ptHeight || + stObj->pt->depth0 != ptDepth || + stObj->pt->array_size != ptLayers) { /* The gallium texture does not match the Mesa texture so delete the * gallium texture now. We'll make a new one below. @@ -1896,9 +1807,10 @@ st_finalize_texture(struct gl_context *ctx, gl_target_to_pipe(stObj->base.Target), firstImageFormat, stObj->lastLevel, - stObj->width0, - stObj->height0, - stObj->depth0, + ptWidth, + ptHeight, + ptDepth, + ptLayers, bindings); if (!stObj->pt) { diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index c7f3949bf9e..7a19f35bbf5 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -178,7 +178,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(&funcs); - ctx = _mesa_create_context_for_api(api, visual, shareCtx, &funcs, NULL); + ctx = _mesa_create_context(api, 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. @@ -203,6 +203,11 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_drawpix(st); st_destroy_drawtex(st); + /* Unreference any user vertex buffers. */ + for (i = 0; i < st->num_user_vbs; i++) { + pipe_resource_reference(&st->user_vb[i], NULL); + } + for (i = 0; i < Elements(st->state.sampler_views); i++) { pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 64a8f790e22..77765f02379 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -185,6 +185,11 @@ struct st_context int force_msaa; void *winsys_drawable_handle; + + /* User vertex buffers. */ + struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS]; + unsigned user_vb_stride[PIPE_MAX_ATTRIBS]; + unsigned num_user_vbs; }; diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 8e1263fe84e..6530a06ade4 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -243,14 +243,13 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, static GLboolean is_interleaved_arrays(const struct st_vertex_program *vp, const struct st_vp_variant *vpv, - const struct gl_client_array **arrays, - GLboolean *userSpace) + const struct gl_client_array **arrays) { GLuint attr; const struct gl_buffer_object *firstBufObj = NULL; GLint firstStride = -1; - GLuint num_client_arrays = 0; const GLubyte *client_addr = NULL; + GLboolean user_memory; for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; @@ -259,16 +258,19 @@ is_interleaved_arrays(const struct st_vertex_program *vp, if (firstStride < 0) { firstStride = stride; + user_memory = !bufObj || !bufObj->Name; } else if (firstStride != stride) { return GL_FALSE; } - + if (!bufObj || !bufObj->Name) { - num_client_arrays++; /* Try to detect if the client-space arrays are * "close" to each other. */ + if (!user_memory) { + return GL_FALSE; + } if (!client_addr) { client_addr = arrays[mesaAttr]->Ptr; } @@ -278,6 +280,9 @@ is_interleaved_arrays(const struct st_vertex_program *vp, } } else if (!firstBufObj) { + if (user_memory) { + return GL_FALSE; + } firstBufObj = bufObj; } else if (bufObj != firstBufObj) { @@ -285,57 +290,11 @@ is_interleaved_arrays(const struct st_vertex_program *vp, } } - *userSpace = (num_client_arrays == vpv->num_inputs); - /* debug_printf("user space: %s (%d arrays, %d inputs)\n", - (int)*userSpace ? "Yes" : "No", num_client_arrays, vp->num_inputs); */ - return GL_TRUE; } /** - * Compute the memory range occupied by the arrays. - */ -static void -get_arrays_bounds(const struct st_vertex_program *vp, - const struct st_vp_variant *vpv, - const struct gl_client_array **arrays, - GLuint max_index, - const GLubyte **low, const GLubyte **high) -{ - const GLubyte *low_addr = NULL; - const GLubyte *high_addr = NULL; - GLuint attr; - - /* debug_printf("get_arrays_bounds: Handling %u attrs\n", vpv->num_inputs); */ - - for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const GLint stride = arrays[mesaAttr]->StrideB; - const GLubyte *start = arrays[mesaAttr]->Ptr; - const unsigned sz = (arrays[mesaAttr]->Size * - _mesa_sizeof_type(arrays[mesaAttr]->Type)); - const GLubyte *end = start + (max_index * stride) + sz; - - /* debug_printf("attr %u: stride %d size %u start %p end %p\n", - attr, stride, sz, start, end); */ - - if (attr == 0) { - low_addr = start; - high_addr = end; - } - else { - low_addr = MIN2(low_addr, start); - high_addr = MAX2(high_addr, end); - } - } - - *low = low_addr; - *high = high_addr; -} - - -/** * Set up for drawing interleaved arrays that all live in one VBO * or all live in user space. * \param vbuffer returns vertex buffer info @@ -346,15 +305,24 @@ setup_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, const struct st_vp_variant *vpv, const struct gl_client_array **arrays, - GLuint max_index, - GLboolean userSpace, struct pipe_vertex_buffer *vbuffer, - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned max_index) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; GLuint attr; - const GLubyte *offset0 = NULL; + const GLubyte *low_addr = NULL; + + /* Find the lowest address. */ + if(vpv->num_inputs) { + low_addr = arrays[vp->index_to_input[0]]->Ptr; + + for (attr = 1; attr < vpv->num_inputs; attr++) { + const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr; + low_addr = MIN2(low_addr, start); + } + } for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; @@ -362,40 +330,28 @@ setup_interleaved_attribs(struct gl_context *ctx, struct st_buffer_object *stobj = st_buffer_object(bufobj); GLsizei stride = arrays[mesaAttr]->StrideB; - /*printf("stobj %u = %p\n", attr, (void*)stobj);*/ - if (attr == 0) { - const GLubyte *low, *high; - - get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high); - /* debug_printf("buffer range: %p %p range %d max index %u\n", - low, high, high - low, max_index); */ - - offset0 = low; - if (userSpace) { + if (bufobj && bufobj->Name) { + vbuffer->buffer = NULL; + pipe_resource_reference(&vbuffer->buffer, stobj->buffer); + vbuffer->buffer_offset = pointer_to_offset(low_addr); + } else { vbuffer->buffer = - pipe_user_buffer_create(pipe->screen, (void *) low, high - low, + pipe_user_buffer_create(pipe->screen, (void*)low_addr, + stride * (max_index + 1), PIPE_BIND_VERTEX_BUFFER); vbuffer->buffer_offset = 0; - } - else { - vbuffer->buffer = NULL; - pipe_resource_reference(&vbuffer->buffer, stobj->buffer); - vbuffer->buffer_offset = pointer_to_offset(low); + + /* Track user vertex buffers. */ + pipe_resource_reference(&st->user_vb[0], vbuffer->buffer); + st->user_vb_stride[0] = stride; + st->num_user_vbs = 1; } vbuffer->stride = stride; /* in bytes */ - vbuffer->max_index = max_index; } - /* - if (arrays[mesaAttr]->InstanceDivisor) - vbuffer[attr].max_index = arrays[mesaAttr]->_MaxElement; - else - vbuffer[attr].max_index = max_index; - */ - velements[attr].src_offset = - (unsigned) (arrays[mesaAttr]->Ptr - offset0); + (unsigned) (arrays[mesaAttr]->Ptr - low_addr); velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; velements[attr].vertex_buffer_index = 0; velements[attr].src_format = @@ -419,10 +375,9 @@ setup_non_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, const struct st_vp_variant *vpv, const struct gl_client_array **arrays, - GLuint max_index, - GLboolean *userSpace, struct pipe_vertex_buffer vbuffer[], - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned max_index) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; @@ -433,8 +388,6 @@ setup_non_interleaved_attribs(struct gl_context *ctx, struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; GLsizei stride = arrays[mesaAttr]->StrideB; - *userSpace = GL_FALSE; - if (bufobj && bufobj->Name) { /* Attribute data is in a VBO. * Recall that for VBOs, the gl_client_array->Ptr field is @@ -442,37 +395,23 @@ setup_non_interleaved_attribs(struct gl_context *ctx, */ struct st_buffer_object *stobj = st_buffer_object(bufobj); assert(stobj->buffer); - /*printf("stobj %u = %p\n", attr, (void*) stobj);*/ vbuffer[attr].buffer = NULL; pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer); vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr); } else { - /* attribute data is in user-space memory, not a VBO */ - uint bytes; - /*printf("user-space array %d stride %d\n", attr, stride);*/ - - *userSpace = GL_TRUE; - /* wrap user data */ if (arrays[mesaAttr]->Ptr) { - /* user's vertex array */ - if (arrays[mesaAttr]->StrideB) { - bytes = arrays[mesaAttr]->StrideB * (max_index + 1); - } - else { - bytes = arrays[mesaAttr]->Size - * _mesa_sizeof_type(arrays[mesaAttr]->Type); - } vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, - (void *) arrays[mesaAttr]->Ptr, bytes, + (void *) arrays[mesaAttr]->Ptr, + stride * (max_index + 1), PIPE_BIND_VERTEX_BUFFER); } else { /* no array, use ctx->Current.Attrib[] value */ - bytes = sizeof(ctx->Current.Attrib[0]); + uint bytes = sizeof(ctx->Current.Attrib[0]); vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, (void *) ctx->Current.Attrib[mesaAttr], @@ -482,16 +421,15 @@ setup_non_interleaved_attribs(struct gl_context *ctx, } vbuffer[attr].buffer_offset = 0; - } - assert(velements[attr].src_offset <= 2048); /* 11-bit field */ + /* Track user vertex buffers. */ + pipe_resource_reference(&st->user_vb[attr], vbuffer->buffer); + st->user_vb_stride[attr] = stride; + st->num_user_vbs = MAX2(st->num_user_vbs, attr+1); + } /* common-case setup */ vbuffer[attr].stride = stride; /* in bytes */ - if (arrays[mesaAttr]->InstanceDivisor) - vbuffer[attr].max_index = arrays[mesaAttr]->_MaxElement; - else - vbuffer[attr].max_index = max_index; velements[attr].src_offset = 0; velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor; @@ -609,6 +547,62 @@ translate_prim(const struct gl_context *ctx, unsigned prim) } +static void +st_validate_varrays(struct gl_context *ctx, + const struct gl_client_array **arrays, + unsigned max_index) +{ + struct st_context *st = st_context(ctx); + const struct st_vertex_program *vp; + const struct st_vp_variant *vpv; + struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; + unsigned num_vbuffers, num_velements; + GLuint attr; + unsigned i; + + /* must get these after state validation! */ + vp = st->vp; + vpv = st->vp_variant; + + memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); + + /* Unreference any user vertex buffers. */ + for (i = 0; i < st->num_user_vbs; i++) { + pipe_resource_reference(&st->user_vb[i], NULL); + } + st->num_user_vbs = 0; + + /* + * Setup the vbuffer[] and velements[] arrays. + */ + if (is_interleaved_arrays(vp, vpv, arrays)) { + setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, velements, + max_index); + num_vbuffers = 1; + num_velements = vpv->num_inputs; + if (num_velements == 0) + num_vbuffers = 0; + } + else { + setup_non_interleaved_attribs(ctx, vp, vpv, arrays, + vbuffer, velements, max_index); + num_vbuffers = vpv->num_inputs; + num_velements = vpv->num_inputs; + } + + cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer); + cso_set_vertex_elements(st->cso_context, num_velements, velements); + + /* unreference buffers (frees wrapped user-space buffer objects) + * This is OK, because the pipe driver should reference buffers by itself + * in set_vertex_buffers. */ + for (attr = 0; attr < num_vbuffers; attr++) { + pipe_resource_reference(&vbuffer[attr].buffer, NULL); + assert(!vbuffer[attr].buffer); + } +} + /** * This function gets plugged into the VBO module and is called when @@ -627,90 +621,81 @@ st_draw_vbo(struct gl_context *ctx, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - const struct st_vertex_program *vp; - const struct st_vp_variant *vpv; - struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; - GLuint attr; - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; - unsigned num_vbuffers, num_velements; struct pipe_index_buffer ibuffer; - GLboolean userSpace = GL_FALSE; - GLboolean vertDataEdgeFlags; struct pipe_draw_info info; unsigned i; + GLboolean new_array = GL_TRUE; + /* Fix this (Bug 34378): + GLboolean new_array = + st->dirty.st && (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM)) != 0;*/ /* Mesa core state should have been validated already */ assert(ctx->NewState == 0x0); - /* Gallium probably doesn't want this in some cases. */ - if (!index_bounds_valid) - if (!vbo_all_varyings_in_vbos(arrays)) - vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + if (ib) { + /* Gallium probably doesn't want this in some cases. */ + if (!index_bounds_valid) + if (!vbo_all_varyings_in_vbos(arrays)) + vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + } else { + /* Get min/max index for non-indexed drawing. */ + min_index = ~0; + max_index = 0; + + for (i = 0; i < nr_prims; i++) { + min_index = MIN2(min_index, prims[i].start); + max_index = MAX2(max_index, prims[i].start + prims[i].count - 1); + } + } + + /* Validate state. */ + if (st->dirty.st) { + GLboolean vertDataEdgeFlags; - /* sanity check for pointer arithmetic below */ - assert(sizeof(arrays[0]->Ptr[0]) == 1); + /* sanity check for pointer arithmetic below */ + assert(sizeof(arrays[0]->Ptr[0]) == 1); - vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && - arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; - if (vertDataEdgeFlags != st->vertdata_edgeflags) { - st->vertdata_edgeflags = vertDataEdgeFlags; - st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; - } + vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && + arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; + if (vertDataEdgeFlags != st->vertdata_edgeflags) { + st->vertdata_edgeflags = vertDataEdgeFlags; + st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; + } - st_validate_state(st); + st_validate_state(st); - /* must get these after state validation! */ - vp = st->vp; - vpv = st->vp_variant; + if (new_array) { + st_validate_varrays(ctx, arrays, max_index); + } #if 0 - if (MESA_VERBOSE & VERBOSE_GLSL) { - check_uniforms(ctx); - } + if (MESA_VERBOSE & VERBOSE_GLSL) { + check_uniforms(ctx); + } #else - (void) check_uniforms; + (void) check_uniforms; #endif - - memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); - /* - * Setup the vbuffer[] and velements[] arrays. - */ - if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) { - /*printf("Draw interleaved\n");*/ - setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace, - vbuffer, velements); - num_vbuffers = 1; - num_velements = vpv->num_inputs; - if (num_velements == 0) - num_vbuffers = 0; - } - else { - /*printf("Draw non-interleaved\n");*/ - setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index, - &userSpace, vbuffer, velements); - num_vbuffers = vpv->num_inputs; - num_velements = vpv->num_inputs; } -#if 0 - { - GLuint i; - for (i = 0; i < num_vbuffers; i++) { - printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride); - printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index); - printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset); - printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer); - } - for (i = 0; i < num_velements; i++) { - printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index); - printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset); - printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format)); + /* Notify the driver that the content of user buffers may have been + * changed. */ + if (!new_array && st->num_user_vbs) { + for (i = 0; i < st->num_user_vbs; i++) { + if (st->user_vb[i]) { + unsigned stride = st->user_vb_stride[i]; + + if (stride) { + pipe->redefine_user_buffer(pipe, st->user_vb[i], + min_index * stride, + (max_index + 1 - min_index) * stride); + } else { + /* stride == 0 */ + pipe->redefine_user_buffer(pipe, st->user_vb[i], + 0, st->user_vb[i]->width0); + } + } } } -#endif - - pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); - cso_set_vertex_elements(st->cso_context, num_velements, velements); setup_index_buffer(ctx, ib, &ibuffer); pipe->set_index_buffer(pipe, &ibuffer); @@ -744,17 +729,6 @@ st_draw_vbo(struct gl_context *ctx, } pipe_resource_reference(&ibuffer.buffer, NULL); - - /* unreference buffers (frees wrapped user-space buffer objects) */ - for (attr = 0; attr < num_vbuffers; attr++) { - pipe_resource_reference(&vbuffer[attr].buffer, NULL); - assert(!vbuffer[attr].buffer); - } - - if (userSpace) - { - pipe->set_vertex_buffers(pipe, 0, NULL); - } } diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 4e76a050701..1e1220bfe52 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -179,7 +179,6 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* common-case setup */ vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */ - vbuffers[attr].max_index = max_index; velements[attr].instance_divisor = 0; velements[attr].vertex_buffer_index = attr; velements[attr].src_format = @@ -220,7 +219,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, break; default: assert(0); - return; + goto out_unref_vertex; } if (bufobj && bufobj->Name) { @@ -256,14 +255,6 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* * unmap vertex/index buffers */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (draw->pt.vertex_buffer[i].buffer) { - pipe_buffer_unmap(pipe, vb_transfer[i]); - pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL); - draw_set_mapped_vertex_buffer(draw, i, NULL); - } - } - if (ib) { draw_set_mapped_index_buffer(draw, NULL); draw_set_index_buffer(draw, NULL); @@ -272,6 +263,14 @@ st_feedback_draw_vbo(struct gl_context *ctx, pipe_buffer_unmap(pipe, ib_transfer); pipe_resource_reference(&ibuffer.buffer, NULL); } + + out_unref_vertex: + for (attr = 0; attr < vp->num_inputs; attr++) { + pipe_buffer_unmap(pipe, vb_transfer[attr]); + draw_set_mapped_vertex_buffer(draw, attr, NULL); + pipe_resource_reference(&vbuffers[attr].buffer, NULL); + } + draw_set_vertex_buffers(draw, 0, NULL); } #endif /* FEATURE_feedback || FEATURE_rastpos */ diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 974fd78d7c8..2f45f470334 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -260,6 +260,8 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_texture_lod_bias = GL_TRUE; ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; + if (ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2) + ctx->Extensions.EXT_texture_format_BGRA8888 = GL_TRUE; ctx->Extensions.APPLE_vertex_array_object = GL_TRUE; @@ -388,6 +390,15 @@ void st_init_extensions(struct st_context *st) PIPE_BIND_SAMPLER_VIEW, 0)) { ctx->Extensions.EXT_texture_sRGB = GL_TRUE; ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE; + if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET, 0) || + screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET, 0)) { + ctx->Extensions.EXT_framebuffer_sRGB = GL_TRUE; + ctx->Const.sRGBCapable = GL_TRUE; + } } if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, @@ -400,10 +411,7 @@ void st_init_extensions(struct st_context *st) if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0) && - (ctx->Mesa_DXTn || - screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET, 0))) { + ctx->Mesa_DXTn) { ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; ctx->Extensions.S3_s3tc = GL_TRUE; } @@ -418,6 +426,12 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.MESA_ycbcr_texture = GL_TRUE; } + /* GL_EXT_texture_array */ + if (screen->get_param(screen, PIPE_CAP_ARRAY_TEXTURES)) { + ctx->Extensions.EXT_texture_array = GL_TRUE; + ctx->Extensions.MESA_texture_array = GL_TRUE; + } + /* GL_ARB_framebuffer_object */ if (ctx->Extensions.EXT_packed_depth_stencil) { /* we support always support GL_EXT_framebuffer_blit */ diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c index 2e0a664dd01..577ee6189bd 100644 --- a/src/mesa/state_tracker/st_format.c +++ b/src/mesa/state_tracker/st_format.c @@ -113,12 +113,9 @@ st_format_datatype(enum pipe_format format) return GL_UNSIGNED_SHORT; } else { - /* compressed format? */ - assert(0); + /* probably a compressed format, unsupported anyway */ + return GL_NONE; } - - assert(0); - return GL_NONE; } @@ -511,6 +508,14 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); + case GL_BGRA: + if (screen->is_format_supported( screen, PIPE_FORMAT_B8G8R8A8_UNORM, + target, sample_count, bindings, + geom_flags )) + return PIPE_FORMAT_B8G8R8A8_UNORM; + return default_rgba_format( screen, target, sample_count, bindings, + geom_flags ); + case 3: case GL_RGB: case GL_RGB8: @@ -1032,7 +1037,8 @@ st_ChooseTextureFormat(struct gl_context *ctx, GLint internalFormat, boolean want_renderable = internalFormat == 3 || internalFormat == 4 || internalFormat == GL_RGB || internalFormat == GL_RGBA || - internalFormat == GL_RGB8 || internalFormat == GL_RGBA8; + internalFormat == GL_RGB8 || internalFormat == GL_RGBA8 || + internalFormat == GL_BGRA; return st_ChooseTextureFormat_renderable(ctx, internalFormat, format, type, want_renderable); @@ -1089,3 +1095,55 @@ st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2) return GL_FALSE; } + + + +/** + * This is used for translating texture border color and the clear + * color. For example, the clear color is interpreted according to + * the renderbuffer's base format. For example, if clearing a + * GL_LUMINANCE buffer, ClearColor[0] = luminance and ClearColor[1] = + * alpha. Similarly for texture border colors. + */ +void +st_translate_color(const GLfloat colorIn[4], GLenum baseFormat, + GLfloat colorOut[4]) +{ + switch (baseFormat) { + case GL_RED: + colorOut[0] = colorIn[0]; + colorOut[1] = 0.0F; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; + case GL_RG: + colorOut[0] = colorIn[0]; + colorOut[1] = colorIn[1]; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; + case GL_RGB: + colorOut[0] = colorIn[0]; + colorOut[1] = colorIn[1]; + colorOut[2] = colorIn[2]; + colorOut[3] = 1.0F; + break; + case GL_ALPHA: + colorOut[0] = colorOut[1] = colorOut[2] = 0.0; + colorOut[3] = colorIn[3]; + break; + case GL_LUMINANCE: + colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; + colorOut[3] = 1.0; + break; + case GL_LUMINANCE_ALPHA: + colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0]; + colorOut[3] = colorIn[3]; + break; + case GL_INTENSITY: + colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0]; + break; + default: + COPY_4V(colorOut, colorIn); + } +} diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h index fe195c1069b..0fb570f6ee4 100644 --- a/src/mesa/state_tracker/st_format.h +++ b/src/mesa/state_tracker/st_format.h @@ -77,4 +77,10 @@ st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type); extern GLboolean st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2); + +extern void +st_translate_color(const GLfloat colorIn[4], GLenum baseFormat, + GLfloat colorOut[4]); + + #endif /* ST_FORMAT_H */ diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index c5f6008a222..4bf68280839 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -105,13 +105,12 @@ st_render_mipmap(struct st_context *st, static void decompress_image(enum pipe_format format, const uint8_t *src, uint8_t *dst, - unsigned width, unsigned height) + unsigned width, unsigned height, unsigned src_stride) { const struct util_format_description *desc = util_format_description(format); const uint bw = util_format_get_blockwidth(format); const uint bh = util_format_get_blockheight(format); const uint dst_stride = 4 * MAX2(width, bw); - const uint src_stride = util_format_get_stride(format, width); desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); @@ -144,10 +143,9 @@ decompress_image(enum pipe_format format, static void compress_image(enum pipe_format format, const uint8_t *src, uint8_t *dst, - unsigned width, unsigned height) + unsigned width, unsigned height, unsigned dst_stride) { const struct util_format_description *desc = util_format_description(format); - const uint dst_stride = util_format_get_stride(format, width); const uint src_stride = 4 * width; desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); @@ -236,7 +234,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000); /* decompress the src image: srcData -> srcTemp */ - decompress_image(format, srcData, srcTemp, srcWidth, srcHeight); + decompress_image(format, srcData, srcTemp, srcWidth, srcHeight, srcTrans->stride); _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, @@ -248,7 +246,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, dstWidth2); /* stride in texels */ /* compress the new image: dstTemp -> dstData */ - compress_image(format, dstTemp, dstData, dstWidth, dstHeight); + compress_image(format, dstTemp, dstData, dstWidth, dstHeight, dstTrans->stride); free(srcTemp); free(dstTemp); @@ -338,6 +336,11 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, if (lastLevel == 0) return; + /* The texture isn't in a "complete" state yet so set the expected + * lastLevel here, since it won't get done in st_finalize_texture(). + */ + stObj->lastLevel = lastLevel; + if (pt->last_level < lastLevel) { /* The current gallium texture doesn't have space for all the * mipmap levels we need to generate. So allocate a new texture. @@ -352,13 +355,9 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, oldTex->width0, oldTex->height0, oldTex->depth0, + oldTex->array_size, oldTex->bind); - /* The texture isn't in a "complete" state yet so set the expected - * lastLevel here, since it won't get done in st_finalize_texture(). - */ - stObj->lastLevel = lastLevel; - /* This will copy the old texture's base image into the new texture * which we just allocated. */ @@ -367,8 +366,6 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, /* release the old tex (will likely be freed too) */ pipe_resource_reference(&oldTex, NULL); pipe_sampler_view_reference(&stObj->sampler_view, NULL); - - pt = stObj->pt; } else { /* Make sure that the base texture image data is present in the @@ -377,6 +374,8 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, st_finalize_texture(ctx, st->pipe, texObj); } + pt = stObj->pt; + assert(pt->last_level >= lastLevel); /* Try to generate the mipmap by rendering/texturing. If that fails, diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 179e5dc8392..5c8853cfadb 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -426,19 +426,13 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi) struct gl_config mode; gl_buffer_index idx; + if (!stfbi) + return NULL; + stfb = CALLOC_STRUCT(st_framebuffer); if (!stfb) return NULL; - /* for FBO-only context */ - if (!stfbi) { - struct gl_framebuffer *base = _mesa_get_incomplete_framebuffer(); - - stfb->Base = *base; - - return stfb; - } - st_visual_to_context_mode(stfbi->visual, &mode); _mesa_initialize_window_framebuffer(&stfb->Base, &mode); @@ -764,7 +758,8 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); } else { - ret = FALSE; + struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer(); + ret = _mesa_make_current(st->ctx, incomplete, incomplete); } st_framebuffer_reference(&stdraw, NULL); diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 42f1c2017f8..5c68fd78c30 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -286,6 +286,8 @@ translate_texture_target( GLuint textarget, case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D; case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE; case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT; + case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_1D_ARRAY; + case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY; default: debug_assert( 0 ); return TGSI_TEXTURE_1D; @@ -751,10 +753,12 @@ compile_instruction( /** * Emit the TGSI instructions to adjust the WPOS pixel center convention + * Basically, add (adjX, adjY) to the fragment position. */ static void emit_adjusted_wpos( struct st_translate *t, - const struct gl_program *program, GLfloat value) + const struct gl_program *program, + GLfloat adjX, GLfloat adjY) { struct ureg_program *ureg = t->ureg; struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg); @@ -764,7 +768,7 @@ emit_adjusted_wpos( struct st_translate *t, * The shader might also use gl_FragCoord.w and .z. */ ureg_ADD(ureg, wpos_temp, wpos_input, - ureg_imm4f(ureg, value, value, 0.0f, 0.0f)); + ureg_imm4f(ureg, adjX, adjY, 0.0f, 0.0f)); t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp); } @@ -848,9 +852,12 @@ emit_wpos(struct st_context *st, boolean invert = FALSE; if (fp->OriginUpperLeft) { + /* Fragment shader wants origin in upper-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) { + /* the driver supports upper-left origin */ } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) { + /* the driver supports lower-left origin, need to invert Y */ ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT); invert = TRUE; } @@ -858,28 +865,37 @@ emit_wpos(struct st_context *st, assert(0); } else { + /* Fragment shader wants origin in lower-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) + /* the driver supports lower-left origin */ ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT); else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) + /* the driver supports upper-left origin, need to invert Y */ invert = TRUE; else assert(0); } if (fp->PixelCenterInteger) { + /* Fragment shader wants pixel center integer */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) + /* the driver supports pixel center integer */ ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) - emit_adjusted_wpos(t, program, invert ? 0.5f : -0.5f); + /* the driver supports pixel center half integer, need to bias X,Y */ + emit_adjusted_wpos(t, program, 0.5f, invert ? 0.5f : -0.5f); else assert(0); } else { + /* Fragment shader wants pixel center half integer */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) { + /* the driver supports pixel center half integer */ } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { + /* the driver supports pixel center integer, need to bias X,Y */ ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - emit_adjusted_wpos(t, program, invert ? -0.5f : 0.5f); + emit_adjusted_wpos(t, program, 0.5f, invert ? -0.5f : 0.5f); } else assert(0); diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 7b32b46838a..fc1dfb3ef9e 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -108,6 +108,8 @@ delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv) { if (fpv->driver_shader) cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); + if (fpv->parameters) + _mesa_free_parameter_list(fpv->parameters); FREE(fpv); } @@ -404,6 +406,7 @@ st_translate_fragment_program(struct st_context *st, { struct pipe_context *pipe = st->pipe; struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); + GLboolean deleteFP = GL_FALSE; if (!variant) return NULL; @@ -413,17 +416,18 @@ st_translate_fragment_program(struct st_context *st, #if FEATURE_drawpix if (key->bitmap) { /* glBitmap drawing */ - struct gl_fragment_program *fp; + struct gl_fragment_program *fp; /* we free this temp program below */ st_make_bitmap_fragment_program(st, &stfp->Base, &fp, &variant->bitmap_sampler); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); stfp = st_fragment_program(fp); + deleteFP = GL_TRUE; } else if (key->drawpixels) { /* glDrawPixels drawing */ - struct gl_fragment_program *fp; + struct gl_fragment_program *fp; /* we free this temp program below */ if (key->drawpixels_z || key->drawpixels_stencil) { fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z, @@ -433,6 +437,7 @@ st_translate_fragment_program(struct st_context *st, /* RGBA */ st_make_drawpix_fragment_program(st, &stfp->Base, &fp); variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); + deleteFP = GL_TRUE; } stfp = st_fragment_program(fp); } @@ -630,6 +635,12 @@ st_translate_fragment_program(struct st_context *st, debug_printf("\n"); } + if (deleteFP) { + /* Free the temporary program made above */ + struct gl_fragment_program *fp = &stfp->Base; + _mesa_reference_fragprog(st->ctx, &fp, NULL); + } + return variant; } diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 155ea39f18c..1e0a8323ab8 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -59,6 +59,7 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, + GLuint layers, GLuint bind ) { struct pipe_resource pt, *newtex; @@ -68,6 +69,8 @@ st_texture_create(struct st_context *st, assert(width0 > 0); assert(height0 > 0); assert(depth0 > 0); + if (target == PIPE_TEXTURE_CUBE) + assert(layers == 6); DBG("%s target %s format %s last_level %d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), @@ -84,7 +87,7 @@ st_texture_create(struct st_context *st, pt.width0 = width0; pt.height0 = height0; pt.depth0 = depth0; - pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1); + pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : layers); pt.usage = PIPE_USAGE_DEFAULT; pt.bind = bind; pt.flags = 0; @@ -98,6 +101,72 @@ st_texture_create(struct st_context *st, /** + * In OpenGL the number of 1D array texture layers is the "height" and + * the number of 2D array texture layers is the "depth". In Gallium the + * number of layers in an array texture is a separate 'array_size' field. + * This function converts dimensions from the former to the later. + */ +void +st_gl_texture_dims_to_pipe_dims(GLenum texture, + GLuint widthIn, + GLuint heightIn, + GLuint depthIn, + GLuint *widthOut, + GLuint *heightOut, + GLuint *depthOut, + GLuint *layersOut) +{ + switch (texture) { + case GL_TEXTURE_1D: + assert(heightIn == 1); + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = 1; + *depthOut = 1; + *layersOut = 1; + break; + case GL_TEXTURE_1D_ARRAY: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = 1; + *depthOut = 1; + *layersOut = heightIn; + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = 1; + break; + case GL_TEXTURE_CUBE_MAP: + assert(depthIn == 1); + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = 6; + break; + case GL_TEXTURE_2D_ARRAY: + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = 1; + *layersOut = depthIn; + break; + default: + assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()"); + /* fall-through */ + case GL_TEXTURE_3D: + *widthOut = widthIn; + *heightOut = heightIn; + *depthOut = depthIn; + *layersOut = 1; + break; + } +} + + +/** * Check if a texture image can be pulled into a unified mipmap texture. */ GLboolean @@ -105,6 +174,8 @@ st_texture_match_image(const struct pipe_resource *pt, const struct gl_texture_image *image, GLuint face, GLuint level) { + GLuint ptWidth, ptHeight, ptDepth, ptLayers; + /* Images with borders are never pulled into mipmap textures. */ if (image->Border) @@ -115,12 +186,17 @@ st_texture_match_image(const struct pipe_resource *pt, if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format) return GL_FALSE; + st_gl_texture_dims_to_pipe_dims(image->TexObject->Target, + image->Width, image->Height, image->Depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + /* Test if this image's size matches what's expected in the * established texture. */ - if (image->Width != u_minify(pt->width0, level) || - image->Height != u_minify(pt->height0, level) || - image->Depth != u_minify(pt->depth0, level)) + if (ptWidth != u_minify(pt->width0, level) || + ptHeight != u_minify(pt->height0, level) || + ptDepth != u_minify(pt->depth0, level) || + ptLayers != pt->array_size) return GL_FALSE; return GL_TRUE; @@ -212,14 +288,20 @@ st_texture_image_data(struct st_context *st, GLuint src_row_stride, GLuint src_image_stride) { struct pipe_context *pipe = st->pipe; - GLuint depth = u_minify(dst->depth0, level); GLuint i; const GLubyte *srcUB = src; struct pipe_transfer *dst_transfer; + GLuint layers; + + if (dst->target == PIPE_TEXTURE_1D_ARRAY || + dst->target == PIPE_TEXTURE_2D_ARRAY) + layers = dst->array_size; + else + layers = u_minify(dst->depth0, level); DBG("%s\n", __FUNCTION__); - for (i = 0; i < depth; i++) { + for (i = 0; i < layers; i++) { dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i, PIPE_TRANSFER_WRITE, 0, 0, u_minify(dst->width0, level), diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index bca856d7142..d50c3c9af79 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -71,7 +71,10 @@ struct st_texture_object */ GLuint lastLevel; - /** The size of the level=0 mipmap image */ + /** The size of the level=0 mipmap image. + * Note that the number of 1D array layers will be in height0 and the + * number of 2D array layers will be in depth0, as in GL. + */ GLuint width0, height0, depth0; /* On validation any active images held in main memory or in other @@ -168,9 +171,20 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, + GLuint layers, GLuint tex_usage ); +extern void +st_gl_texture_dims_to_pipe_dims(GLenum texture, + GLuint widthIn, + GLuint heightIn, + GLuint depthIn, + GLuint *widthOut, + GLuint *heightOut, + GLuint *depthOut, + GLuint *layersOut); + /* Check if an image fits into an existing texture object. */ extern GLboolean diff --git a/src/mesa/swrast/s_trispan.h b/src/mesa/swrast/s_trispan.h deleted file mode 100644 index 15207e863e3..00000000000 --- a/src/mesa/swrast/s_trispan.h +++ /dev/null @@ -1,31 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#ifndef S_TRISPAN_H -#define S_TRISPAN_H - - -#endif /* S_TRISPAN_H */ diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index 858b8281da3..b1967e65417 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -125,6 +125,43 @@ convert_half_to_float(const struct gl_client_array *input, } } +/** + * \brief Convert fixed-point to floating-point. + * + * In OpenGL, a fixed-point number is a "signed 2's complement 16.16 scaled + * integer" (Table 2.2 of the OpenGL ES 2.0 spec). + * + * If the buffer has the \c normalized flag set, the formula + * \code normalize(x) := (2*x + 1) / (2^16 - 1) \endcode + * is used to map the fixed-point numbers into the range [-1, 1]. + */ +static void +convert_fixed_to_float(const struct gl_client_array *input, + const GLubyte *ptr, GLfloat *fptr, + GLuint count) +{ + GLuint i, j; + const GLint size = input->Size; + + if (input->Normalized) { + for (i = 0; i < count; ++i) { + const GLfixed *in = (GLfixed *) ptr; + for (j = 0; j < size; ++j) { + *fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1); + } + ptr += input->StrideB; + } + } else { + for (i = 0; i < count; ++i) { + const GLfixed *in = (GLfixed *) ptr; + for (j = 0; j < size; ++j) { + *fptr++ = in[j] / (GLfloat) (1 << 16); + } + ptr += input->StrideB; + } + } +} + /* Adjust pointer to point at first requested element, convert to * floating point, populate VB->AttribPtr[]. */ @@ -174,6 +211,9 @@ static void _tnl_import_array( struct gl_context *ctx, case GL_HALF_FLOAT: convert_half_to_float(input, ptr, fptr, count, sz); break; + case GL_FIXED: + convert_fixed_to_float(input, ptr, fptr, count); + break; default: assert(0); break; diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 37940efdc11..6834f3b5aa5 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -130,6 +130,8 @@ void vbo_use_buffer_objects(struct gl_context *ctx); void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func); +void vbo_check_buffers_are_unmapped(struct gl_context *ctx); + void GLAPIENTRY _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index d56c91cd094..1b0ed79473b 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -40,13 +40,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "vbo_attrib.h" +/** + * Max number of primitives (number of glBegin/End pairs) per VBO. + */ #define VBO_MAX_PRIM 64 -/* Wierd implementation stuff: + +/** + * Size of the VBO to use for glBegin/glVertex/glEnd-style rendering. */ #define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */ -#define VBO_MAX_ATTR_CODEGEN 16 -#define ERROR_ATTRIB 16 /** Current vertex program mode */ @@ -152,7 +155,6 @@ struct vbo_exec_context void vbo_exec_init( struct gl_context *ctx ); void vbo_exec_destroy( struct gl_context *ctx ); void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state ); -void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap ); void vbo_exec_BeginVertices( struct gl_context *ctx ); void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ); diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 03d6bb4aefe..2f9f3ec7c46 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -159,8 +159,7 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) exec->vtx.attrsz[i], exec->vtx.attrptr[i]); - if (memcmp(current, tmp, sizeof(tmp)) != 0) - { + if (memcmp(current, tmp, sizeof(tmp)) != 0) { memcpy(current, tmp, sizeof(tmp)); /* Given that we explicitly state size here, there is no need @@ -192,14 +191,18 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) } -static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) +/** + * Copy current vertex attribute values into the current vertex. + */ +static void +vbo_exec_copy_from_current(struct vbo_exec_context *exec) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLint i; - for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { - const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { + const GLfloat *current = (GLfloat *) vbo->currval[i].Ptr; switch (exec->vtx.attrsz[i]) { case 4: exec->vtx.attrptr[i][3] = current[3]; case 3: exec->vtx.attrptr[i][2] = current[2]; @@ -213,17 +216,21 @@ static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) /** * Flush existing data, set new attrib size, replay copied vertices. + * This is called when we transition from a small vertex attribute size + * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. + * We need to go back over the previous 2-component texcoords and insert + * zero and one values. */ -static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, - GLuint attr, - GLuint newsz ) +static void +vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, + GLuint attr, GLuint newSize ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); - GLint lastcount = exec->vtx.vert_count; + const GLint lastcount = exec->vtx.vert_count; GLfloat *old_attrptr[VBO_ATTRIB_MAX]; - GLuint old_vtx_size = exec->vtx.vertex_size; - GLuint oldsz = exec->vtx.attrsz[attr]; + const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ + const GLuint oldSize = exec->vtx.attrsz[attr]; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices @@ -239,7 +246,7 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); } - if (unlikely(oldsz)) { + if (unlikely(oldSize)) { /* Do a COPY_TO_CURRENT to ensure back-copying works for the * case when the attribute already exists in the vertex and is * having its size increased. @@ -251,21 +258,21 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, * begin/end so that they don't bloat the vertices. */ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && - !oldsz && lastcount > 8 && exec->vtx.vertex_size) { + !oldSize && lastcount > 8 && exec->vtx.vertex_size) { vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } /* Fix up sizes: */ - exec->vtx.attrsz[attr] = newsz; - exec->vtx.vertex_size += newsz - oldsz; + exec->vtx.attrsz[attr] = newSize; + exec->vtx.vertex_size += newSize - oldSize; exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / (exec->vtx.vertex_size * sizeof(GLfloat))); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; - if (unlikely(oldsz)) { + if (unlikely(oldSize)) { /* Size changed, recalculate all the attrptr[] values */ GLfloat *tmp = exec->vtx.vertex; @@ -283,11 +290,11 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, * values. */ vbo_exec_copy_from_current( exec ); - - } else { + } + else { /* Just have to append the new attribute at the end */ exec->vtx.attrptr[attr] = exec->vtx.vertex + - exec->vtx.vertex_size - newsz; + exec->vtx.vertex_size - newSize; } /* Replay stored vertices to translate them @@ -311,10 +318,10 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; if (j == attr) { - if (oldsz) { + if (oldSize) { GLfloat tmp[4]; - COPY_CLEAN_4V(tmp, oldsz, data + old_offset); - COPY_SZ_4V(dest + new_offset, newsz, tmp); + COPY_CLEAN_4V(tmp, oldSize, data + old_offset); + COPY_SZ_4V(dest + new_offset, newSize, tmp); } else { GLfloat *current = (GLfloat *)vbo->currval[j].Ptr; COPY_SZ_4V(dest + new_offset, sz, current); @@ -337,70 +344,82 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, } -static void vbo_exec_fixup_vertex( struct gl_context *ctx, - GLuint attr, GLuint sz ) +/** + * This is when a vertex attribute transitions to a different size. + * For example, we saw a bunch of glTexCoord2f() calls and now we got a + * glTexCoord4f() call. We promote the array from size=2 to size=4. + */ +static void +vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - int i; - if (sz > exec->vtx.attrsz[attr]) { + if (newSize > exec->vtx.attrsz[attr]) { /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. */ - vbo_exec_wrap_upgrade_vertex( exec, attr, sz ); + vbo_exec_wrap_upgrade_vertex( exec, attr, newSize ); } - else if (sz < exec->vtx.active_sz[attr]) { + else if (newSize < exec->vtx.active_sz[attr]) { static const GLfloat id[4] = { 0, 0, 0, 1 }; + GLuint i; /* New size is smaller - just need to fill in some * zeros. Don't need to flush or wrap. */ - for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++) + for (i = newSize; i <= exec->vtx.attrsz[attr]; i++) exec->vtx.attrptr[attr][i-1] = id[i-1]; } - exec->vtx.active_sz[attr] = sz; + exec->vtx.active_sz[attr] = newSize; /* Does setting NeedFlush belong here? Necessitates resetting * vtxfmt on each flush (otherwise flags won't get reset * afterwards). */ if (attr == 0) - exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; } -/* +/** + * This macro is used to implement all the glVertex, glColor, glTexCoord, + * glVertexAttrib, etc functions. */ -#define ATTR( A, N, V0, V1, V2, V3 ) \ -do { \ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ +#define ATTR( A, N, V0, V1, V2, V3 ) \ +do { \ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ \ - if (unlikely(!(exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ - ctx->Driver.BeginVertices( ctx ); \ + if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ + ctx->Driver.BeginVertices( ctx ); \ + \ if (unlikely(exec->vtx.active_sz[A] != N)) \ vbo_exec_fixup_vertex(ctx, A, N); \ \ - { \ - GLfloat *dest = exec->vtx.attrptr[A]; \ - if (N>0) dest[0] = V0; \ - if (N>1) dest[1] = V1; \ - if (N>2) dest[2] = V2; \ - if (N>3) dest[3] = V3; \ - } \ - \ - if ((A) == 0) { \ - GLuint i; \ - \ - for (i = 0; i < exec->vtx.vertex_size; i++) \ - exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ - \ + { \ + GLfloat *dest = exec->vtx.attrptr[A]; \ + if (N>0) dest[0] = V0; \ + if (N>1) dest[1] = V1; \ + if (N>2) dest[2] = V2; \ + if (N>3) dest[3] = V3; \ + } \ + \ + if ((A) == 0) { \ + /* This is a glVertex call */ \ + GLuint i; \ + \ + for (i = 0; i < exec->vtx.vertex_size; i++) \ + exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ + \ exec->vtx.buffer_ptr += exec->vtx.vertex_size; \ - exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ - \ - if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ - vbo_exec_vtx_wrap( exec ); \ - } \ + \ + /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \ + /* something to draw (not just updating a color or texcoord).*/ \ + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ + \ + if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + vbo_exec_vtx_wrap( exec ); \ + } \ } while (0) @@ -514,6 +533,24 @@ static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) /** + * Flush (draw) vertices. + * \param unmap - leave VBO unmapped after flushing? + */ +static void +vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap) +{ + if (exec->vtx.vert_count || unmap) { + vbo_exec_vtx_flush( exec, unmap ); + } + + if (exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); + reset_attrfv( exec ); + } +} + + +/** * Called via glBegin. */ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) @@ -539,7 +576,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) * begin/end pairs. */ if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) - vbo_exec_FlushVertices_internal( ctx, GL_FALSE ); + vbo_exec_FlushVertices_internal(exec, GL_FALSE); i = exec->vtx.prim_count++; exec->vtx.prim[i].mode = mode; @@ -825,7 +862,7 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) /* Hook our functions into the dispatch table. */ - _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { ASSERT(i < Elements(exec->vtx.attrsz)); @@ -894,32 +931,23 @@ void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); } -void vbo_exec_BeginVertices( struct gl_context *ctx ) -{ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (0) printf("%s\n", __FUNCTION__); - vbo_exec_vtx_map( exec ); - assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); - exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; -} - -void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap ) +/** + * Called upon first glVertex, glColor, glTexCoord, etc. + */ +void vbo_exec_BeginVertices( struct gl_context *ctx ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (exec->vtx.vert_count || unmap) { - vbo_exec_vtx_flush( exec, unmap ); - } + vbo_exec_vtx_map( exec ); - if (exec->vtx.vertex_size) { - vbo_exec_copy_to_current( exec ); - reset_attrfv( exec ); - } + assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; } /** + * Called via ctx->Driver.FlushVertices() * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT */ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) @@ -932,10 +960,8 @@ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) assert(exec->flush_call_depth == 1); #endif - if (0) printf("%s\n", __FUNCTION__); - - if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { - if (0) printf("%s - inside begin/end\n", __FUNCTION__); + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + /* We've had glBegin but not glEnd! */ #ifdef DEBUG exec->flush_call_depth--; assert(exec->flush_call_depth == 0); @@ -943,14 +969,12 @@ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) return; } - vbo_exec_FlushVertices_internal( ctx, GL_TRUE ); + /* Flush (draw), and make sure VBO is left unmapped when done */ + vbo_exec_FlushVertices_internal(exec, GL_TRUE); /* Need to do this to ensure BeginVertices gets called again: */ - if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) - exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; - - exec->ctx->Driver.NeedFlush &= ~flags; + ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags); #ifdef DEBUG exec->flush_call_depth--; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 80085c17c5c..457343a1a5c 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -39,6 +39,43 @@ /** + * All vertex buffers should be in an unmapped state when we're about + * to draw. This debug function checks that. + */ +static void +check_buffers_are_unmapped(const struct gl_client_array **inputs) +{ +#ifdef DEBUG + GLuint i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + if (inputs[i]) { + struct gl_buffer_object *obj = inputs[i]->BufferObj; + assert(!_mesa_bufferobj_mapped(obj)); + } + } +#endif +} + + +/** + * A debug function that may be called from other parts of Mesa as + * needed during debugging. + */ +void +vbo_check_buffers_are_unmapped(struct gl_context *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + /* check the current vertex arrays */ + check_buffers_are_unmapped(exec->array.inputs); + /* check the current glBegin/glVertex/glEnd-style VBO */ + assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj)); +} + + + +/** * Compute min and max elements by scanning the index buffer for * glDraw[Range]Elements() calls. * If primitive restart is enabled, we need to ignore restart @@ -502,8 +539,13 @@ recalculate_input_bindings(struct gl_context *ctx) static void bind_arrays(struct gl_context *ctx) { + if (!ctx->Array.RebindArrays) { + return; + } + bind_array_obj(ctx); recalculate_input_bindings(ctx); + ctx->Array.RebindArrays = GL_FALSE; } @@ -576,6 +618,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, if (primCount > 0) { /* draw one or two prims */ + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL, GL_TRUE, start, start + count - 1); } @@ -585,6 +628,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, prim[0].start = start; prim[0].count = count; + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL, GL_TRUE, start, start + count - 1); } @@ -790,6 +834,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, * for the latter case elsewhere. */ + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, index_bounds_valid, start, end ); } @@ -1106,6 +1151,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, prim[i].basevertex = 0; } + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib, GL_FALSE, ~0, ~0); } else { @@ -1130,6 +1176,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, else prim[0].basevertex = 0; + check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib, GL_FALSE, ~0, ~0); } diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 87f64310561..539658021e3 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -245,6 +245,7 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) arrays[attr]._MaxElement = count; /* ??? */ varying_inputs |= 1 << attr; + ctx->NewState |= _NEW_ARRAY; } } @@ -252,6 +253,9 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) } +/** + * Unmap the VBO. This is called before drawing. + */ static void vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) { @@ -284,6 +288,9 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) } +/** + * Map the vertex buffer to begin storing glVertex, glColor, etc data. + */ void vbo_exec_vtx_map( struct vbo_exec_context *exec ) { @@ -300,14 +307,12 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) if (!_mesa_is_bufferobj(exec->vtx.bufferobj)) return; - if (exec->vtx.buffer_map != NULL) { - assert(0); - exec->vtx.buffer_map = NULL; - exec->vtx.buffer_ptr = NULL; - } + assert(!exec->vtx.buffer_map); + assert(!exec->vtx.buffer_ptr); if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 && ctx->Driver.MapBufferRange) { + /* The VBO exists and there's room for more */ exec->vtx.buffer_map = (GLfloat *)ctx->Driver.MapBufferRange(ctx, target, @@ -320,6 +325,7 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) } if (!exec->vtx.buffer_map) { + /* Need to allocate a new VBO */ exec->vtx.buffer_used = 0; ctx->Driver.BufferData(ctx, target, @@ -348,9 +354,10 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) /** * Execute the buffer and save copied verts. + * \param keep_unmapped if true, leave the VBO unmapped when we're done. */ void -vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) +vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped) { if (0) vbo_exec_debug_verts( exec ); @@ -390,7 +397,7 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) /* If using a real VBO, get new storage -- unless asked not to. */ - if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) { + if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !keepUnmapped) { vbo_exec_vtx_map( exec ); } } @@ -398,14 +405,13 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) /* May have to unmap explicitly if we didn't draw: */ - if (unmap && + if (keepUnmapped && _mesa_is_bufferobj(exec->vtx.bufferobj) && exec->vtx.buffer_map) { vbo_exec_vtx_unmap( exec ); } - - if (unmap || exec->vtx.vertex_size == 0) + if (keepUnmapped || exec->vtx.vertex_size == 0) exec->vtx.max_vert = 0; else exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 4ee78e9e103..c8199544526 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -646,11 +646,11 @@ static void _save_reset_vertex( struct gl_context *ctx ) do { \ struct vbo_save_context *save = &vbo_context(ctx)->save; \ \ - if (save->active_sz[A] != N) \ + if (save->active_sz[A] != N) \ save_fixup_vertex(ctx, A, N); \ \ { \ - GLfloat *dest = save->attrptr[A]; \ + GLfloat *dest = save->attrptr[A]; \ if (N>0) dest[0] = V0; \ if (N>1) dest[1] = V1; \ if (N>2) dest[2] = V2; \ @@ -663,7 +663,7 @@ do { \ for (i = 0; i < save->vertex_size; i++) \ save->buffer_ptr[i] = save->vertex[i]; \ \ - save->buffer_ptr += save->vertex_size; \ + save->buffer_ptr += save->vertex_size; \ \ if (++save->vert_count >= save->max_vert) \ _save_wrap_filled_vertex( ctx ); \ diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index d0454bf6212..634a6d3f84b 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -202,6 +202,7 @@ static void vbo_bind_vertex_list(struct gl_context *ctx, buffer_offset += node->attrsz[src] * sizeof(GLfloat); varying_inputs |= 1<<attr; + ctx->NewState |= _NEW_ARRAY; } } diff --git a/src/mesa/x86-64/xform4.S b/src/mesa/x86-64/xform4.S index e52a6118c31..6141e434679 100644 --- a/src/mesa/x86-64/xform4.S +++ b/src/mesa/x86-64/xform4.S @@ -55,7 +55,7 @@ _mesa_x86_64_transform_points4_general: * rdx = source */ movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -138,7 +138,7 @@ _mesa_x86_64_transform_points4_3d: movaps 16(%rax), %xmm10 movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -199,7 +199,7 @@ p4_3d_done: _mesa_x86_64_transform_points4_identity: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -228,7 +228,7 @@ p4_identity_done: _mesa_3dnow_transform_points4_3d_no_rot: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -293,7 +293,7 @@ p4_3d_no_rot_done: _mesa_3dnow_transform_points4_perspective: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -360,7 +360,7 @@ p4_perspective_done: _mesa_3dnow_transform_points4_2d_no_rot: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ @@ -416,7 +416,7 @@ p4_2d_no_rot_done: _mesa_3dnow_transform_points4_2d: movl V4F_COUNT(%rdx), %ecx /* count */ - movzx V4F_STRIDE(%rdx), %eax /* stride */ + movzbl V4F_STRIDE(%rdx), %eax /* stride */ movl %ecx, V4F_COUNT(%rdi) /* set dest count */ movl $4, V4F_SIZE(%rdi) /* set dest size */ diff --git a/src/mesa/x86/read_rgba_span_x86.S b/src/mesa/x86/read_rgba_span_x86.S index 3886a510bbc..3be4515b114 100644 --- a/src/mesa/x86/read_rgba_span_x86.S +++ b/src/mesa/x86/read_rgba_span_x86.S @@ -77,7 +77,9 @@ */ .globl _generic_read_RGBA_span_BGRA8888_REV_MMX +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_BGRA8888_REV_MMX +#endif .type _generic_read_RGBA_span_BGRA8888_REV_MMX, @function _generic_read_RGBA_span_BGRA8888_REV_MMX: pushl %ebx @@ -172,7 +174,9 @@ _generic_read_RGBA_span_BGRA8888_REV_MMX: */ .globl _generic_read_RGBA_span_BGRA8888_REV_SSE +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_BGRA8888_REV_SSE +#endif .type _generic_read_RGBA_span_BGRA8888_REV_SSE, @function _generic_read_RGBA_span_BGRA8888_REV_SSE: pushl %esi @@ -335,7 +339,9 @@ _generic_read_RGBA_span_BGRA8888_REV_SSE: .text .globl _generic_read_RGBA_span_BGRA8888_REV_SSE2 +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_BGRA8888_REV_SSE2 +#endif .type _generic_read_RGBA_span_BGRA8888_REV_SSE2, @function _generic_read_RGBA_span_BGRA8888_REV_SSE2: pushl %esi @@ -494,7 +500,9 @@ _generic_read_RGBA_span_BGRA8888_REV_SSE2: .text .globl _generic_read_RGBA_span_RGB565_MMX +#ifndef USE_DRICORE .hidden _generic_read_RGBA_span_RGB565_MMX +#endif .type _generic_read_RGBA_span_RGB565_MMX, @function _generic_read_RGBA_span_RGB565_MMX: @@ -648,7 +656,7 @@ _generic_read_RGBA_span_RGB565_MMX: testl $0x01, %ecx je .L01 - movzxw (%eax), %ecx + movzwl (%eax), %ecx movd %ecx, %mm4 pshufw $0x00, %mm4, %mm0 |